springboot参数校验

297 阅读5分钟

1.创建一个统一返回结果集

@Data
public class JsonResult implements Serializable {
private static final long serialVersionUID = -1946193220290386110L;

public static final boolean SUCCESS = true;
public static final boolean FAIL = false;

private boolean status;
private int code;
private String msg;
private Object data;

public JsonResult(boolean status, int code, String msg, Object data) {
this.status = status;
this.code = code;
this.msg = msg;
this.data = data;
}

public static JsonResult success(Object data) {
return new JsonResult(SUCCESS, 200, "ok", data);
}

public static JsonResult success(String msg) {
return new JsonResult(SUCCESS, 200, msg, null);
}

public static JsonResult fail(String msg) {
return fail(400, msg);
}

public static JsonResult fail(int code, String msg) {
return new JsonResult(FAIL, code, msg, null);
}
}

2.创建一个用于测试的用户类

@Data
public class User implements Serializable {

@Length(min = 5, max = 10, message = "用户名长度不合法")
@NotNull(message = "用户名不能为空")
private String username;

@Length(min = 6, max = 16, message = "密码长度不合法")
@NotNull(message = "密码不能为空")
private String password;
}

3.创建一个controller

@RestController
//在请求方法中校验需要在类上加该注解
@Validated
public class UserController {

//测试post请求
//@Validated用于校验参数,如果参数校验失败,错误信息封装到BindingResult
@PostMapping("/login")
public JsonResult login(@Validated @RequestBody User user, BindingResult bindingResult){
//判断BindingResult中是否有错误信息
if(bindingResult.hasErrors()){
return JsonResult.fail(bindingResult.getFieldError().getDefaultMessage());
}
return JsonResult.success("登陆成功");
}

//测试get请求
@GetMapping("/getLogin")
public JsonResult getLogin(@Validated User user, BindingResult bindingResult){
if(bindingResult.hasErrors()){
return JsonResult.fail(bindingResult.getFieldError().getDefaultMessage());
}
return JsonResult.success("登陆成功");
}

//测试请求方法中校验
//这种校验不支持封装到BindingResult中,需要自己做异常处理
@GetMapping("/getUser")
public JsonResult getUser(@NotNull(message = "用户名不能为空") String username){
User user = new User();
user.setUsername(username);
user.setPassword("123456");
return JsonResult.success(user);
}
}

4.测试

  • 测试post请求,由于未写html页面,用postman进行测试

    • 请求:post http://localhost:8080/login
    • 参数:{"username":"admin", "password":"123"}
    • 返回结果:{"status":false,"code":400,"msg":"密码长度不合法","data":null}
  • 测试get请求

    • 请求:get http://localhost:8080/getLogin?username=admin&password=123
    • 返回结果:{"status":false,"code":400,"msg":"密码长度不合法","data":null}
  • 测试请求方法中校验

    • 请求:get http://localhost:8080/getUser
    • 返回结果:springboot默认的错误信息

5.统一异常处理

@RestControllerAdvice
public class GlobalExceptionHandler {

/**
* post请求参数校验抛出的异常
* @param e
* @return
*/

@ExceptionHandler(MethodArgumentNotValidException.class)
public JsonResult methodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e){
//获取异常中随机一个异常信息
String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
return JsonResult.fail(defaultMessage);
}

/**
* get请求参数校验抛出的异常
* @param e
* @return
*/

@ExceptionHandler(BindException.class)
public JsonResult bindExceptionHandler(BindException e){
//获取异常中随机一个异常信息
String defaultMessage = e.getBindingResult().getFieldError().getDefaultMessage();
return JsonResult.fail(defaultMessage);
}

/**
* 请求方法中校验抛出的异常
* @param e
* @return
*/

@ExceptionHandler(ConstraintViolationException.class)
public JsonResult constraintViolationExceptionHandler(ConstraintViolationException e){
//获取异常中第一个错误信息
String message = e.getConstraintViolations().iterator().next().getMessage();
return JsonResult.fail(message);
}
}

将所有的校验异常都在异常统一处理后,controller参数中就可以不写BindingResult,也不需要每个方法都校验是否有异常了

使用异常统一处理后的controller

@RestController
public class UserBetterController {

@PostMapping("/login")
public JsonResult login(@Validated @RequestBody User user){
return JsonResult.success("登陆成功");
}

@GetMapping("/getLogin")
public JsonResult getLogin(@Validated User user){
return JsonResult.success("登陆成功");
}

@GetMapping("/getUser")
public JsonResult getUser(@NotNull(message = "用户名不能为空") String username){
User user = new User();
user.setUsername(username);
user.setPassword("123456");
return JsonResult.success(user);
}
}

6.分组校验

  • 创建用于分组的接口
//什么都不需要写,springboot根据类去分组校验
//用户校验添加角色校验
public interface Add {}

//用于校验修改角色校验
public interface Update {}
  • 创建一个测试分组的实体类
@Data
public class Role {

//修改角色时,必须要有id
@NotNull(message = "修改角色必须有id", groups = Update.class)
private Long id;

//添加角色时必须要有name
@NotNull(message = "添加角色必须有name", groups = Add.class)
//添加修改都需要name的长度在1-10
@Length(min = 1, max = 10, message = "名称不合法", groups = {Add.class, Update.class})
private String name;
}
  • 创建测试controller
@RestController
public class RoleController {

@GetMapping("add")
public JsonResult add(@Validated(Add.class) Role role){
return JsonResult.success("添加成功");
}

@GetMapping("update")
public JsonResult update(@Validated(Update.class) Role role){
return JsonResult.success("修改成功");
}
}
  • 测试

    • 测试添加角色
      请求:get http://localhost:8080/add
      返回结果:{"status":false,"code":400,"msg":"添加角色必须有name","data":null}

    • 测试修改角色
      请求:get http://localhost:8080/update
      返回结果:{"status":false,"code":400,"msg":"修改角色必须有id","data":null}

7.自定义校验注解

  • 创建自定义校验注解
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
//用于校验手机号的逻辑类
@Constraint(validatedBy = PhoneValidator.class)
public @interface Phone {
//手机号的校验格式
String regexp() default "^[1][3-9][0-9]{9}$";

//出现错误返回的信息
String message() default "
手机号格式错误";

Class<?>[] groups() default { };

Class<? extends Payload>[] payload() default { };

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
public @interface List {
Phone[] value();
}
}
  • 创建校验注解的类
//校验注解的类必须实现ConstraintValidator,第一个泛型是注解,第二个泛型是校验参数的类型(手机号是String类型)
public class PhoneValidator implements ConstraintValidator<Phone, String> {

private String regexp;

//初始化方法
@Override
public void initialize(Phone constraintAnnotation) {
//获取校验的手机号的格式
this.regexp = constraintAnnotation.regexp();
}

//value是@Phone注解所注解的字段值
//校验,返回true则通过校验,返回false则校验失败,错误信息为注解中的message
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if(value == null){
return true;
}

return value.matches(regexp);
}
}
  • 测试
@RestController
@Validated
public class PhoneController {

@GetMapping("/sendPhone")
public JsonResult sendPhone(@Phone @NotNull(message = "手机号不能为空") String phone){
return JsonResult.success("正确的手机号");
}
}

请求:get http://localhost:8080/sendPhone?phone=123
返回结果:{"status":false,"code":400,"msg":"手机号格式错误","data":null}

常用的校验注解自行搜索引擎

项目路径


作者博客

作者公众号 在这里插入图片描述