暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

springboot参数校验

dean技术分享 2019-05-17
190
  1. 创建一个统一返回结果集

    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
    @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. 创建一个用于测试的用户类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    @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

    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
    @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默认的错误信息


  1. 统一异常处理

    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
    @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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    @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);
    }
    }


  2. 分组校验

  • 创建用于分组的接口

    1
    2
    3
    4
    5
    6
    //什么都不需要写,springboot根据类去分组校验
    //用户校验添加角色校验
    public interface Add {}

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    @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}


  1. 自定义校验注解

  • 创建自定义校验注解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @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();    
        }
    }
  • 创建校验注解的类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //校验注解的类必须实现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);
    }
    }
  • 测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    @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}


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


阅读原文有项目链接

文章转载自dean技术分享,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论