ConvertColumnTransfer优化

This commit is contained in:
redkale
2024-06-04 11:05:38 +08:00
parent 9b22fc3f5d
commit 897eb97d46
14 changed files with 224 additions and 64 deletions

View File

@@ -29,6 +29,7 @@ import org.redkale.cluster.spi.ClusterModuleEngine;
import org.redkale.cluster.spi.HttpClusterRpcClient;
import org.redkale.cluster.spi.HttpLocalRpcClient;
import org.redkale.convert.Convert;
import org.redkale.convert.ConvertColumnTransfer;
import org.redkale.convert.bson.BsonFactory;
import org.redkale.convert.json.*;
import org.redkale.convert.proto.ProtobufFactory;
@@ -303,6 +304,10 @@ public final class Application {
"jsonconvert", Convert.class, JsonFactory.root().getConvert());
this.resourceFactory.register(
"protobufconvert", Convert.class, ProtobufFactory.root().getConvert());
Consumer<ConvertColumnTransfer> transferConsumer = resourceFactory::inject;
BsonFactory.root().registerTransferConsumer(transferConsumer);
JsonFactory.root().registerTransferConsumer(transferConsumer);
ProtobufFactory.root().registerTransferConsumer(transferConsumer);
// 系统内部模块组件
moduleEngines.add(this.sourceModule); // 放第一很多module依赖于source

View File

@@ -22,14 +22,17 @@ public final class ConvertColumnEntry {
private ConvertType convertType;
private ConvertColumnTransfer transfer;
public ConvertColumnEntry() {}
public ConvertColumnEntry(ConvertColumn column) {
public ConvertColumnEntry(ConvertColumn column, ConvertColumnTransfer transfer) {
if (column == null) return;
this.name = column.name();
this.index = column.index();
this.ignore = column.ignore();
this.convertType = column.type();
this.transfer = transfer;
}
public ConvertColumnEntry(String name) {
@@ -55,6 +58,19 @@ public final class ConvertColumnEntry {
this.convertType = convertType;
}
public ConvertColumnEntry(
String name, int index, boolean ignore, ConvertType convertType, ConvertColumnTransfer transfer) {
this.name = name;
this.index = index;
this.ignore = ignore;
this.convertType = convertType;
this.transfer = transfer;
}
public ConvertColumnTransfer transfer() {
return transfer;
}
public String name() {
return name == null ? "" : name;
}
@@ -89,7 +105,11 @@ public final class ConvertColumnEntry {
@Override
public String toString() {
return "ConvertColumnEntry{" + "index=" + index + ", name=" + name + ", ignore=" + ignore + ", convertType="
+ convertType + '}';
return "ConvertColumnEntry{"
+ "index=" + index
+ ", name=" + name
+ ", ignore=" + ignore
+ ", convertType=" + convertType
+ '}';
}
}

View File

@@ -7,10 +7,25 @@ package org.redkale.convert;
import org.redkale.util.Attribute;
/**
* 字段值转换器,常见于脱敏操作
*
* <p>详情见: https://redkale.org
*
* @author zhangjx
* @since 2.8.0
*
* @param <F> 字段类型
*/
public interface ConvertColumnTransfer<F> {
public <A> A transfer(Object obj, Attribute attribute, F value);
/**
* 字段值转换
*
* @param obj 父对象
* @param attribute 属性对象
* @param value 字段值
*
* @return Object
*/
public Object transfer(Object obj, Attribute attribute, F value);
}

View File

@@ -15,6 +15,7 @@ import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.*;
import org.redkale.annotation.ConstructorParameters;
@@ -59,6 +60,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
private final ConcurrentHashMap<AccessibleObject, ConvertColumnEntry> columnEntrys = new ConcurrentHashMap();
private final ConcurrentHashMap<Class, ConvertColumnTransfer> transfers = new ConcurrentHashMap();
private final Set<Class> skipIgnores = new HashSet();
final Set<String> ignoreMapColumns = new HashSet();
@@ -70,6 +73,8 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
private boolean skipAllIgnore = false;
private Consumer<ConvertColumnTransfer> transferConsumer;
protected ConvertFactory(ConvertFactory<R, W> parent, int features) {
this.features = features;
this.parent = parent;
@@ -445,7 +450,24 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return new ConvertColumnEntry(realName, true);
}
}
ConvertColumnEntry entry = new ConvertColumnEntry(ref);
ConvertColumnTransfer transfer = null;
Class<? extends ConvertColumnTransfer> transferClass = ref.tranfer();
if (transferClass != ConvertColumnTransfer.class) {
transfer = findTransfer(transferClass);
if (transfer == null) {
try {
transfer = transferClass.getConstructor().newInstance();
} catch (Exception e) {
throw new ConvertException(e);
}
Consumer<ConvertColumnTransfer> consumer = findTransferConsumer();
if (consumer != null) {
consumer.accept(transfer);
}
register((Class) transferClass, transfer);
}
}
ConvertColumnEntry entry = new ConvertColumnEntry(ref, transfer);
if (skipAllIgnore) {
entry.setIgnore(false);
return entry;
@@ -868,11 +890,27 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return child;
}
private Consumer<ConvertColumnTransfer> findTransferConsumer() {
if (transferConsumer != null) {
return transferConsumer;
}
return parent == null ? null : parent.findTransferConsumer();
}
private Class findEntityAlias(String name) {
Class clazz = entitys.get(name);
return parent == null ? clazz : parent.findEntityAlias(name);
}
/**
* 设置ConvertColumnTransfer初始化的处理函数
*
* @param consumer ConvertColumnTransfer处理函数
*/
public final void registerTransferConsumer(Consumer<ConvertColumnTransfer> consumer) {
this.transferConsumer = consumer;
}
/**
* 使所有类的所有被声明为ConvertColumn.ignore = true 的字段或方法变为ConvertColumn.ignore = false
*
@@ -922,9 +960,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
ignoreMapColumnLock.lock();
try {
if (ignore) {
for (String column : columns) {
ignoreMapColumns.add(column);
}
ignoreMapColumns.addAll(List.of(columns));
} else {
for (String column : columns) {
ignoreMapColumns.remove(column);
@@ -945,9 +981,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
ignoreMapColumnLock.lock();
try {
if (ignore) {
for (String column : columns) {
ignoreMapColumns.add(column);
}
ignoreMapColumns.addAll(columns);
} else {
for (String column : columns) {
ignoreMapColumns.remove(column);
@@ -1007,7 +1041,7 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return field == null || register(field, entry);
}
public final <E> boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
public final boolean register(final AccessibleObject field, final ConvertColumnEntry entry) {
if (field == null || entry == null) {
return false;
}
@@ -1048,11 +1082,23 @@ public abstract class ConvertFactory<R extends Reader, W extends Writer> {
return result;
}
public final <C extends ConvertColumnTransfer> ConvertColumnTransfer findTransfer(Class<C> type) {
ConvertColumnTransfer transfer = transfers.get(type);
if (transfer != null) {
return transfer;
}
return this.parent == null ? null : this.parent.findTransfer(type);
}
// ----------------------------------------------------------------------
public final <E> Encodeable<W, E> getAnyEncoder() {
return (Encodeable<W, E>) anyEncoder;
}
public final <C extends ConvertColumnTransfer> void register(final Class<C> clazz, final C transfer) {
transfers.put(Objects.requireNonNull(clazz), Objects.requireNonNull(transfer));
}
public final <E> void register(final Type clazz, final SimpledCoder<R, W, E> coder) {
decoders.put(clazz, coder);
encoders.put(clazz, coder);

View File

@@ -7,7 +7,6 @@ package org.redkale.convert;
import java.lang.reflect.*;
import org.redkale.annotation.Comment;
import org.redkale.persistence.Column;
import org.redkale.util.Attribute;
/**
@@ -45,20 +44,10 @@ public final class DeMember<R extends Reader, T, F> {
this.method = method;
if (field != null) {
Comment ct = field.getAnnotation(Comment.class);
if (ct == null) {
Column col = field.getAnnotation(Column.class);
this.comment = col == null ? "" : col.comment();
} else {
this.comment = ct.value();
}
this.comment = ct == null ? "" : ct.value();
} else if (method != null) {
Comment ct = method.getAnnotation(Comment.class);
if (ct == null) {
Column col = method.getAnnotation(Column.class);
this.comment = col == null ? "" : col.comment();
} else {
this.comment = ct.value();
}
this.comment = ct == null ? "" : ct.value();
} else {
this.comment = "";
}

View File

@@ -7,7 +7,6 @@ package org.redkale.convert;
import java.lang.reflect.*;
import org.redkale.annotation.Comment;
import org.redkale.persistence.Column;
import org.redkale.util.Attribute;
/**
@@ -42,17 +41,25 @@ public final class EnMember<W extends Writer, T, F> {
final Method method; // 对应类成员的Method也可能为null
final ConvertColumnTransfer transfer; // 一般为null
int index;
int position; // 从1开始
int tag; // 主要给protobuf使用
public EnMember(Attribute<T, F> attribute, Encodeable<W, F> encoder, Field field, Method method) {
public EnMember(
Attribute<T, F> attribute,
Encodeable<W, F> encoder,
Field field,
Method method,
ConvertColumnTransfer transfer) {
this.attribute = attribute;
this.encoder = encoder;
this.field = field;
this.method = method;
this.transfer = transfer;
Class t = attribute.type();
this.string = CharSequence.class.isAssignableFrom(t);
this.bool = t == Boolean.class || t == boolean.class;
@@ -60,20 +67,10 @@ public final class EnMember<W extends Writer, T, F> {
this.jsonFieldNameBytes = ('"' + attribute.field() + "\":").getBytes();
if (field != null) {
Comment ct = field.getAnnotation(Comment.class);
if (ct == null) {
Column col = field.getAnnotation(Column.class);
this.comment = col == null ? "" : col.comment();
} else {
this.comment = ct.value();
}
this.comment = ct == null ? "" : ct.value();
} else if (method != null) {
Comment ct = method.getAnnotation(Comment.class);
if (ct == null) {
Column col = method.getAnnotation(Column.class);
this.comment = col == null ? "" : col.comment();
} else {
this.comment = ct.value();
}
this.comment = ct == null ? "" : ct.value();
} else {
this.comment = "";
}
@@ -84,7 +81,8 @@ public final class EnMember<W extends Writer, T, F> {
final ConvertFactory factory, final Class<T> clazz, final String fieldname) {
try {
Field field = clazz.getDeclaredField(fieldname);
return new EnMember<>(Attribute.create(field), factory.loadEncoder(field.getGenericType()), field, null);
return new EnMember<>(
Attribute.create(field), factory.loadEncoder(field.getGenericType()), field, null, null);
} catch (Exception e) {
throw new ConvertException(e);
}
@@ -95,7 +93,7 @@ public final class EnMember<W extends Writer, T, F> {
try {
Field field = clazz.getDeclaredField(fieldname);
return new EnMember<>(
Attribute.create(clazz, fieldname, fieldtype), factory.loadEncoder(fieldtype), field, null);
Attribute.create(clazz, fieldname, fieldtype), factory.loadEncoder(fieldtype), field, null, null);
} catch (Exception e) {
throw new ConvertException(e);
}
@@ -103,11 +101,16 @@ public final class EnMember<W extends Writer, T, F> {
public static <W extends Writer, T, F> EnMember<W, T, F> create(
final Attribute<T, F> attribute, final ConvertFactory factory, final Class<F> fieldtype) {
return new EnMember<>(attribute, factory.loadEncoder(fieldtype), null, null);
return new EnMember<>(attribute, factory.loadEncoder(fieldtype), null, null, null);
}
public F getFieldValue(T obj) {
return attribute.get(obj);
public Object getFieldValue(T obj) {
F val = attribute.get(obj);
if (transfer != null) {
return transfer.transfer(obj, attribute, val);
} else {
return val;
}
}
public final boolean accepts(String name) {

View File

@@ -106,7 +106,11 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
fieldCoder = colFactory.loadEncoder(t);
}
EnMember member = new EnMember(
createAttribute(colFactory, type, clazz, field, null, null), fieldCoder, field, null);
createAttribute(colFactory, type, clazz, field, null, null),
fieldCoder,
field,
null,
ref == null ? null : ref.transfer());
if (ref != null) {
member.index = ref.getIndex();
}
@@ -189,7 +193,8 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
createAttribute(colFactory, type, clazz, null, method, null),
fieldCoder,
maybeField,
method);
method,
ref == null ? null : ref.transfer());
if (Utility.contains(list, m -> m.attribute.field().equals(member.attribute.field()))) {
continue;
}
@@ -214,7 +219,11 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
// Type t = TypeToken.createClassType(f.getGenericType(), this.type);
try {
EnMember member = new EnMember(
createAttribute(factory, type, clazz, f, null, null), null, f, null);
createAttribute(factory, type, clazz, f, null, null),
null,
f,
null,
ref2 == null ? null : ref2.transfer());
if (ref2 != null) {
member.index = ref2.getIndex();
}
@@ -238,7 +247,11 @@ public class ObjectEncoder<W extends Writer, T> implements Encodeable<W, T> {
// this.type), this.type);
try {
EnMember member = new EnMember(
createAttribute(factory, type, clazz, null, getter, null), null, null, null);
createAttribute(factory, type, clazz, null, getter, null),
null,
null,
null,
ref2 == null ? null : ref2.transfer());
if (ref2 != null) {
member.index = ref2.getIndex();
}

View File

@@ -5,13 +5,12 @@
*/
package org.redkale.convert.json;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import static org.redkale.asm.Opcodes.*;
import java.lang.reflect.*;
import java.lang.reflect.Type;
import java.util.*;
import org.redkale.asm.*;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import static org.redkale.asm.Opcodes.*;
import org.redkale.convert.*;
import org.redkale.convert.ext.*;
import org.redkale.util.*;
@@ -258,6 +257,9 @@ public abstract class JsonDynEncoder<T> implements Encodeable<JsonWriter, T> {
if (ref != null && ref.ignore()) {
continue;
}
if (ref != null && ref.transfer() != null) {
return null;
}
if (!(checkMemberType(factory, clazz, method.getGenericReturnType(), method.getReturnType()))) {
return null;
}

View File

@@ -0,0 +1,72 @@
/*
*/
package org.redkale.test.convert;
import org.junit.jupiter.api.*;
import org.redkale.convert.ConvertColumn;
import org.redkale.convert.ConvertColumnTransfer;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.Attribute;
/**
*
* @author zhangjx
*/
public class ConvertTransferTest {
public static void main(String[] args) throws Throwable {
ConvertTransferTest test = new ConvertTransferTest();
test.run1();
}
@Test
public void run1() throws Throwable {
ParamRequest param = new ParamRequest();
param.setName("haha");
param.setPhone("1381234500");
Assertions.assertEquals("{\"name\":\"haha\",\"phone\":\"138****00\"}", param.toString());
}
public static class ParamRequest {
private String name;
@ConvertColumn(tranfer = ParamTransfer.class)
private String phone;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
}
}
public static class ParamTransfer implements ConvertColumnTransfer<String> {
@Override
public Object transfer(Object obj, Attribute attribute, String value) {
if (value == null || value.length() < 5) {
return value;
} else {
return value.substring(0, 3) + "****" + value.substring(value.length() - 2);
}
}
}
}

View File

@@ -77,14 +77,14 @@ public class CustMessage2Test {
protected void afterInitEnMember(ConvertFactory factory) {
Function func1 = t -> eventName;
Attribute attribute1 = Attribute.create(clazz, "event", String.class, func1, null);
EnMember member1 = new EnMember(attribute1, factory.loadEncoder(String.class), null, null);
EnMember member1 = new EnMember(attribute1, factory.loadEncoder(String.class), null, null, null);
setIndex(member1, 1);
setPosition(member1, 1);
initForEachEnMember(factory, member1);
Function func2 = t -> t;
Attribute attribute2 = Attribute.create(clazz, "result", clazz, func2, null);
EnMember member2 = new EnMember(attribute2, valEncoder, null, null);
EnMember member2 = new EnMember(attribute2, valEncoder, null, null, null);
setIndex(member2, 2);
setPosition(member2, 2);
initForEachEnMember(factory, member2);

View File

@@ -2,10 +2,9 @@
*/
package org.redkale.test.convert;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import java.util.function.*;
import org.junit.jupiter.api.*;
import org.redkale.convert.*;
@@ -73,7 +72,7 @@ public class CustMessageTest {
protected void afterInitEnMember(ConvertFactory factory) {
Function func = t -> t;
Attribute attribute = Attribute.create(clazz, getMessageName(clazz), clazz, func, null);
EnMember member = new EnMember(attribute, valEncoder, null, null);
EnMember member = new EnMember(attribute, valEncoder, null, null, null);
setIndex(member, 1);
setPosition(member, 1);
initForEachEnMember(factory, member);

View File

@@ -97,14 +97,14 @@ public class PBCustMessage2Test {
protected void afterInitEnMember(ConvertFactory factory) {
Function func1 = t -> eventName;
Attribute attribute1 = Attribute.create(clazz, "event", String.class, func1, null);
EnMember member1 = new EnMember(attribute1, factory.loadEncoder(String.class), null, null);
EnMember member1 = new EnMember(attribute1, factory.loadEncoder(String.class), null, null, null);
setIndex(member1, 1);
setPosition(member1, 1);
initForEachEnMember(factory, member1);
Function func2 = t -> t;
Attribute attribute2 = Attribute.create(clazz, "data", clazz, func2, null);
EnMember member2 = new EnMember(attribute2, valEncoder, null, null);
EnMember member2 = new EnMember(attribute2, valEncoder, null, null, null);
setIndex(member2, 2);
setPosition(member2, 2);
initForEachEnMember(factory, member2);

View File

@@ -2,10 +2,9 @@
*/
package org.redkale.test.convert.proto;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import java.util.*;
import java.util.function.*;
import org.junit.jupiter.api.*;
@@ -84,7 +83,7 @@ public class PBCustMessageTest {
protected void afterInitEnMember(ConvertFactory factory) {
Function func = t -> t;
Attribute attribute = Attribute.create(clazz, getMessageName(clazz), clazz, func, null);
EnMember member = new EnMember(attribute, valEncoder, null, null);
EnMember member = new EnMember(attribute, valEncoder, null, null, null);
setIndex(member, 1);
setPosition(member, 1);
initForEachEnMember(factory, member);