不使用注解的SpringBoot是没有灵魂的
在有些场景下,需要对入参进行过滤,例如sql中不能预编译的字段等,这时候可以通过写一个过滤注解,然后只需要将需注解加到想要过滤的字段上,便可以完成预想逻辑的过滤操作。
1. 创建注解
@Target({ ElementType.FIELD, ElementType.PARAMETER})
//@Target
用于设定注解使用范围
//Target
通过ElementType
来指定注解可使用范围的枚举集合
//FIELD
: 可用于域上
//PARAMETER
:可用于参数上
@Retention(RetentionPolicy.RUNTIME)
//@Retention
注解可以用来修饰其他注解,是注解的注解,称为元注解。
//@Retention
注解有一个属性value
,是RetentionPolicy
类型的。
//RetentionPolicy.RUNTIME
:注解不仅被保存到class文件中,JVM加载class文件之后,仍然存在
@Constraint(validatedBy = {ParamsConstraintValidator.class})
//自定义验证注解
这段的逻辑是CheckParams
注解加工的默认类型是String
,返回消息默认Param Illegal
,注解的具体过滤逻辑在ParamsConstraintValidator
类中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| /** * 对入参字段做sql注入风险过滤,String类型为默认配置类型 */
@Target({ ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) @Constraint(validatedBy = {ParamsConstraintValidator.class})
public @interface CheckParams {
boolean required() default true;
String message() default “Param Illegal";
/** * type:String * @return */ String type() default “String";
}
|
2. 实现注解的过滤逻辑
自定义注解处理类必须实现ConstraintValidator
接口, 其中CheckParams
是自己定义的注解, 而Object是注解标注参数的类型,也可以是String或者其它类型。
type
和message
在上边已经默认配置,在添加注解时可以进行覆盖。
SecUtil.escapeSql
是过滤参数的方法,这里不细写了,任何我们想要的参数加工逻辑都可以。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| public class ParamsConstraintValidator implements ConstraintValidator<CheckParams, Object> {
public static final String STRING_TYPE = “String"; private String type = ""; private String message ="";
@Override public void initialize(CheckParams constraintAnnotation) { ConstraintValidator.super.initialize(constraintAnnotation); type = constraintAnnotation.type(); message = constraintAnnotation.message(); }
@Override public boolean isValid(Object o, ConstraintValidatorContext constraintValidatorContext) { if (o == null) { return true; } constraintValidatorContext.disableDefaultConstraintViolation(); constraintValidatorContext.buildConstraintViolationWithTemplate(message).addConstraintViolation(); switch (type) { case STRING_TYPE: return checkString(o); default: return true; }
}
/** * 检验String,List<String> * * @param o * @return */ private boolean checkString(Object o) { if (o instanceof String) { String obj = (String)o; String afterObj = SecUtil.escapeSql(obj); return Objects.equals(obj, afterObj); } else if (o instanceof List) { List list = (List)o; for (Object it : list) { if (it instanceof String) { String obj = (String)it; String afterObj = SecUtil.escapeSql(obj); if (!Objects.equals(obj, afterObj)) { return false; } } }
} return true; } }
|
3. 使用注解
在入参对象中,将其加到需要过滤的参数上,
1 2 3 4 5
| @CheckParams(message = “Param Illegal") private List<String> param1;
@CheckParams(type = “String”, message = “Param Illegal") private String param2;
|