推荐使用jackson自定义serializer实现字段级脱敏:定义@sensitive注解和sensitivetype枚举,通过sensitivemodule全局注册脱敏逻辑,结合sensitiveutils统一处理各类敏感信息,避免aop方案。

自定义脱敏注解定义
先定义一个运行时保留的注解,用于标记需要脱敏的字段:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Sensitive {
SensitiveType value() default SensitiveType.DEFAULT;
}
再定义脱敏类型枚举,便于扩展不同脱敏策略(如手机号、身份证、邮箱等):
public enum SensitiveType {
PHONE, ID_CARD, EMAIL, BANK_CARD, DEFAULT
}
实现 JSON 序列化时的脱敏逻辑
推荐使用 Jackson,通过自定义 Serializer 实现字段级脱敏,比 AOP 切面更精准、高效且与序列化生命周期契合。
定义一个 SensitiveSerializer:
public class SensitiveSerializer extends JsonSerializer
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value == null) {
gen.writeNull();
return;
}
// 获取当前序列化字段上的 @Sensitive 注解(需配合 BeanPropertyWriter 传递上下文)
// 更稳妥做法:在序列化前通过反射或上下文获取注解信息 → 推荐用 JsonSerializer 的子类 + @JsonSerialize 注解绑定到字段
更实用的方式是:为每个字段显式指定序列化器(适合少量关键字段),或全局注册模块处理所有带 @Sensitive 的 String 字段:
- 创建
SensitiveModule继承SimpleModule - 重写
setupModule,遍历所有 Bean 属性,若发现字段有@Sensitive,则替换其序列化器为SensitiveSerializer - 在
SensitiveSerializer中,通过context.getAttribute("sensitiveType")或构造时传入类型,调用对应脱敏方法
脱敏工具类封装
统一管理脱敏规则,例如:
public class SensitiveUtils {
public static String desensitize(String original, SensitiveType type) {
if (original == null || original.isEmpty()) return original;
return switch (type) {
case PHONE -> maskPhone(original);
case ID_CARD -> maskIdCard(original);
case EMAIL -> maskEmail(original);
default -> maskDefault(original);
};
}
private static String maskPhone(String phone) {
return phone.replaceAll("(\d{3})\d{4}(\d{4})", "$1****$2");
}
// 其他脱敏方法略
}
集成到 Spring Boot 项目
在配置类中注册 Jackson 模块:
@Configuration
public class JacksonConfig {
@Bean
@Primary
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SensitiveModule());
return mapper;
}
}
实体类中直接使用:
public class User {
private String name;
@Sensitive(SensitiveType.PHONE)
private String phone;
@Sensitive(SensitiveType.ID_CARD)
private String idCard;
// getter/setter
}
返回 JSON 时,phone 和 idCard 自动脱敏,无需额外切面或手动处理。
不建议用 AOP 在 Controller 返回前修改 JSON 字符串 —— 易出错、难维护、破坏序列化职责边界。Jackson 原生支持注解驱动的序列化定制,才是标准、稳定、可测试的方案。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











