实体转换器 EntityConverter
1、接口声明
package org.noear.solon.core.handle;
import org.noear.solon.core.wrap.MethodWrap;
import org.noear.solon.lang.Preview;
/**
* 实体转换器(预览,未启用)
*/
public interface EntityConverter {
/**
* 实例检测(移除时用)
*/
default boolean isInstance(Class<?> clz) {
return clz.isInstance(this);
}
/**
* 名字
*/
default String name() {
return this.getClass().getSimpleName();
}
/**
* 映射
*/
default String[] mappings() {
return null;
}
/**
* 是否允许写
*
*/
boolean allowWrite();
/**
* 是否能写
*/
boolean canWrite(String mime, Context ctx);
/**
* 写入并返回(渲染并返回(默认不实现))
*/
String writeAndReturn(Object data, Context ctx) throws Throwable;
/**
* 写入
*
* @param data 数据
* @param ctx 上下文
*/
void write(Object data, Context ctx) throws Throwable;
/**
* 是否允许读
*/
boolean allowRead();
/**
* 是否能读
*/
boolean canRead(Context ctx, String mime);
/**
* 读取(参数分析)
*
* @param ctx 上下文
* @param target 控制器
* @param mWrap 函数包装器
*/
Object[] read(Context ctx, Object target, MethodWrap mWrap) throws Throwable;
}
扩展虚拟类 AbstractEntityConverter:
public abstract class AbstractEntityConverter extends AbstractEntityReader implements EntityConverter {
@Override
public Object[] read(Context ctx, Object target, MethodWrap mWrap) throws Throwable {
return doRead(ctx, target, mWrap);
}
}
扩展虚拟类 AbstractBytesEntityConverter:
package org.noear.solon.serialization;
import org.noear.solon.core.handle.AbstractEntityConverter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.Assert;
import java.util.Base64;
/**
* 虚拟字节码实体转换器
*/
public abstract class AbstractBytesEntityConverter<T extends EntitySerializer<byte[]>> extends AbstractEntityConverter {
protected final T serializer;
public T getSerializer() {
return serializer;
}
public AbstractBytesEntityConverter(T serializer) {
Assert.notNull(serializer, "Serializer not be null");
this.serializer = serializer;
}
@Override
public boolean allowWrite() {
return true;
}
@Override
public boolean canWrite(String mime, Context ctx) {
return serializer.matched(ctx, mime);
}
@Override
public String writeAndReturn(Object data, Context ctx) throws Throwable {
byte[] tmp = serializer.serialize(data);
return Base64.getEncoder().encodeToString(tmp);
}
@Override
public void write(Object data, Context ctx) throws Throwable {
if (SerializationConfig.isOutputMeta()) {
ctx.headerAdd("solon.serialization", name());
}
serializer.serializeToBody(ctx, data);
}
@Override
public boolean allowRead() {
return true;
}
@Override
public boolean canRead(Context ctx, String mime) {
return serializer.matched(ctx, mime);
}
}
扩展虚拟类 AbstractStringEntityConverter :
package org.noear.solon.serialization;
import org.noear.solon.core.handle.AbstractEntityConverter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.Assert;
/**
* 虚拟字符串实体转换器
*/
public abstract class AbstractStringEntityConverter<T extends EntitySerializer<String>> extends AbstractEntityConverter {
protected final T serializer;
public T getSerializer() {
return serializer;
}
public AbstractStringEntityConverter(T serializer) {
Assert.notNull(serializer, "Serializer not be null");
this.serializer = serializer;
}
protected boolean isWriteType() {
return false;
}
@Override
public boolean allowWrite() {
return true;
}
@Override
public boolean canWrite(String mime, Context ctx) {
return serializer.matched(ctx, mime);
}
@Override
public String writeAndReturn(Object data, Context ctx) throws Throwable {
return serializer.serialize(data);
}
@Override
public void write(Object data, Context ctx) throws Throwable {
if (SerializationConfig.isOutputMeta()) {
ctx.headerAdd("solon.serialization", name());
}
String text = null;
if (isWriteType()) {
//序列化处理
//
text = serializer.serialize(data);
} else {
//非序列化处理
//
if (data == null) {
return;
}
if (data instanceof Throwable) {
throw (Throwable) data;
}
text = serializer.serialize(data);
}
ctx.attrSet("output", text);
doWrite(ctx, data, text);
}
/**
* 输出
*
* @param ctx 上下文
* @param data 数据(原)
* @param text 文源
*/
protected void doWrite(Context ctx, Object data, String text) {
if (data instanceof String && isWriteType() == false) {
ctx.output(text);
} else {
//如果没有设置过,用默认的 //如 ndjson,sse 或故意改变 mime(可由外部控制)
if (ctx.contentTypeNew() == null) {
ctx.contentType(serializer.mimeType());
}
ctx.output(text);
}
}
@Override
public boolean allowRead() {
return true;
}
@Override
public boolean canRead(Context ctx, String mime) {
return serializer.matched(ctx, mime);
}
}
2、定制参考1
package org.noear.solon.serialization.abc;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.LazyReference;
import org.noear.solon.core.wrap.MethodWrap;
import org.noear.solon.core.wrap.ParamWrap;
import org.noear.solon.serialization.AbstractBytesEntityConverter;
import org.noear.solon.serialization.SerializerNames;
/**
* Abc 实体转换器
*/
public class AbcEntityConverter extends AbstractBytesEntityConverter<AbcBytesSerializer> {
public AbcEntityConverter(AbcBytesSerializer serializer) {
super(serializer);
}
/**
* 后缀或名字映射
*/
@Override
public String[] mappings() {
return new String[]{SerializerNames.AT_ABC};
}
/**
* 转换 body
*
* @param ctx 请求上下文
* @param mWrap 函数包装器
*/
@Override
protected Object changeBody(Context ctx, MethodWrap mWrap) throws Exception {
return null;
}
/**
* 转换 value
*
* @param ctx 请求上下文
* @param p 参数包装器
* @param pi 参数序位
* @param pt 参数类型
* @param bodyRef 主体对象
*/
@Override
protected Object changeValue(Context ctx, ParamWrap p, int pi, Class<?> pt, LazyReference bodyRef) throws Throwable {
if (p.spec().isRequiredPath() || p.spec().isRequiredCookie() || p.spec().isRequiredHeader()) {
//如果是 path、cookie, header
return super.changeValue(ctx, p, pi, pt, bodyRef);
}
if (p.spec().isRequiredBody() == false && ctx.paramMap().containsKey(p.spec().getName())) {
//有可能是path、queryString变量
return super.changeValue(ctx, p, pi, pt, bodyRef);
}
if (p.spec().isRequiredBody()) {
return serializer.deserializeFromBody(ctx, p.getType());
} else {
return null;
}
}
}
3、定制参考1
package org.noear.solon.serialization.fastjson2;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.JSONWriter;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.util.LazyReference;
import org.noear.solon.core.wrap.MethodWrap;
import org.noear.solon.core.wrap.ParamWrap;
import org.noear.solon.serialization.AbstractStringEntityConverter;
import org.noear.solon.serialization.SerializerNames;
import java.util.Collection;
import java.util.List;
/**
* Fastjson2 实体转换器
*/
public class Fastjson2EntityConverter extends AbstractStringEntityConverter<Fastjson2StringSerializer> {
public Fastjson2EntityConverter(Fastjson2StringSerializer serializer) {
super(serializer);
serializer.getDeserializeConfig().addFeatures(JSONReader.Feature.ErrorOnEnumNotMatch);
serializer.getSerializeConfig().addFeatures(JSONWriter.Feature.BrowserCompatible);
}
/**
* 后缀或名字映射
*/
@Override
public String[] mappings() {
return new String[]{SerializerNames.AT_JSON};
}
/**
* 转换 body
*
* @param ctx 请求上下文
* @param mWrap 函数包装器
*/
@Override
protected Object changeBody(Context ctx, MethodWrap mWrap) throws Exception {
return serializer.deserializeFromBody(ctx);
}
/**
* 转换 value
*
* @param ctx 请求上下文
* @param p 参数包装器
* @param pi 参数序位
* @param pt 参数类型
* @param bodyRef 主体对象
*/
@Override
protected Object changeValue(Context ctx, ParamWrap p, int pi, Class<?> pt, LazyReference bodyRef) throws Throwable {
if (p.spec().isRequiredPath() || p.spec().isRequiredCookie() || p.spec().isRequiredHeader()) {
//如果是 path、cookie, header 变量
return super.changeValue(ctx, p, pi, pt, bodyRef);
}
if (p.spec().isRequiredBody() == false && ctx.paramMap().containsKey(p.spec().getName())) {
//可能是 path、queryString 变量
return super.changeValue(ctx, p, pi, pt, bodyRef);
}
Object bodyObj = bodyRef.get();
if (bodyObj == null) {
return super.changeValue(ctx, p, pi, pt, bodyRef);
}
if (bodyObj instanceof JSONObject) {
JSONObject tmp = (JSONObject) bodyObj;
if (p.spec().isRequiredBody() == false) {
//
//如果没有 body 要求;尝试找按属性找
//
if (tmp.containsKey(p.spec().getName())) {
//支持泛型的转换
if (p.spec().isGenericType()) {
return tmp.getObject(p.spec().getName(), p.getGenericType());
} else {
return tmp.getObject(p.spec().getName(), pt);
}
}
}
//尝试 body 转换
if (pt.isPrimitive() || pt.getTypeName().startsWith("java.lang.")) {
return super.changeValue(ctx, p, pi, pt, bodyRef);
} else {
if (List.class.isAssignableFrom(pt)) {
return null;
}
if (pt.isArray()) {
return null;
}
//支持泛型的转换 如:Map<T>
if (p.spec().isGenericType()) {
return tmp.to(p.getGenericType());
} else {
return tmp.to(pt);
}
}
}
if (bodyObj instanceof JSONArray) {
JSONArray tmp = (JSONArray) bodyObj;
//如果参数是非集合类型
if (!Collection.class.isAssignableFrom(pt)) {
return null;
}
//集合类型转换
if (p.spec().isGenericType()) {
//转换带泛型的集合
return tmp.to(p.getGenericType());
} else {
//不仅可以转换为List 还可以转换成Set
return tmp.to(pt);
}
}
return bodyObj;
}
}