SpringBoot - 优雅的实现【参数校验】高级进阶

简介: SpringBoot - 优雅的实现【参数校验】高级进阶


Pre

SpringBoot - 优雅的实现【参数校验】高级进阶

SpringBoot - 优雅的实现【自定义参数校验】高级进阶

SpringBoot - 优雅的实现【参数分组校验】高级进阶

SpringBoot - 使用Assert校验让业务代码更简洁


概述

日常开发中,对入参进行参数校验是必不可少的一个环节。 而使用最多的就是Validator框架 。

Validator校验框架遵循了JSR-303 【Java Specification Requests】验证规范 。

这里我们探讨下,在boot项目中如何优雅的集成参数校验框架



参数校验三部曲

Step1 搞依赖

boot 2.3 以后版本的pom信息如下

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
    </dependencies>
  • spring boot-2.3之前的版本只需要引入 spring-boot-starter-web 即可 ,已经包含了

  • spring boot-2.3及以后的版本,校验包是一个单独的starter,需要同时引入spring-boot-starter-validation


Step2 搞参数校验的实体类

package com.artisan.vo;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
/**
 * @author 小工匠
 * @version 1.0 
 * @mark: show me the code , change the world
 */
@Data
public class Artisan {
    private String id;
    @NotBlank(message = "名字为必填项")
    private String name;
    @Length(min = 8, max = 12, message = "password长度必须位于8到12之间")
    private String password;
    @Email(message = "请填写正确的邮箱地址")
    private String email;
    private String sex;
    @NotEmpty(message = "Code不能为空")
    private String code;
}

常用的校验注解

注解 功能
@AssertFalse 可以为null,如果不为null的话必须为false
@AssertTrue 可以为null,如果不为null的话必须为true
@DecimalMax 设置不能超过最大值
@DecimalMin 设置不能超过最小值
@Digits 设置必须是数字且数字整数的位数和小数的位数必须在指定范围内
@Future 日期必须在当前日期的未来
@Past 日期必须在当前日期的过去
@Max 最大不得超过此最大值
@Min 最大不得小于此最小值
@NotNull 不能为null,可以是空
@Null 必须为null
@Pattern 必须满足指定的正则表达式
@Size 集合、数组、map等的size()值必须在指定范围内
@Email 必须是email格式
@Length 长度必须在指定范围内
@NotBlank 字符串不能为null,字符串trim()后也不能等于“”
@NotEmpty 不能为null,集合、数组、map等size()不能为0;字符串trim()后可以等于“”
@Range 值必须在指定范围内
@URL 必须是一个URL



Step3 开始验证

注意看注释

package com.artisan.controller;
import com.artisan.vo.Artisan;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.Email;
/**
 * @author 小工匠
 * @version 1.0
 * @mark: show me the code , change the world
 */
@RestController
@Slf4j
@Validated
@RequestMapping("/valid")
public class ArtisanController {
    /**
     * 使用@RequestBody注解,用于接受前端发送的json数据
     *
     * @param artisan
     * @return
     */
    @PostMapping("/testJson")
    public String testJson(@Validated @RequestBody Artisan artisan) {
        log.info("InComing Param  {}", artisan);
        return "testJson valid success";
    }
    /**
     * 模拟表单提交
     *
     * @param artisan
     * @return
     */
    @PostMapping(value = "/testForm")
    public String testForm(@Validated Artisan artisan) {
        log.info("InComing Param is {}", artisan);
        return "testForm valid success";
    }
    /**
     * 模拟单参数提交
     *
     * @param email
     * @return
     */
    @PostMapping(value = "/testParma")
    public String testParma(@Email String email) {
        log.info("InComing Param is {}", email);
        return "testParma  valid success";
    }
}
  • testJson使用 @RequestBody注解,用于接受前端发送的json数据
  • testForm模拟表单提交
  • testParma模拟单参数提交
    当使用单参数校验时需要在Controller上加上@Validated注解,否则不生效


【测试第一个接收JSON的接口 】

可以看到抛出的异常为: org.springframework.web.bind.MethodArgumentNotValidException


【测试第二个接收表单的接口 】

可以看到抛出的异常为: org.springframework.validation.BindException


【测试第三个接收单参数的接口 】

可以看到抛出的异常为:javax.validation.ConstraintViolationException


存在的问题

且不说好不好看, 不管怎么样,现在是通过Validation框架实现了校验。 当然了,我们的追求肯定不是这样的,Validator校验框架返回的错误提示太臃肿了 ,格式啥的都不一样,很难搞哦, 怎么给前台返回????



使用 统一格式 + 全局异常Handler 优化

增加统一返回 和 全局异常Handler,单独拦截参数校验的三个异常:javax.validation.ConstraintViolationExceptionorg.springframework.validation.BindExceptionorg.springframework.web.bind.MethodArgumentNotValidException

/**
     * @param e
     * @return
     */
    @ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
    public ResponseEntity<ResponseData<String>> handleValidatedException(Exception e) {
        ResponseData<String> resp = null;
        if (e instanceof MethodArgumentNotValidException) {
            // BeanValidation exception
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            resp = ResponseData.fail(HttpStatus.BAD_REQUEST.value(),
                    ex.getBindingResult().getAllErrors().stream()
                            .map(ObjectError::getDefaultMessage)
                            .collect(Collectors.joining("; "))
            );
        } else if (e instanceof ConstraintViolationException) {
            // BeanValidation GET simple param
            ConstraintViolationException ex = (ConstraintViolationException) e;
            resp = ResponseData.fail(HttpStatus.BAD_REQUEST.value(),
                    ex.getConstraintViolations().stream()
                            .map(ConstraintViolation::getMessage)
                            .collect(Collectors.joining("; "))
            );
        } else if (e instanceof BindException) {
            // BeanValidation GET object param
            BindException ex = (BindException) e;
            resp = ResponseData.fail(HttpStatus.BAD_REQUEST.value(),
                    ex.getAllErrors().stream()
                            .map(ObjectError::getDefaultMessage)
                            .collect(Collectors.joining("; "))
            );
        }
        log.error("参数校验异常:{}", resp.getMessage());
        return new ResponseEntity<>(resp, HttpStatus.BAD_REQUEST);
    }

重新测试


源码

https://github.com/yangshangwei/boot2


相关文章
|
9天前
|
前端开发 Java
SpringBoot之数组,集合,日期参数的详细解析
SpringBoot之数组,集合,日期参数的详细解析
13 0
|
22天前
|
Java 数据库连接 Spring
Spring Boot命令行启动添加参数
Spring Boot命令行启动添加参数
|
5天前
|
Java Spring
Spring Boot脚手架集成校验框架
Spring Boot脚手架集成校验框架
13 0
|
6天前
|
开发框架 Java 开发者
Spring Boot接收参数的多种方式
【4月更文挑战第20天】
11 0
|
9天前
|
JSON 前端开发 Java
SpringBoot之JSON参数,路径参数的详细解析
SpringBoot之JSON参数,路径参数的详细解析
13 0
|
9天前
|
前端开发 Java
SpringBoot之实体参数的详细解析
SpringBoot之实体参数的详细解析
11 0
|
11天前
|
JSON Java 数据格式
Spring Boot实现各种参数校验
这些是Spring Boot中实现参数校验的一些常见方法,你可以根据项目需求选择适合的方式来进行参数校验。
13 0
|
1月前
|
Java
SpringBoot整合AOP整合aspectj实现面向切面编程实现参数接收和请求时间打印
SpringBoot整合AOP整合aspectj实现面向切面编程实现参数接收和请求时间打印
6 0
|
2月前
|
Java 应用服务中间件
SpringBoot 启动参数设置环境变量、JVM参数、tomcat远程调试
SpringBoot 启动参数设置环境变量、JVM参数、tomcat远程调试
27 0
|
JSON 数据安全/隐私保护 数据格式
SpringBoot中的异常处理与参数校验_2
  兄弟们好,这次来跟老铁交流两个问题,异常和参数校验,在说参数校验之前我们先来说异常处理吧,因为后面参数的校验会牵扯到异常处理这块的内容。   说到异常处理,我不知道大家有没有写过或者遇到过如下的写法。
208 0