写Spring项目的接口中要经常接收前端传过来的参数,要判断参数是否有效,比如邮箱格式要正确,名字不能为空等等。
手动判断比较麻烦,我们可以通过注解的方式来判断值是否有效,spring中已经提供了这类注解(要手动引入,点这里),比如👇
常用注解
值 | 作用 |
---|---|
@NotNull | 字符串内容不能为空 |
@Max | 定义最大值 |
@Min | 定义最小值 |
数据必须是邮箱格式 | |
@Future | 必须是将来的日期 |
... |
实例中使用代码示例,bean:
@Date
public class User{
private int id;
@NotBlank
private String name;
@Positive
private int age;
}
Controller:
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/register")
public String register(@Validated User user){
// ... 操作user的数据
}
}
有时候时候并不能满足我们的要求,比如要求用户的年龄参数只能是18到25之间,传了其他数就认为传参错误。
开始来自定义一个注解👇
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@Constraint(validatedBy = AgeValidator.class)
public @interface Youth{
int value() default 0;
String message() default "age valid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
@interface表示新建一个注解,跟class差不多,Youth表示这个注解的名字,使用的时候就是@Youth
@Retention(RetentionPolicy.RUNTIME) 就是说运行时也有效,不懂问题不大。
@Target(ElementType.FIELD) 就是说这个注解只能写在字段上,不懂问题也不大。
@Constraint(validatedBy = CategoryValidator.class) 表示谁来判断被@Youth注解的参数值有效性,我们写了个AgeValidator.class,所以再新建一个AgeValidator类,👇
public class AgeValidator implements ConstraintValidator<Youth, Integer> {
@Override
public boolean isValid(Integer age, ConstraintValidatorContext constraintValidatorContext) {
return age>=18 && age<=25;
}
}
实现ConstraintValidator接口,并且里面有个isValid的方法,这个方法返回true表示被@Youth注解的字段是有效的,否则无效。
ConstraintValidator的泛型参数,第一个要为其提供判断的注解,这里就是Youth,第二个表示你这个注解标在哪种数据类型上,我们这里注解在年龄上,所以是Integer。
可以了,现在可以使用了。
@Date
public class User{
private int id;
@NotBlank
private String name;
@Youth
private int age;
}
这时候前端传递的age如果不是在18和25中间,那么就会报错。
什么,非对象类型参数也想要这种注解?像下面这样?
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/detail/{id}")
public String detail(@PathVariable Integer id){
// ... 操作user的数据
}
@GetMapping("/search")
public String search(Integer age){
// ... 操作user的数据
}
}
此时注解需要加载参数上,则需要修改注解@Youth
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.PARAMETER}) //只要修改这里 修改成这样
@Constraint(validatedBy = AgeValidator.class)
public @interface Youth{
int value() default 0;
String message() default "age valid";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
多了个ElementType.PARAMETER表示这个注解也可以加在参数上。
修改完成,继续使用👇
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/search")
public String search(@Youth Integer age){
// ... 操作user的数据
}
@GetMapping("/detail/{id}")
public String detail(@PathVariable @Youth Integer id){
// ... 操作user的数据
}
}
不出意外的话,是没有效果的,因为还要加上
@Validated // 添加这个
@RestController
@RequestMapping("/user")
public class UserController {
// ...
}
这下就好了,🤭