基于SpringBoot,对于Restful接口适应,内部使用了ObjectMapper的序列化机制。
自定义数据注解
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataMasking {
/**
* 脱敏函数
*
* @return 默认为非脱敏
*/
DataMaskingFunc maskFunc() default DataMaskingFunc.NO_MASK;
}
自定义Serializer
- DataMaskingFunc
public enum DataMaskingFunc {
/**
* 不脱敏
*/
NO_MASK((str, maskChar) -> {
return str;
}),
/**
* 全脱敏
*/
ALL_MASK((str, maskChar) -> {
if (StringUtils.hasLength(str)) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
sb.append(StringUtils.hasLength(maskChar) ? maskChar : DataMaskingOperation.MASK_CHAR);
}
return sb.toString();
} else {
return str;
}
});
/**
* 内置的操作
*/
private final DataMaskingOperation operation;
/**
* 私有构造
*
* @param operation 脱敏操作
*/
DataMaskingFunc(DataMaskingOperation operation) {
this.operation = operation;
}
/**
* 获取脱敏操作函数
*
* @return 脱敏操作函数
*/
public DataMaskingOperation operation() {
return this.operation;
}
}
- DataMaskingOperation
public interface DataMaskingOperation {
/**
* 脱敏字符串
*/
String MASK_CHAR = "*";
/**
* 执行脱敏操作
*
* @param content 待脱敏内容
* @param maskChar 脱敏字符串
* @return 脱敏后的字符串
*/
String mask(String content, String maskChar);
}
- DataMaskingSerializer
public class DataMaskingSerializer extends StdScalarSerializer<Object> {
/**
* 数据脱敏操作
*/
private final DataMaskingOperation operation;
/**
* 默认构造
*/
public DataMaskingSerializer() {
super(String.class, false);
this.operation = null;
}
/**
* 基于已有的脱敏操作构造
*
* @param operation 脱敏操作
*/
public DataMaskingSerializer(DataMaskingOperation operation) {
super(String.class, false);
this.operation = operation;
}
@Override
public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
String content;
if (Objects.isNull(operation)) {
content = DataMaskingFunc.ALL_MASK.operation().mask((String) o, null);
} else {
content = operation.mask((String) o, null);
}
jsonGenerator.writeString(content);
}
public boolean isEmpty(SerializerProvider prov, Object value) {
String str = (String) value;
return str.isEmpty();
}
public final void serializeWithType(Object value, JsonGenerator gen, SerializerProvider provider, TypeSerializer typeSer) throws IOException {
this.serialize(value, gen, provider);
}
public JsonNode getSchema(SerializerProvider provider, Type typeHint) {
return this.createSchemaNode("string", true);
}
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) throws JsonMappingException {
this.visitStringFormat(visitor, typeHint);
}
}
自定义AnnotationIntrospector
public class DataMaskingAnnotationIntrospector extends NopAnnotationIntrospector {
public Object findSerializer(Annotated annotated) {
DataMasking annotation = annotated.getAnnotation(DataMasking.class);
if (annotation != null) {
return new DataMaskingSerializer(annotation.maskFunc().operation());
}
return null;
}
}
覆盖ObjectMapper
@Configuration(proxyBeanMethods = false)
public class DataMaskConfiguration {
/**
* Object Mapper实例
*
* @param builder 构建器
* @return 构建器
*/
@Bean
@Primary
ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {
ObjectMapper objectMapper = builder.createXmlMapper(false).build();
AnnotationIntrospector ai = objectMapper.getSerializationConfig().getAnnotationIntrospector();
AnnotationIntrospector newAi = AnnotationIntrospectorPair.pair(ai, new DataMaskingAnnotationIntrospector());
objectMapper.setAnnotationIntrospector(newAi);
return objectMapper;
}
/**
* 在Jackson2ObjectMapperBuilder存在时引入默认配置
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({Jackson2ObjectMapperBuilder.class})
static class JacksonObjectMapperConfiguration {
JacksonObjectMapperConfiguration() {
}
}
}