注解使用
大约 5 分钟
1. 了解
注解的了解
注解(Annotation)是一种元数据,它提供了关于程序代码其他部分的信息。在Java等编程语言中,注解是在源代码中加入的特殊标记,用于提供给编译器、解释器或其他工具一些额外的信息。注解通常以@
符号开始,后跟注解的名称。
注解的作用包括但不限于:
- 提供程序的额外信息: 注解可以用于提供关于类、方法、字段等元素的额外信息,这些信息可以被其他程序或工具利用。例如,
@Deprecated
注解可以标记一个方法或类已被废弃,建议不再使用。 - 编译时检查: 注解可以在编译时进行检查,帮助开发者发现潜在的错误或问题。例如,通过
@Override
注解,编译器可以检查方法是否正确地重写了父类中的方法。 - 运行时处理: 注解也可以在运行时被读取和处理,使得程序可以根据注解的信息动态地执行特定的操作。例如,Spring框架中的
@Autowired
注解可以用于自动装配依赖项。 - 生成文档: 注解可以用于生成文档,使得文档更加详细和准确。例如,Java中的
@author
注解可以用于指定作者信息,在生成文档时会自动生成相应的作者信息。 - 简化配置: 注解可以简化配置过程,减少重复性的代码。例如,Spring框架中的
@Component
注解可以用于将类标记为组件,从而无需在XML配置文件中进行显式配置。
总的来说,注解为程序提供了一种灵活且强大的机制,可以帮助开发者在编写、编译和运行程序时更加方便、高效地使用和管理信息。
2. 使用场景
简化通用代码,包括入参验证和出参脱敏,以减少重复工作。
使用场景
- 配置和依赖注入: 使用注解可以简化配置和依赖注入的过程。例如,在Spring框架中,可以使用
@Autowired
注解来自动装配依赖项,而不需要显式配置。 - 持久化框架: 在ORM(对象关系映射)框架中,注解可以用于映射实体类和数据库表之间的关系。例如,使用JPA(Java Persistence API)中的注解来定义实体类和表之间的映射关系。
- Web开发: 在Web开发中,注解可以用于定义请求处理器、URL映射、参数绑定等。例如,Spring MVC框架中的
@Controller
、@RequestMapping
等注解可以用于定义控制器和请求处理方法。 - 测试框架: 注解可以用于标记测试用例、测试方法、测试数据等。例如,JUnit中的
@Test
注解用于标记测试方法。 - 配置管理: 注解可以用于配置管理,例如定义配置文件的位置、属性的默认值等。例如,Spring框架中的
@PropertySource
注解可以用于指定属性文件的位置。 - 安全控制: 注解可以用于安全控制,例如定义权限、角色等。例如,Spring Security框架中的注解可以用于定义访问控制规则。
- 日志记录: 注解可以用于记录日志,例如标记需要记录日志的方法或类。例如,使用AspectJ中的注解来定义切点和通知,实现日志记录功能。
- 性能监控: 注解可以用于性能监控,例如标记需要监控性能的方法或类。例如,使用Spring框架中的注解来定义切面,实现性能监控功能。
3. 常用注解编写
3.1 出参脱敏
结合hutool包的脱敏工具类编写
作用在字段上
代码
注解
/**
* 脱敏注解
*
* @author zwj
* @date 2024/02/26
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveDataSerializer.class)
public @interface SensitiveData {
SensitiveDataType type() ;
/**
* 前置不需要打码的长度
*/
int prefixLen() default 0;
/**
* 后置不需要打码的长度
*/
int suffixLen() default 0;
/**
* 遮罩字符
*/
String maskingChar() default "*";
}
实现
/**
* 敏感数据序列化程序
*
* @author zwj
* @date 2024/02/26
*/
public class SensitiveDataSerializer extends JsonSerializer<String> implements ContextualSerializer {
private SensitiveDataType sensitiveDataType;
private int prefixLen;
private int suffixLen;
private String maskingChar;
@Override
public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) {
if (beanProperty != null) {
SensitiveData desensitization = beanProperty.getAnnotation(SensitiveData.class);
if (desensitization != null) {
this.sensitiveDataType = desensitization.type();
this.prefixLen = desensitization.prefixLen();
this.suffixLen = desensitization.suffixLen();
this.maskingChar = desensitization.maskingChar();
}
}
return this;
}
@Override
public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
throws IOException {
if (!ObjectUtils.isEmpty(value)) {
switch (sensitiveDataType) {
case EMAIL:
value = DesensitizedUtil.email(value);
break;
case PHONE_NUMBER:
value = DesensitizedUtil.mobilePhone(value);
break;
case ID_CARD:
if (prefixLen == 0 && suffixLen == 0) {
prefixLen = 6;
suffixLen = 4;
}
value = DesensitizedUtil.idCardNum(value, prefixLen, suffixLen);
break;
case CUSTOMIZE_RULE:
value = StrUtil.hide(value, prefixLen, suffixLen);
break;
default:
value = value;
break;
}
}
jsonGenerator.writeString(value);
}
}
使用
public class UserDataResponseVo {
/**
* 电话(对电话号码脱敏)
*/
@SensitiveData(type = SensitiveDataType.PHONE_NUMBER)
private String phone;
/**
* 证件号,使用自定义规则,保留前1位和后2位(从1开始)
*/
@SensitiveData(type = SensitiveDataType.CUSTOMIZE_RULE,prefixLen = 1,suffixLen = 2,maskingChar = "#")
private String idCard;
// 省略其他字段和方法
}
代码说明
@JacksonAnnotationsInside注解的含义是告诉Jackson JSON库,该注解可以在其他注解中使用。它是一个标记注解,用于标识其他注解是否可以嵌套在Jackson注解中使用。
@JsonSerialize(using = SensitiveDataSerializer.class)注解的含义是指定了在序列化对象时使用的自定义序列化器。其中,SensitiveDataSerializer.class是一个自定义的序列化器类,用于对敏感数据进行脱敏处理。