IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Springboot 参数校验 -> 正文阅读

[Java知识库]Springboot 参数校验

Springboot 参数校验

? Java API规范(JSR303)定义了Bean校验的标准 validation-api,但没有提供实现。hibernate validation 是对这个规范的实现,并增加了校验注解如 @Email@Length 等。

? Spring Validation 是对 hibernate validation 的二次封装,用于支持 spring mvc 参数自动校验。

引入依赖

? 如果spring-boot版本小于2.3.xspring-boot-starter-web会自动传入hibernate-validator依赖。如果spring-boot版本大于2.3.x,则需要手动引入依赖:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.0.1.Final</version>
</dependency>

requestBody 参数校验

? POSTPUT请求一般会使用requestBody传递参数,这种情况下,只要给 DTO 对象加上 @Validated 注解就能实现自动参数校验。

? 比如,有一个保存Brand的接口,要求 name 长度是不能超过30字符。

/**
 * 参数实体上声明约束
 */
@Data
public class BrandDto {

    private Long id;

    @NotBlank(message = "品牌名不能为空!")
    @Length(max = 30, message = "品牌名太长了!")
    private String name;

    private String chineseSpell;

    private String englishName;
}

/**
  * 在方法参数上使用@Valid声明校验注解(使用@Valid和@Validated都可以)
  */
@PostMapping("/brand")
public Result saveBrand(@RequestBody @Valid BrandDto brand){
    return brandService.saveBrand(brand);
}

? 校验失败,会抛出 MethodArgumentNotValidException 异常,Spring默认会将其转为400(Bad Request)请求。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y137UAG6-1637506371219)(https://i.loli.net/2021/11/21/iq2us3R7968ItVg.png)]

? image-20211121215025114

requestParam/PathVariable 参数校验

? 如果是 GET 请求一般会使用 requestParam/PathVariable 传参,此时要在类上标注 @Validated 注解,并在入参上声明约束注解。

@RestController
@RequestMapping("/v1/web/brand")
@Validated
public class BrandController {
 	@Autowired
    private BrandService brandService;

 	/**
     * 查询品牌
     */
   @GetMapping("/brand")
    public Result getBrand(@RequestParam("id")
                               @NotNull(message = "id不能为空!")
                               @Max(value = 10000, message = "id超过最大范围了!") Long id){
        return brandService.getBrand(id);
    }
}

? 校验失败,会抛出 ConstraintViolationException 异常:

image-20211121214407611

? image-20211121214532689

统一异常处理

? 如果校验失败,会抛出 MethodArgumentNotValidException 或者 ConstraintViolationException 异常。在实际项目开发中,通常会用统一异常处理根据业务情况来返回一个更友好的提示:

// 等价于 @ControllerAdvice + @ResponseBody
@RestControllerAdvice  
public class GlobalExectionHandler {


    /**
     * requestBody 接收参数,校验失败统一处理
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public Result handleMethodArgumentNotValidException(MethodArgumentNotValidException exception){
        BindingResult bindingResult = exception.getBindingResult();
        List<FieldError> fieldErrorList =  bindingResult.getFieldErrors();
        int size = fieldErrorList.size();

        StringBuilder sb = new StringBuilder("参数校验失败:");
        for (int i = 0; i < size; i++) {
            FieldError fieldError = fieldErrorList.get(i);
            sb.append(fieldError.getField()).append(":").append(fieldError.getDefaultMessage());
            if(i != (size-1)){
                sb.append(", ");
            }
        }
        String msg = sb.toString();
        return Result.parameterError().setMessage(msg);
    }


    /**
     * requestParam/PathVariable 接收参数,校验失败统一处理
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public Result handleConstraintViolationException(ConstraintViolationException exception) {
        return Result.parameterError().setMessage("参数校验失败:" + exception.getMessage());
    }
}

快速失败

? Spring Validation 默认会校验完所有字段,然后才抛出异常。可以开启 Fali Fast 模式,一旦校验失败就立即返回。

@Configuration
public class ValidateConfig {

    /**
     * 开启参数校验快速失败模式
     */
    @Bean
    public Validator validator() {
        ValidatorFactory validatorFactory = Validation.byProvider(HibernateValidator.class)
                .configure()
                // 快速失败模式
                .failFast(true)
                .buildValidatorFactory();
        return validatorFactory.getValidator();
    }
}

嵌套校验

? 实际场景中,可能存在一个实体类中还嵌套着另外的实体类,即一个对象的某个属性是对另一个对象的引用。这种情况下可以使用嵌套校验,此时,该属性字段上必须加上 @Valid注解,下面是一个具体的例子:

/**
 * 参数实体上声明约束
 */
@Data
public class BrandDto {

    private Long id;

    @NotBlank(message = "品牌名不能为空!")
    @Length(max = 30, message = "品牌名太长了!")
    private String name;

    private String chineseSpell;

    private String englishName;
    
    /**
     * 嵌套校验,添加 @Valid
     */
    @Valid
    private EnterpriseBrandDto enterpriseBrandDto;

}


@Data
public class EnterpriseBrandDto {
    private Long id;

    @NotNull(message = "企业账号id不能为空!")
    private Long enterpriseId;

    @NotNull(message = "品牌id不能为空!")
    private Long brandId;

    private Date createDate;

    private Date updateDate;
}



@RestController
@RequestMapping("/v1/web/brand")
public class BrandController {
    /**
     * 在方法参数上使用@Valid声明校验注解
     */
    @PostMapping("/brand")
    public Result saveBrand(@RequestBody @Valid BrandDto brand){
        return brandService.saveBrand(brand);
    }
}

集合校验

? 如果请求体直接传递了json 数组给后台,并希望对数组中的每一项都进行参数校验。此时要使用自定义 list 集合来接收参数:

@Data
public class ValidList<E> implements List<E> {

    @Delegate
    @Valid
    public List<E> list = new ArrayList<>();
}


@RestController
@RequestMapping("/v1/web/brand")
public class BrandController {
   /**
     * 集合校验
     */
    @PostMapping("/brands")
    public Result saveBrands(@RequestBody @Valid ValidList<BrandDto> brands){
        return brandService.saveBrands(brands);
    }
}
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-22 12:12:16  更:2021-11-22 12:14:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 3:13:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码