zoukankan      html  css  js  c++  java
  • 如何优雅的处理SpringBoot接口中参数校验

    相信我们在处理接口参数校验时,都不会使用大量的if,else 进行来处理,这样显得太繁琐,下面就来介绍一下如何能够简单而有效的处理方式:

    一、使用注解来处理参数校验

    1、实体类

    package com.dongl.bean.mybean;
    
    
    import com.dongl.utils.annotation.CheckField;
    import lombok.Data;
    import org.hibernate.validator.constraints.Range;
    
    import javax.validation.constraints.NotNull;
    import java.util.Date;
    @Data
    public class User { /**主键*/ private Long id; /**姓名*/ @NotNull private String name; /**性别*/ @CheckField(fieldValues = {"男", "女"}) private String sex; /**出生日期*/ private Date birthDay; /**年龄*/ @Range(min = 20 , max = 99) private Short age; /**详细地址*/ private String address; }

    2、Controller层

    package com.dongl.controller;
    
    import com.dongl.bean.mybean.User;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    /**
     * @author D-L
     * @Classname AnnotationController
     * @Version 1.0
     * @Description   接口参数校验异常处理
     * @Date 2020/8/26
     */
    
    @RestController
    @RequestMapping("Annotation")
    public class AnnotationController {
    
        @PostMapping(value = "user")
        public String test(@Validated @RequestBody User user  /*, BindingResult bindingResult*/) {
            System.out.println(user);
            return "do something you like ------";
        }
    }

    3、响应结果

    测试参数:

    {
        "name":"admin",
        "sex":"男",
        "age":120,
        "address":"杭州市西湖区"
    }

    response:

    {
        "timestamp": "2020-08-26T07:25:45.547+0000",
        "status": 400,
        "error": "Bad Request",
        "errors": [
            {
                "codes": [
                    "Range.user.age",
                    "Range.age",
                    "Range.java.lang.Short",
                    "Range"
                ],
                "arguments": [
                    {
                        "codes": [
                            "user.age",
                            "age"
                        ],
                        "arguments": null,
                        "defaultMessage": "age",
                        "code": "age"
                    },
                    99,
                    20
                ],
                "defaultMessage": "需要在20和99之间",
                "objectName": "user",
                "field": "age",
                "rejectedValue": 120,
                "bindingFailure": false,
                "code": "Range"
            }
        ],
        "message": "Validation failed for object='user'. Error count: 1",
        "trace": "org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public java.lang.String com.dongl.controller.AnnotationController.test(com.dongl.bean.mybean.User): [Field error in object 'user' on field 'age': rejected value [120]; codes [Range.user.age,Range.age,Range.java.lang.Short,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [user.age,age]; arguments []; default message [age],99,20]; default message [需要在20和99之间]] 
    	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    	at java.lang.Thread.run(Thread.java:748)
    ",
        "path": "/Annotation/user"
    }

    结论】:这样的响应结果显然有点不够优雅,太繁琐,有没有更好的处理方式,当然有,下面使用 BindResult 处理。

     

    二、针对接口处理  Validator + BindResult进行校验

    1、处理响应结果

    package com.dongl.controller;
    
    import com.dongl.bean.mybean.User;
    import org.springframework.validation.BindingResult;
    import org.springframework.validation.ObjectError;
    import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.List;
    
    /**
     * @author D-L
     * @Classname AnnotationController
     * @Version 1.0
     * @Description   处理参数校验异常 
     * @Date 2020/8/24
     */
    
    @RestController
    @RequestMapping("Annotation")
    public class AnnotationController {
    
        @PostMapping(value = "user")
        public String test(@Validated @RequestBody User user  , BindingResult bindingResult) {
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            // 如果有参数校验失败,会将错误信息封装成对象组装在BindingResult里
            for(ObjectError error : allErrors){
                return error.getDefaultMessage();
            }
            System.out.println(user);
            return "do something you like ------";
        }
    }

     

    2、响应结果

    需要在20和99之间

    结论】当然这种方式已经解决了返回体繁琐的问题,但是每一处理接口参数都需要添加,还是有点不尽人意,有没有更好的解决方法,当然有,下面通过全局的方式处理。

     

    三、全局异常处理  Validator + 自动抛出异常

    1、全局处理响应结果

    首先,我们需要新建一个类,在这个类上加上@ControllerAdvice或@RestControllerAdvice注解,这个类就配置成全局处理类了。(这个根据你的Controller层用的是@Controller还是@RestController来决定)

    这里就以@RestController为例:

    package com.dongl.utils.error;
    
    import org.springframework.validation.ObjectError;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    /**
     * @author D-L
     * @Classname ExceptionControllerAdvice
     * @Version 1.0
     * @Description   全局处理参数校验异常返回提示
     * @Date 2020/8/26
     */
    @RestControllerAdvice
    public class ExceptionControllerAdvice {
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public String MethodArgumentNotValidExceptionHandler(MethodArgumentNotValidException e) {
            // 从异常对象中拿到ObjectError对象
            ObjectError objectError = e.getBindingResult().getAllErrors().get(0);
            // 然后提取错误提示信息进行返回
            return objectError.getDefaultMessage();
        }
    }

     

    2、测试结果:

    需要在20和99之间

    注释】:这里说明一下如果你进行了全局的处理,但在接口上又进行了手动处理,这时命中的是接口上的,也就是全局配置不生效了。

  • 相关阅读:
    inux修改profile文件出错后所有命令不能用
    windows常用批处理脚本
    Namespace + functions versus static methods on a class 命名空间函数和类的静态方法对比
    vs2008(visual studio)使用cppcheck
    保存文件为UTF8格式(Writing UTF8 files in C++).
    C++ smtp发送邮件类(ssl/tls)转自codeproject。
    CString、TCHAR、WCHAR 字符串等转BSTR的几种方法。
    C/C++中全局变量的那些事儿
    [C++] 哪本书是对程序员最有影响、每个程序员都该阅读的书?读书排行。
    (转)修改VS2008(vc)中工程/解决方案/类的名字
  • 原文地址:https://www.cnblogs.com/dongl961230/p/13565702.html
Copyright © 2011-2022 走看看