0、原理
通过创建bean,实现自定义的json转换Jackson2ObjectMapperBuilder
通过此对象去serializers转换,内部通过继承StdSerializer泛化接口,实现定制的序列化操作
1、定义注解
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DesensitizedIdCard {
}
2、定义脱敏序列化
import static java.util.stream.Collectors.toMap;
/**
* 脱敏序列化
*/
public class DesensitizeSerialize extends StdSerializer<Desensitized> {
public static Map<Class, DesensitizeService> mapper = new HashMap<>();
static {
mapper.put(DesensitizedIdCard.class,new DesensitizeServiceIdCardImpl());
mapper.put(DesensitizedName.class,new DesensitizeServiceNameImpl());
mapper.put(DesensitizedTel.class,new DesensitizeServiceTelImpl());
}
protected DesensitizeSerialize() {
super(Desensitized.class);
}
/**
* 定制序列化
*/
@Override
public void serialize(Desensitized bean, JsonGenerator gen, SerializerProvider provider) throws IOException {
//处理序列化
Map<String, Object> properties = beanProperties(bean);
gen.writeStartObject();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
gen.writeObjectField(entry.getKey(), entry.getValue());
}
gen.writeEndObject();
}
/**
* 解析对象属性
*
* @param bean
* @return
*/
private Map<String, Object> beanProperties(Object bean) {
try {
return Arrays.stream(Introspector.getBeanInfo(bean.getClass(), Object.class).getPropertyDescriptors())
.filter(descriptor -> Objects.nonNull(descriptor.getReadMethod()))
.flatMap(descriptor -> {
String name = descriptor.getName();
Method getter = descriptor.getReadMethod();
Object value = ReflectionUtils.invokeMethod(getter, bean);
if (null == value) {
//null不进行转化
return null;
}
DesensitizeService desensitizeService = getDesensitizer(bean, descriptor.getName());
if (null != desensitizeService) {
value = desensitizeService.option(String.valueOf(value));
}
Property originalProperty = new Property(name, value);
return Stream.of(originalProperty);
})
.collect(toMap(Property::getName, Property::getValue));
} catch (Exception e) {
return Collections.emptyMap();
}
}
/**
* 根据属性获取Annotation
*/
private Annotation[] getAnnotations(Object bean, String property) {
try {
Field field = bean.getClass().getDeclaredField(property);
return field.getAnnotations();
} catch (NoSuchFieldException e) {
return new Annotation[]{};
}
}
private DesensitizeService getDesensitizer(Object bean, String property) {
Annotation[] annotations = getAnnotations(bean, property);
DesensitizeService desensitizer = null;
for (Annotation ano : annotations) {
desensitizer = mapper.get(ano.annotationType());
if (null != desensitizer) {
break;
}
}
return desensitizer;
}
/**
* 属性对应值
*/
private class Property {
private String name;
private Object value;
public Property(String name, Object value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public Object getValue() {
return value;
}
}
}
3、定义脱敏接口
public interface DesensitizeService {
String NULL = "null";
String option(String value);
}
4、脱敏实现类
/**
* 身份证脱敏
* 规则:显示最后四位,其他隐藏。共计18位或者15位,比如:*************1234,容错处理:处理内容为空,返回原值
*/
public class DesensitizeServiceIdCardImpl implements DesensitizeService {
@Override
public String option(String idCard) {
if (StringUtils.isBlank(idCard) || NULL.equals(idCard)) {
return idCard;
}
String num = StringUtils.right(idCard, 4);
return StringUtils.leftPad(num, StringUtils.length(idCard), "*");
}
}
5、定义脱敏对外提供的接口,(哪个类需要脱敏直接实现后加入对应注解即可)
public interface Desensitized {
}
6、配置扩展脱敏
@Slf4j
@Configuration
public class DesensitizeConfiguration {
@Bean
@ConditionalOnMissingBean
public Jackson2ObjectMapperBuilder mapperBuilder() {
log.debug("desensitize Configuration 脱敏配置");
Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder = new Jackson2ObjectMapperBuilder();
jackson2ObjectMapperBuilder.serializers(new DesensitizeSerialize());
return jackson2ObjectMapperBuilder;
}
}
7、实例
@Getter
@Setter
@ToString
public class TestDTO implements Serializable, Desensitized {
private String id;
private String type;
private String pic;
@DesensitizedName
private String name;
@DesensitizedIdCard
private String idCard;
@DesensitizedTel
private String tel;
}