前言
有些时候,我们可能对输出的某些字段要做特殊的处理在输出到前端,比如:身份证号,电话等信息,在前端展示的时候我们需要进行脱敏处理,这时候通过自定义注解就非常的有用了。在Jackson中要自定义注解,我们可以通过@JacksonAnnotationsInside注解来实现,如下示例:
一、自定义注解
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @JacksonAnnotationsInside @JsonSerialize(using = SensitiveSerializer.class) public @interface Sensitive {//加密开始位置int start()default 0 ;//加密结束位置int end() default 0 ;//加密掩码String mask() default "*" ; }
二、自定义序列化处理器SensitiveSerializer
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.BeanProperty; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.JsonSerializer; import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.ser.ContextualSerializer; import org.springframework.util.StringUtils; import java.io.IOException; import java.util.Collections;/*** @author songwp* @date 2024-11-15* @desc 自定义序列化器,用于对敏感字段进行脱敏处理*/ public class SensitiveSerializer extends JsonSerializer<String> implements ContextualSerializer {private Sensitive sensitive;@Overridepublic void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {String val = value;if (sensitive != null && StringUtils.hasLength(val)) {String m = sensitive.mask();int start = sensitive.start();int end = sensitive.end();int totalLength = value.length();if (totalLength <= 2) {val = totalLength == 1 ? value + m : value.substring(0, 1) + m;} else if (totalLength <= 6) {val = value.substring(0, 1) + String.join("", Collections.nCopies(totalLength - 2, m)) + value.substring(totalLength - 1);} else {int prefixLength = Math.min(start, totalLength - 1);int suffixLength = Math.min(end, totalLength - 1);if (prefixLength > totalLength) {prefixLength = totalLength / 2;}if (suffixLength > totalLength) {suffixLength = totalLength / 2;}int maskLength = Math.max(0, totalLength - (prefixLength + suffixLength));if (maskLength == 0) {prefixLength -= 2;suffixLength -= 2;maskLength = Math.max(2, totalLength - (prefixLength + suffixLength));}prefixLength = Math.min(prefixLength, totalLength - 1);suffixLength = Math.min(suffixLength, totalLength - 1);maskLength = totalLength - prefixLength - suffixLength;val = value.substring(0, prefixLength) + String.join("", Collections.nCopies(maskLength, m)) + value.substring(totalLength - suffixLength);}}gen.writeString(val);}@Overridepublic JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {sensitive = property.getAnnotation(Sensitive.class);return this;} }
三、在输出的Java Bean中使用上面的注解
import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.songwp.config.Sensitive; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable;/*** @author songwp* @version 1.0* @date 2024-11-15* @description: user domain*/ @Data @AllArgsConstructor @NoArgsConstructor public class User implements Serializable {@JsonSerialize(using = ToStringSerializer.class)private Long id;@Sensitive(start = 2, end = 4)private String name;@Sensitive(start = 6, end = 4)private String idCard;@Sensitive(start = 4, end = 3)private String phone; }
四、在前端展示结果如下:
敏感数据得到了脱敏处理。