Spring Boot @Validated 和Javax的@Valid配合使用

这篇具有很好参考价值的文章主要介绍了Spring Boot @Validated 和Javax的@Valid配合使用。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、@Validated 和@Valid有什么用

@Validation 和@Valid 常常配合使用对传输的参数进行数据校验的注解,并通过配置全局异常处理器进行合理化的提示,增加用户的体验

并且@Validated可以通过分组来指定什么时候触发什么样的参数校验(这里看一下就行,下面有说什么是分组)

二、为什么要使用@Validated 和@Valid的思考?

其实不用这两个注解也可以完成对传输的参数进校验,那样我们就需要一直写if语句进行判断 ,如果不为xxx,抛出异常,然后进行捕获处理  

但是当多处都用到的一样的传输参数的时候,我们每次都需要写一些重复的if进行校验,其实代码是不优雅的。因此有了这两个组件来帮我们进行传输参数的校验。

三、使用方法

3.1 引入pom

<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<!--validator请求参数校验-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-validation</artifactId>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
		</dependency>

       <!--测试方法-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
		</dependency>
	</dependencies>

3.2 写实体类加入一写校验注解

常用的校验注解

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端     
Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    private String name;

    @NotNull(message = "年龄不能为空")
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;

}

3.3 编写controller层进行测试 (请求参数是对象)

注意需要在请求参数的前面加上@Valid注解

统一返回类

package com.sofwin.validator.config;

import lombok.Data;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 21:34
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 统一返回参数
 */
@Data
public  class  BaseResult<T> {
    private int code;
    private String message;
    private T data;

    public BaseResult() {
    }

    public BaseResult(int code, T data,String message) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public static <T> BaseResult<T> build(int code, T data, String message) {
        return new BaseResult<T>(code,data,message);
    }

    public static <T> BaseResult<T> build( T data, BaseResult resultCodeEnum) {
        return new BaseResult<T>(resultCodeEnum.getCode(),data,resultCodeEnum.getMessage());
    }

    public static <T> BaseResult<T> ok(T data) {
        return new BaseResult<>(20000,data,"success");
    }

    public static <T> BaseResult<T> fail(T data) {
        return new BaseResult<>(50000,data,"error");
    }



}

controller 

package com.sofwin.validator.controller;

import com.sofwin.validator.config.BaseResult;
import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.domain.UserR;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

/**
 * @packageName: com.sofwin.validator.controller
 * @author: wentao
 * @date: 2023/9/4 21:14
 * @version: 1.0
 * @description: 请求参数校验
 */

@RestController
@RequestMapping("validator")
public class ValidatorController {


    @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }
   
}

正常参数

 Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

非正常参数 

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

我们发现没有提示我们在实体中message中写的提示信息,是因为我们没有设置全局异常处理器

,它只是在控制台返回了提示信息 

2023-09-05 21:24:03.305  WARN 20924 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.sofwin.validator.config.BaseResult com.sofwin.validator.controller.ValidatorController.validPostTest(com.sofwin.validator.domain.UserR): [Field error in object 'userR' on field 'age': rejected value [1111]; codes [Range.userR.age,Range.age,Range.java.lang.Integer,Range]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [userR.age,age]; arguments []; default message [age],200,1]; default message [最小为1岁,最大为200岁]] ]

全局异常处理器

package com.sofwin.validator.config;

import lombok.extern.slf4j.Slf4j;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
import org.slf4j.Logger;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 21:28
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 全局异常处理器
 */

@RestControllerAdvice
@Slf4j
public class GlobExceptionHandeler {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    //valid参数校验出现异常
    @ExceptionHandler(BindException.class)
    public BaseResult bindException(BindException e) {
        logger.error("valid参数校验出现异常");
        System.out.println(e);
        return BaseResult.build(441,null,e.getBindingResult().getAllErrors().get(0).getDefaultMessage());
    }

    //validated参数校验出现异常
    @ExceptionHandler(ConstraintViolationException.class)
    public BaseResult constraintViolationException(ConstraintViolationException e) {
        logger.error("validated参数校验出现异常");

        return BaseResult.build(441,null,e.getLocalizedMessage().split(":")[1].trim());
    }

    @ExceptionHandler(Exception.class)
    public BaseResult constraintViolationException(Exception e) {
        logger.error("Exception");
        return BaseResult.build(441,null,e.getLocalizedMessage());
    }
}

 加入全局异常处理器后非正常参数返回结果:

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

3.4 当参数不是一个对象

 一定要在controller上加入@Validated才生效

@RestController
@RequestMapping("validator")
@Validated
public class ValidatorController {


    @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }
  

    @GetMapping("/validGet1")
    public BaseResult validGetTest( @NotBlank(message = "名字不能为空") String name ) {
        return BaseResult.ok(name);
    }
}

 

3.5 分组

当我们在特定情况下才进行参数校验才进行分组,例如只有当我们插入的时候我们进行校验,其他时候不进行参数的校验,这个时候就可以使用分组

实体类

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    //进行分组
    @NotBlank(message = "名称不能为空(InsertGroup)",groups = InsertGroup.class)
    private String name;

    @NotNull(message = "年龄不能为空")
    @NotNull(message = "年龄不能为空(InsertGroup)",groups = {InsertGroup.class,UpdateGroup.class})
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

   

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;



}

其中InsertGroup和UpdateGroup只是一个普通的接口


public interface InsertGroup {

}



public interface UpdateGroup {

}

 

controller

package com.sofwin.validator.controller;

import com.sofwin.validator.config.BaseResult;
import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.domain.UserR;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;

/**
 * @packageName: com.sofwin.validator.controller
 * @author: wentao
 * @date: 2023/9/4 21:14
 * @version: 1.0
 * @description: 请求参数校验
 */

@RestController
@RequestMapping("validator")
@Validated
public class ValidatorController {


    @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }
    @PostMapping("/validPost2")
    public BaseResult validPostTest2(@Validated(InsertGroup.class) @RequestBody UserR user ) {
        return BaseResult.ok(user);
    }

    @GetMapping("/validGet1")
    public BaseResult validGetTest( @NotBlank(message = "名字不能为空") String name ) {
        return BaseResult.ok(name);
    }

    @GetMapping("/validGet2")
    public BaseResult validGetTest2(@Validated(InsertGroup.class) @NotNull(message = "名字不能为空") String name ) {
        return BaseResult.ok(name);
    }
}

测试

validPost2、validGet2
validPost2 

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

validGet2

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

3.6 自定义注解

当它提供的注解我们没有办法解决我们的问题的时候,我们就可以自定义注解

定义注解Status

package com.sofwin.validator.config;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 21:52
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 自定义校验注解
 */
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
//自己写校验规则
@Constraint(validatedBy = {StatusConstraint.class})
//元注解 可以分组使用,如果不写定义相同的注解会出现错误
@Repeatable(Status.List.class)
public @interface Status {

    String[] statusType() default {};

    String message() default "状态传递有误";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload()  default {};

   @Target({ElementType.FIELD,ElementType.PARAMETER})
   @Retention(RetentionPolicy.RUNTIME)
   @Documented
    @interface List {
       Status[] value();
   }

}

校验规则

package com.sofwin.validator.config;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.lang.annotation.Annotation;
import java.util.Arrays;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.config
 * @author: wentao
 * @date: 2023/9/4 22:04
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 自定义校验柜子
 */
public class StatusConstraint implements ConstraintValidator<Status,Integer> {

    List<String> statusType;

    /**
     * 一般进行初始化
     * @param constraintAnnotation
     */
    @Override
    public void initialize(Status constraintAnnotation) {
        String[] strings = constraintAnnotation.statusType();
        statusType = Arrays.asList(strings);
    }

    /**
     *
     * @param value  参数的值
     * @param context
     * @return  true 通过不抛出异常  fasle不通过抛出异常
     */
    @Override
    public boolean isValid(Integer value, ConstraintValidatorContext context) {
        if (value !=null) {
            if (!statusType.contains(String.valueOf(value))) {
                return  false;
            }
            return  true;
        }
        return false;
    }
}

测试

实体类

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    //进行分组
    @NotBlank(message = "名称不能为空(InsertGroup)",groups = InsertGroup.class)
    private String name;

    @NotNull(message = "年龄不能为空")
    @NotNull(message = "年龄不能为空(InsertGroup)",groups = {InsertGroup.class,UpdateGroup.class})
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

    @Status(statusType = {"1","2"})
    private Integer status;

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;



}

controller 

  @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }

正常传参

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

非正常传参

 3.7 当出现类中出现嵌套的情况

当出现嵌套的情况只需要在类的属性中在加一个注解@Valid

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

实体类

package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.Status;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;
import org.hibernate.validator.constraints.Range;
import org.springframework.web.bind.annotation.Mapping;

import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;
import java.util.List;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class UserR {

    @NotBlank(message = "名称不能为空")
    //进行分组
    @NotBlank(message = "名称不能为空(InsertGroup)",groups = InsertGroup.class)
    private String name;

    @NotNull(message = "年龄不能为空")
    @NotNull(message = "年龄不能为空(InsertGroup)",groups = {InsertGroup.class,UpdateGroup.class})
    @Range(min = 1,max = 200,message ="最小为{min}岁,最大为{max}岁" )
    private Integer age;

    @Status(statusType = {"1","2"})
    private Integer status;

    @Size(message ="编号长度为 [4-8] ", min = 4, max = 8)
    private String idNo;


    //嵌套使用valid才能生效
    @Valid
    private List<SonUser> sonUserList;
}
package com.sofwin.validator.domain;

import com.sofwin.validator.config.InsertGroup;
import com.sofwin.validator.config.UpdateGroup;
import lombok.Data;

import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.math.BigDecimal;

/**
 * @packageName: com.sofwin.validator.domain
 * @author: wentao
 * @date: 2023/9/4 21:17
 * @version: 1.0
 * @email 1660420659@qq.com
 * @description: 测试
 */
@Data
public class SonUser {

    @NotBlank(message = "sonName不能为空")
    private String sonName;

}

controller

  @PostMapping("/validPost")
    public BaseResult validPostTest(@Valid @RequestBody UserR user ) {
       return BaseResult.ok(user);
    }

Spring Boot @Validated 和Javax的@Valid配合使用,工作后,spring boot,java,后端

四、 总结 

@Valid:没有分组的功能。

@Valid:可以用在方法、构造函数、方法参数和成员属性(字段)上

@Validated:提供了一个分组功能,可以在入参验证时,根据不同的分组采用不同的验证机制

@Validated:可以用在类型、方法和方法参数上。但是不能用在成员属性(字段)上

两者是否能用于成员属性(字段)上直接影响能否提供嵌套验证的功能文章来源地址https://www.toymoban.com/news/detail-696166.html

到了这里,关于Spring Boot @Validated 和Javax的@Valid配合使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • spring boot 配合element ui vue实现表格的批量删除(前后端详细教学,简单易懂,有手就行)

    目录 一.前言: 二. 前端代码: 2.1.element ui组件代码   2.2删除按钮 2.3.data 2.4.methods 三.后端代码: 研究了其他人的博客,找到了一篇有含金量的,进行了部分改写实现前后端分离,参考博主为小白Rachel 先看看页面效果,要是符合你们所需的功能那就继续看下去         1406

    2024年02月04日
    浏览(70)
  • springboot使用@Valid 和 @Validated 注解校验详解以及编写一个自定义全局异常类

    全局异常处理类 验证: ============================================== 导入所需要的包: 如果你是 springboot 项目,那么可以不用引入了,已经引入了,他就存在于最核心的 web 开发包里面。 如果你不是 springboot 项目,那么引入下面依赖即可: 新建三个实体类 实现一: 使用@Valid注解修

    2024年02月10日
    浏览(41)
  • Spring boot如何工作

    越来越方便了  java技术生态发展近25年,框架也越来越方便使用了,简直so easy!!!我就以Spring衍生出的Spring boot做演示,Spring boot会让你开发应用更快速。 快速启动spring boot 请参照官网 Spring | Quickstart 代码如下: 注maven的pom文件 (部分): 运行 通过浏览器方法http://loc

    2024年02月11日
    浏览(32)
  • Spring Boot工作原理

            Spring Boot 基于 Spring 开发,Spirng Boot 本身并不提供 Spring 框架的核心特性以及扩展功能,只是用于快速、敏捷地开发新一代基于 Spring 框架的应用程序。也就是说,它并不是用来替代 Spring 的解决方案,而是和 Spring 框架紧密结合用于提升 Spring 开发者体验的工具。Spr

    2024年03月15日
    浏览(52)
  • Spring @Validated 失效分析

    最近在落地 DDD,希望对 command 进行参数校验,由于部分流量入口是 MQ,所以希望在应用层是用 @Validated 进行参数校验,结果。。。 Controller 中使用 @Validated @Validated 注解的作用这里就不多做介绍了,具体用法在网上应该有不少。 在之前使用 MVC 架构编码时,通常是将 @Validat

    2024年02月03日
    浏览(32)
  • Spring Boot的核心组件和工作原理

    Spring Boot是一个快速构建应用程序的框架,通过自动化配置和约定优于配置的原则,可以快速地创建可独立运行的、生产级别的Spring应用程序。Spring Boot的核心组件是自动配置、起步依赖和嵌入式Web服务器。 在本文中,我们将深入了解Spring Boot的核心组件以及它们的工作原理。

    2024年02月04日
    浏览(48)
  • Spring Boot 整合 Camunda 实现工作流

    工作流是我们开发企业应用几乎必备的一项功能,工作流引擎发展至今已经有非常多的产品。最近正好在接触 Camunda ,所以来做个简单的入门整合介绍。如果您也刚好在调研或者刚开始计划接入,希望本文对您有所帮助。如果您是一名Java开发或Spring框架爱好者,欢迎关注我程

    2024年01月18日
    浏览(69)
  • Spring Boot + Activiti 结合,实现工作流

    Activiti是一个工作流引擎,Activiti可以将业务系统中复杂的业务流程抽取出来,使用专门的建模语言BPMN2.0进行定义,业务流程按照预先定义的流程进行执行,实现了系统的流程由Activiti进行管理,减少业务系统由于流程变更进行系统升级改造的工作量,Activiti流程就是数据库表

    2023年04月13日
    浏览(78)
  • Spring Boot 中动态创建 Flowable 工作流

    在 Spring Boot 中动态创建 Flowable 工作流可以通过以下步骤实现: 1. 创建 Flowable 配置:首先,您需要在 Spring Boot 应用程序中配置 Flowable。您可以使用 Spring Boot 的配置文件或注解来配置 Flowable。 2. 创建工作流定义:接下来,您需要创建工作流定义。您可以使用 Flowable 的 API 来

    2024年02月10日
    浏览(42)
  • Spring Boot整合Camunda打造高效工作流程

    🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是尘缘,一个在CSDN分享笔记的博主。📚📚 👉点击这里,就可以查看我的主页啦!👇👇 尘缘的个人主页 🎁如果感觉还不错的话请给我点赞吧!🎁🎁 💖期待你的加入,一起学习,一起进步!💖💖 在现代的软件开发中,工作流管

    2024年04月13日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包