美文网首页系统设计
七 springboot集成javax.validation

七 springboot集成javax.validation

作者: cf6bfeab5260 | 来源:发表于2019-04-03 11:23 被阅读0次

    1 引入pom依赖:

     <!--java验证框架-->
            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>1.1.0.Final</version>
            </dependency>
    

    特别注意:

    • 如果您已经使用了spring-boot-starter-web,那它已经引入了最合适的 validation-api版本 ,不用单独引依赖。
    • 低版本的 validation-api 的空校验只有@NotNull ,高版本的请注意区分 @NotNull @NotEmpty @NotBlank 的使用。(本文样例是低版本)

    2 简单参数的校验

    • 在类上加 org.springframework.validation.annotation.Validated注解,这里必须是在类上加,在方法或者参数上加,验证会不起作用
    • 这个类必须在spring容器里,比如用@Controller @Service之类的注解标记或者在xml注入都行。
    /**
     * @author: zenghong
     * @Date: 2019/4/2 14:16
     * @Description: 样例接口
     * @RestController 标记为RestController
     * @RequestMapping 这个类的公共请求路径
     * @Validated 这个注解必须注解在类上面,在方法或者参数上,对于非复杂对象的校验将会失效
     */
    @RestController
    @RequestMapping("/example")
    @Validated
    public class ExampleController {
    
    • 然后就可以直接在参数加javax.validated的校验注解了:
    /**
         * 功能描述:  根据id和name查询example  GET 参数为简单对象的示例
         *
         * @ApiOperation swagger的东西,本项目不强制使用
         * @GetMapping 等于 requestMapping + method=GET
         * @ResponseBody 标记返回值示一个json
         * @NotNull @Size 验证非空,验证长度 ,可查看javax.validation.constraints包下其他的验证注解
         * @param:
         * @return:
         * @author: zenghong
         * @date: 2019/4/2 下午2:50
         */
        @ApiOperation("根据id查询example")
        @GetMapping("getExampleByIdAndName")
        @ResponseBody
        public BaseResponse<StnExample> getExampleByIdAndName(
                @Size(min = 8, max = 10,message = "id 长度应为1~11") @NotNull(message = "id 不能为空") String id,
                @Size(min = 8, max = 10,message = "name 长度应为1~64")  @NotNull(message = "name 不能为空") String name) {
    
            //日志的打印拼接请使用占位符方式,字符串本身的拼接用 + 没有关系。
            log.info("日志打印示例{},{},{}", "参数1", "参数2", id+name);
    
            BaseResponse response = new BaseResponse();
            return response;
        }
    

    请求结果:


    image.png

    3 复杂参数校验

    • 在需要校验的复杂参数前面加@Validated 注解
        /**
         * 功能描述:  添加一条记录 - POST 参数为复杂对象的示例
         *
         * @ApiOperation swagger的东西,本项目不强制使用
         * @GetMapping 等于 requestMapping + method=GET
         * @ResponseBody 标记返回值示一个json
         * @param:
         * @return:
         * @author: zenghong
         * @date: 2019/4/2 下午2:50
         */
        @ApiOperation("根据id查询example")
        @PostMapping("AddExample")
        @ResponseBody
        public BaseResponse<StnExample> AddExample(@Validated @RequestBody BaseRequest<StnExample> request) {
    
            log.info("日志打印示例{},{},{}", "参数1", "参数2", request.toString());
    
            BaseResponse response = new BaseResponse();
            return response;
        }
    
    • 在复杂对象上加校验注解
    public class StnExample implements Serializable {
        private static final long serialVersionUID = 42L;
    
        /**
         * 主键ID
         */
        @NotNull(message = "id 不能为空")
        private Long id;
    
        /**
         * 客户姓名
         */
        @NotNull(message = "userName 不能为空")
        private String userName;
    

    如果,用到了范型嵌套对象,必须使用@Valid ( javax.validation.Valid )注解,@Validated对此不起作用:

    public class BaseRequest<T> implements Serializable {
        private static final long serialVersionUID = -4105149695353549745L;
        /** 当前页 */
        protected Integer pageIndex;
        /** 页记录数 */
        protected Integer pageSize;
        /** 请求体 */
        @Valid
        protected T body;
    

    请求结果:


    image.png

    4 全局异常捕获

    您应该发现了,默认给出来的异常信息很丑(特别是简单对象校验不过的时候)。咱们应该进行异常捕获,格式化输出。

    @ControllerAdvice
    @Slf4j
    @ResponseBody
    public class GlobalExceptionHandler {
    
    
    
        /**
         *
         * 功能描述:  捕获 自定义的业务异常,并处理,该异常由程序员手动抛出
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 上午11:47
         */
        @ExceptionHandler(StationException.class)
        public BaseResponse handleServiceException(StationException e) {
            log.error("业务异常:", e);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(e.getErrorCode());
            response.setMessage(e.getMessage());
            return response;
        }
    
    
        /**
         *
         * 功能描述:  捕获 HttpMediaTypeNotSupportedException 异常,并处理,该异常由验证框架抛出
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 下午2:09
         */
        @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
        public BaseResponse handleHttpMediaTypeNotSupportedException(HttpMediaTypeNotSupportedException e) {
            log.error("HttpMediaTypeNotSupportedException : ",e);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.E3000.getCode());
            response.setMessage(ResponseStateCode.E3000.getMessage()+": MediaType 不正确");
            return response;
        }
    
        /**
         *
         * 功能描述:  捕获 HttpRequestMethodNotSupportedException 异常,并处理,该异常由验证框架抛出
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 下午2:14
         */
        @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
        public BaseResponse handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
            log.error("HttpRequestMethodNotSupportedException : ",e);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.E3000.getCode());
            response.setMessage(ResponseStateCode.E3000.getMessage()+": 不支持的 http method");
            return response;
        }
    
    
        /**
         *
         * 功能描述:  捕获 HttpMessageNotReadableException 异常,并处理,该异常由验证框架抛出
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 下午2:15
         */
        @ExceptionHandler(HttpMessageNotReadableException.class)
        public BaseResponse handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
            log.error("HttpMessageNotReadableException : ",e);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.E3000.getCode());
            response.setMessage(ResponseStateCode.E3000.getMessage()+": 非法的http请求");
            return response;
        }
    
        /**
         *
         * 功能描述:  捕获 MissingServletRequestParameterException 异常,并处理,该异常由验证框架抛出
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 下午2:18
         */
        @ExceptionHandler(MissingServletRequestParameterException.class)
        public BaseResponse handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
            log.error("MissingServletRequestParameterException : ",e);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.E3000.getCode());
            response.setMessage(ResponseStateCode.E3000.getMessage()+": 参数缺失");
            return response;
        }
    
        /**
         *
         * 功能描述:  捕获 ConstraintViolationException 异常,并处理,该异常由验证框架抛出
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 下午2:18
         */
        @ExceptionHandler(value = {ConstraintViolationException.class})
        public BaseResponse handleResourceNotFoundException(ConstraintViolationException e) {
            log.error("ConstraintViolationException : ",e);
            Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
            StringBuilder strBuilder = new StringBuilder();
            for (ConstraintViolation<?> violation : violations) {
                strBuilder.append(violation.getMessage() + "\n");
            }
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.E3000.getCode());
            response.setMessage(ResponseStateCode.E3000.getMessage() +": "+ strBuilder.toString());
            return response;
        }
    
        /**
         * 功能描述:  捕获 MethodArgumentNotValidException 异常,并处理,该异常由验证框架抛出
         *
         * @param: e
         * @return: BaseResponse
         * @author: zenghong
         * @date: 2019/3/12 上午9:11
         */
        @ExceptionHandler(MethodArgumentNotValidException.class)
        public BaseResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
            log.error("MethodArgumentNotValidException : {}",e);
            BindingResult result = e.getBindingResult();
            FieldError error = result.getFieldError();
            String field = error.getField();
            String code = error.getDefaultMessage();
            String message = String.format("%s %s", field, code);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.E3000.getCode());
            response.setMessage(ResponseStateCode.E3000.getMessage() +": "+ message);
    
            return response;
        }
    
    
        /**
         *
         * 功能描述:  搂底的异常处理,正常来讲不应该走到这里的,如果走到这里需要特别注意
         *
         * @param:
         * @return: com.jccfc.station.response.BaseResponse
         * @author: zenghong
         * @date: 2019/4/3 下午2:24
         */
        @ExceptionHandler(value = Exception.class)
        public BaseResponse defaultErrorHandler(Exception e) {
            log.error("发生其他异常,详细信息:", e);
            BaseResponse response = new BaseResponse();
            response.setState(false);
            response.setCode(ResponseStateCode.ERROR.getCode());
            response.setMessage(ResponseStateCode.ERROR.getMessage() +": 服务器错误,请稍后重试");
            return response;
    
        }
    
    }
    

    说明:具体的实体类和返回码枚举需要换成您自己的。

    这个时候的输出:


    image.png image.png

    下一章 八 springboot集成sleuth链路追踪

    相关文章

      网友评论

        本文标题:七 springboot集成javax.validation

        本文链接:https://www.haomeiwen.com/subject/fjkabqtx.html