返回顶部
首页 > 资讯 > 精选 >如何在SpringBoot中使用JSR303对后端数据进行校验
  • 664
分享到

如何在SpringBoot中使用JSR303对后端数据进行校验

2023-06-07 21:06:55 664人浏览 八月长安
摘要

如何在SpringBoot中使用jsR303对后端数据进行校验?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。项目创建首先创建一个springboot项目使用的s

如何在SpringBoot中使用jsR303对后端数据进行校验?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

项目创建

首先创建一个springboot项目

使用的springboot版本为:(本文代码以该版本为准,不同版本springboot,在下面内容会出现一些差异

<parent>  <groupId>org.springframework.boot</groupId>  <artifactId>spring-boot-starter-parent</artifactId>  <version>2.3.9.RELEASE</version>  <relativePath/> <!-- lookup parent from repository --> </parent>

引入如下依赖

 <dependencies>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-thymeleaf</artifactId>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-WEB</artifactId>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-devtools</artifactId>   <scope>runtime</scope>   <optional>true</optional>  </dependency>  <dependency>   <groupId>org.projectlombok</groupId>   <artifactId>lombok</artifactId>   <optional>true</optional>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-test</artifactId>   <scope>test</scope>   <exclusions>    <exclusion>     <groupId>org.junit.vintage</groupId>     <artifactId>junit-vintage-engine</artifactId>    </exclusion>   </exclusions>  </dependency>  <dependency>   <groupId>org.springframework.boot</groupId>   <artifactId>spring-boot-starter-validation</artifactId>  </dependency> </dependencies>

这个作标在新一点的springboot版本中,需要单独引入。在老版本是默认引入的。这个是用来引入对jsr303注解的支持。

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

接着创建一个Java Bean

package cn.jxj4869.demo.entity;import lombok.Data;import javax.validation.constraints.NotNull;@Datapublic class User { @NotNull private Integer id; private String username; private String passWord; private String email;}

返回类型的JavaBean

package cn.jxj4869.demo.entity;import java.util.HashMap;public class R extends HashMap<String, Object> {private static final long serialVersionUID = 1L;public R() {put("code", 0);put("msg", "success");}public static R error(int code, String msg) {R r = new R();r.put("code", code);r.put("msg", msg);return r;}public static R ok(String msg) {R r = new R();r.put("msg", msg);return r;}public R put(String key, Object value) {super.put(key, value);return this;}}

创建一个controller。

index方法用来跳转到首页。

package cn.jxj4869.demo.controller;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.*;@Controllerpublic class UserController { @RequestMapping("/") public String index(){  return "index"; }}

首页代码放到resources/templates目录下

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style>  div{   margin-top: 50px;  } </style></head><body><div> 新增表单 <br><br> <fORM method="post">  <label>用户名</label>  <input type="text" name="username"/>  <br>  <label>密码</label>  <input type="text" name="password"/>  <br>  <label>邮箱</label>  <input type="email" name="email"/>  <br>  <input type="submit" value="提交"/> </form></div><div> 更新表单 <br><br> <form method="post">  <input type="hidden" name="id" value="1">  <label>用户名</label>  <input type="text" name="username"/>  <br>  <label>密码</label>  <input type="text" name="password"/>  <br>  <label>邮箱</label>  <input type="email" name="email"/>  <br>  <input type="submit" value="提交"/> </form></div></body></html>

传统的检验方式

要在后端进行数据校验,传统的校验方式在controller层接受数据后,按照要求对数据进行校验

比如要接收一个user bean对象。

现在要对user对象中的username属性进行非空校验,password属性进行非空校验和长度校验。

 @PostMapping("/user") @ResponseBody public R user1(User user) throws Exception {  if(StringUtils.isEmpty(user.getUsername())) {   return R.error(400,"username不能为空");  }  if(StringUtils.isEmpty(user.getPassword())||user.getPassword().length()>8||user.getPassword().length() <4) {   return R.error(400,"password无效");  }  return null; }

如果有多个方法都需要接受user对象, 而且要校验的属性可能不止usernamepassword这两个属性,如果每个方法里面都采用上面这种校验方式的话,代码就会很臃肿,而且不好维护,当改变了userbean的属性,或者对校验规则进行修改后,就得对所有的校验代码进行更新。 这是一件工程量很大的事。

使用JSR303

为了解决上述问题,我们可以使用JSR303提供的注解进行校验。

JSR是Java Specification Requests的缩写,意思是Java 规范提案。JSR303也就是第303号提案。

使用JSR303的方法很简单,例如上面的需求,我们只需要在user的属性上加上注解即可。

步骤如下:

给Bean添加校验注解,一般是在 javax.validation.constraints这个包下,也还有一些是hibernate提供的。

开启校验功能@Valid。

当校验失败的时候,会抛出org.springframework.validation.BindException异常。

常用的校验注解在文末

package cn.jxj4869.demo.entity;import lombok.Data;import org.hibernate.validator.constraints.Length;import javax.validation.constraints.NotNull;@Datapublic class User { private Integer id; @NotBlank private String username; @NotBlank @Length(min = 4,max = 8) private String password; private String email;}

然后在controller里面的方法上,加上@Valid注解即可

 @PostMapping("/user2") @ResponseBody public R user2(@Valid User user) throws Exception {  System.out.println(user);  return null; }

当校验失败后,会出现如下错误。并且会给出默认的提示信息。

如何在SpringBoot中使用JSR303对后端数据进行校验

自定义错误信息

那这个错误信息是怎么来的呢。

进入@NotNULL注解的代码里面

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)@Documented@Constraint(validatedBy = { })public @interface NotBlank {String message() default "{javax.validation.constraints.NotNull.message}";............ ............ ............}

会有一个message属性。显然就是指定错误的提示内容。而这些错误提示是在一个叫validationMessages.properties的文件中,用idea的搜索工具可以找到,双击shift键打开搜索。

发现有这么多validationMessages.properties的文件,而且支持国际化。

如何在SpringBoot中使用JSR303对后端数据进行校验

打开validationMessages_zh.properties,可以看到里面定义了这么多的提示。而错误提示就是从这文件中获取的。

如何在SpringBoot中使用JSR303对后端数据进行校验

如果我们不想用默认的校验提示信息的话,可以自己指定。

指定message的值即可。

@NotBlank(message = "用户名不能为空") private String username;

如何在SpringBoot中使用JSR303对后端数据进行校验

错误信息的获取与响应

当校验出错时,会默认返回一个错误界面,或者返回错误提示的JSON数据。但默认提供的显然不是我们想要的,如果可以拿到错误信息,那我们就能自定义相应数据了。

拿到错误信息的方式也很简单,只要在方法中加上BindingResult result这个参数,错误信息就会封装这里面。

@PostMapping("/user2") @ResponseBody public R user2(@Valid User user, BindingResult result) throws Exception {  System.out.println(user);  if(result.hasErrors()) { //判断是否有错误   Map<String,String> map = new HashMap<>();   //1、获取校验的错误结果   result.getFieldErrors().forEach((item)->{    //FieldError 获取到错误提示    String message = item.getDefaultMessage();    //获取错误的属性的名字    String field = item.getField();    map.put(field,message);   });   return R.error(400,"提交的数据不合法").put("data",map);  }  // 若没有错误,则进行接下去的业务操作。  return null; }

不过不推荐上面这种方式,理由同上,当校验的地方多了,每个方法里面都加上这么个异常处理,会让代码很臃肿。

不知道你们是否还记得,springMVC里面有个全局的异常处理,我们可以自定义一个异常处理,在这里面统一处理异常。

统一处理BinException。这样就可以不用在controller中去处理错误信息了。

package cn.jxj4869.demo.execption;import cn.jxj4869.demo.entity.R;import org.springframework.validation.BindException;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.bind.annotation.RestControllerAdvice;import java.util.HashMap;import java.util.Map;@RestControllerAdvice(basePackages = "cn.jxj4869.demo.controller")public class MyExceptionControllerAdvice { @ExceptionHandler(value = BindException.class) public R handleVaildException(BindException e) {   Map<String,String> map = new HashMap<>();   //1、获取校验的错误结果   e.getFieldErrors().forEach((item)->{    //FieldError 获取到错误提示    String message = item.getDefaultMessage();    //获取错误的属性的名字    String field = item.getField();    map.put(field,message);   });   return R.error(400,"提交的数据不合法").put("data",map); }}

错误异常类型补充

校验出错的时候,会抛出两种异常

org.springframework.validation.BindException

使用@Valid注解进行校验的时候抛出的

org.springframework.web.bind.MethodArgumentNotValidException

使用@validated校验的时候抛出的

在异常捕获中加入下面这个

 @ExceptionHandler(value= MethodArgumentNotValidException.class) public R handleVaildException(MethodArgumentNotValidException e){  BindingResult bindingResult = e.getBindingResult();  Map<String,String> map = new HashMap<>();  bindingResult.getFieldErrors().forEach((fieldError)->{   map.put(fieldError.getField(),fieldError.getDefaultMessage());  });  return R.error(400,"提交的数据不合法").put("data",map); }

分组校验

在不同业务场景下,校验规则是不一样的,比如user对象中id这个属性,在新增的时候,这个属性是不用填的,要为null,但是在修改的时候,id属性是不能为null的。

可以用注解中的groups属性来指定,在什么场合下使用改注解

@Documented@Constraint(validatedBy = { })@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@Repeatable(List.class)public @interface NotBlank {Class<?>[] groups() default { };........}

首先定义两个接口AddGroupUpdateGroup,不需要做任何实现

package cn.jxj4869.demo.valid;public interface UpdateGroup {}
package cn.jxj4869.demo.valid;public interface AddGroup {}

在user中指定group。

  • id属性在AddGroup的时候,要为null,在UpdateGroup的时候不能为null

  • username属性在AddGroup和Update的时候,都要进行校验,不能为空。

  • password属性,当校验的时候指定分组的话,会不起作用,因为没有给它指定校验的分组

package cn.jxj4869.demo.entity;import cn.jxj4869.demo.valid.AddGroup;import cn.jxj4869.demo.valid.UpdateGroup;import lombok.Data;import javax.validation.constraints.NotBlank;import javax.validation.constraints.NotEmpty;import javax.validation.constraints.NotNull;import javax.validation.constraints.Null;@Datapublic class User { @Null(groups = {AddGroup.class}) @NotNull(groups = {UpdateGroup.class}) private Integer id;   @NotBlank(message = "用户名不能为空",groups = {AddGroup.class,UpdateGroup.class}) private String username; @NotEmpty private String password; private String email;}

在controller中用@Validated注解,指定校验的分组

 @PostMapping("/user3") @ResponseBody public R user3(@Validated(UpdateGroup.class) User user) {  System.out.println(user);  return null; }

结果如下图所示,因为password属性没有指定校验的分组,所以在校验的时候,都不会对它进行合法性检查。

如何在SpringBoot中使用JSR303对后端数据进行校验

如何在SpringBoot中使用JSR303对后端数据进行校验

自定义校验

当提供的注解不能满足我们需求的时候,可以自定义注解。

例如我们现在给user新加一个属性status,并要求这个属性的值只能是0或者1。

新建一个@StatusValue注解。

根据jsr303的规范,校验注解得有三个属性。

  • message:用来获取错误提示的

  • groups:指定校验分组的。

  • payload:可以自定义一些负载信息

使用@Constraint注解指定该注解的校验器

package cn.jxj4869.demo.valid;import javax.validation.Constraint;import javax.validation.Payload;import java.lang.annotation.Documented;import java.lang.annotation.Retention;import java.lang.annotation.Target;import static java.lang.annotation.ElementType.*;import static java.lang.annotation.ElementType.TYPE_USE;import static java.lang.annotation.RetentionPolicy.RUNTIME;@Documented@Constraint(validatedBy = { StatusValueConstraintValidator.class })@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })@Retention(RUNTIME)@interface StatusValue { String message() default "{cn.jxj4869.valid.StatusValue.message}"; Class<?>[] groups() default { }; Class<? extends Payload>[] payload() default { }; int[] value() default { };}

自定义校验器

需要实现ConstraintValidator这个接口,第一个泛型是表示要校验哪个注解,第二个泛型是要校验的数据的类型。

  • initialize是初始化方法

  • isValid校验方法,判断是否校验成功

package cn.jxj4869.demo.valid;import javax.validation.ConstraintValidator;import javax.validation.ConstraintValidatorContext;import java.util.HashSet;import java.util.Set;public class StatusValueConstraintValidator implements ConstraintValidator<StatusValue,Integer> { private Set<Integer> set = new HashSet<>(); //初始化方法 @Override public void initialize(StatusValue constraintAnnotation) {  int[] value = constraintAnnotation.value();  for (int val : value) {   set.add(val);  } }  @Override public boolean isValid(Integer value, ConstraintValidatorContext context) {  return set.contains(value); }}

最后在resources目录下添加一个ValidationMessages.properties文件

用来指定错误信息。

cn.jxj4869.valid.StatusValue.message=必须提交指定的值

UserBean

@Datapublic class User { @Null(groups = {AddGroup.class}) @NotNull(groups = {UpdateGroup.class}) private Integer id; @NotBlank(message = "用户名不能为空",groups = {AddGroup.class,UpdateGroup.class}) private String username; @NotEmpty private String password; private String email; @StatusValue(value = {0,1},groups = {AddGroup.class,UpdateGroup.class}) private Integer status;}

如何在SpringBoot中使用JSR303对后端数据进行校验

如何在SpringBoot中使用JSR303对后端数据进行校验

常用注解汇总

注解功能
@Null对象必须为null
@NotNull对象必须不为null,无法检查长度为0的字符串
@NotBlank字符串必须不为Null,且去掉前后空格长度必须大于0
@NotEmpty字符串必须非空
@Length(min = 1,max = 50)字符串必须在指定长度内
@Range(min = 0,max = 100)必须在指定范围内
@AssertTrue对象必须为true
@AssertFalse对象必须为false
@Max(Value)必须为数字,且小于或等于Value
@Min(Value)必须为数字,且大于或等于Value
@DecimalMax(Value)必须为数字( BigDecimal ),且小于或等于Value。小数存在精度
@DecimalMin(Value)必须为数字( BigDecimal ),且大于或等于Value。小数存在精度
@Digits(integer,fraction)必须为数字( BigDecimal ),integer整数精度,fraction小数精度
@Size(min,max)对象(Array、Collection、Map、String)长度必须在给定范围
@Email字符串必须是合法邮件地址
@PastDate和Calendar对象必须在当前时间之前
@FutureDate和Calendar对象必须在当前时间之后
@Pattern(regexp=“正则”)字符串满足正则表达式的值

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网精选频道,感谢您对编程网的支持。

--结束END--

本文标题: 如何在SpringBoot中使用JSR303对后端数据进行校验

本文链接: https://lsjlt.com/news/250272.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何在SpringBoot中使用JSR303对后端数据进行校验
    如何在SpringBoot中使用JSR303对后端数据进行校验?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。项目创建首先创建一个springboot项目使用的s...
    99+
    2023-06-07
  • Springboot如何使用filter对requestbody参数进行校验
    目录使用filter对request body参数进行校验通过filter修改body参数的思路知识点步骤使用filter对request body参数进行校验 @Slf4j pub...
    99+
    2024-04-02
  • SpringBoot接口如何对参数进行校验
    目录前言什么是不优雅的参数校验实现案例POM请求参数封装Controller中获取参数绑定结果校验结果进一步理解Validation分组校验?@Validate和@Valid什么区别...
    99+
    2024-04-02
  • 如何对参数进行校验
    本篇内容主要讲解“如何对参数进行校验”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何对参数进行校验”吧!背景大部分的方法和构造函数对传入的参数值有一些限制,比...
    99+
    2024-04-02
  • Springboot怎么使用filter对request body参数进行校验
    这篇文章主要为大家展示了“Springboot怎么使用filter对request body参数进行校验”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Springboot怎么使用fil...
    99+
    2023-06-29
  • 使用SpringMVC怎么实现对数据进行校验
    使用SpringMVC怎么实现对数据进行校验?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。一、导入jar包若要实现数据校验功能,需要导入必要的jar包,主要包括以下几个:c...
    99+
    2023-05-31
    springmvc
  • java使用Validation进行数据校验
    在开发中,我们经常遇到参数校验的需求,比如用户注册的时候,要校验用户名不能为空、用户名长度不超过20个字符、手机号是合法的手机号格式等等。如果使用普通方式,我们会把校验的代码和真正的业务处理逻辑耦合在一起,而且如果未来要新增一种校验逻辑也需...
    99+
    2023-09-01
    java spring
  • Python如何进行数据指纹MD5校验对比
    Python如何进行数据指纹MD5校验对比,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。Python3—数据指纹MD5校验与对比MD5消息摘要算法(英语:MD5...
    99+
    2023-06-02
  • SpringBoot如何进行参数校验实例详解
    目录前言为什么需要参数校验SpringBoot中集成参数校验第一步,引入依赖第二步,定义要参数校验的实体类第三步,定义校验类进行测试第四步,体验效果参数异常加入全局异常处理器体验效果...
    99+
    2024-04-02
  • 使用Spring MVC怎么对参数进行校验
    本篇文章为大家展示了使用Spring MVC怎么对参数进行校验,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1. 内嵌异常处理如果只是这个controller的异常做单独处理,那么就适合绑定这个co...
    99+
    2023-05-31
    springmvc
  • Springboot 如何使用BindingResult校验参数
    目录使用BindingResult校验参数1、创建一个参数对象2、controller控制层写参数接收的入口3、传入参数和控制台打印结果4、常用校验注解BindingResult 作...
    99+
    2024-04-02
  • Node 中怎么在Controller 层进行数据校验
    Node 中怎么在Controller 层进行数据校验,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。数据校验层后端由于重业务逻辑以及待处理...
    99+
    2024-04-02
  • 如何进行SpringBoot开发的集成参数校验
    这期内容当中小编将会给大家带来有关如何进行SpringBoot开发的集成参数校验,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。对于 web服务来说,为防止非法参数对业务造...
    99+
    2024-04-02
  • 如何使用@Valid+BindingResult进行controller参数校验
    这篇文章主要介绍“如何使用@Valid+BindingResult进行controller参数校验”,在日常操作中,相信很多人在如何使用@Valid+BindingResult进行controller参数校验问题上存在疑惑,小编查阅了各式资...
    99+
    2023-06-21
  • 如何进行C++代码的数据校验?
    如何进行C++代码的数据校验在编写C++代码时,数据校验是非常重要的一环。通过对用户输入的数据进行校验,可以增强程序的健壮性和安全性。本文将介绍一些常见的数据校验方法和技巧,帮助读者有效地进行C++代码的数据校验。输入数据类型检查在对用户输...
    99+
    2023-11-04
    跨平台 数据校验 C++代码
  • 如何使用SQL语句在MySQL中进行数据校验和完整性约束?
    如何使用SQL语句在MySQL中进行数据校验和完整性约束?数据校验和完整性约束是数据库管理系统中常用的方法,用于确保数据的正确性和完整性。在MySQL中,我们可以通过使用SQL语句来实现这些约束。本文将介绍如何使用SQL语句在MySQL中进...
    99+
    2023-12-18
    MySQL SQL语句 数据校验
  • Python 使用@property对属性进行数据规范性校验的实现
    在绑定属性时,如果我们直接把属性暴露出去,虽然写起来很简单,但是,没办法检查参数,导致可以把成绩随便改: s = Student() s.score = 9999 这显然不合...
    99+
    2024-04-02
  • 如何使用JavaScript进行表单校验功能
    这篇文章主要介绍如何使用JavaScript进行表单校验功能,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!文本框校验以下是文本框的校验步骤。1.获取待校验的文本框value值,2.对...
    99+
    2024-04-02
  • 前端如何调用后端接口进行数据交互详解(axios和SpringBoot)
    目录一、介绍二、项目结构三、代码编写四、运用总结前端调用后端接口,获得数据并渲染 一、介绍 一个完善的系统,前后端交互是必不可少的,这个过程可以分成下面几步: 前端向后端发起请求后端...
    99+
    2023-03-19
    前端和后端怎么进行数据交互的 前端如何调用后端数据 前端与后端接口的交互案例
  • 使用pt-table-checksum工具对主从数据的一致性进行校验
    本文主要给大家简单讲讲使用pt-table-checksum工具对主从数据的一致性进行校验,相关专业术语大家可以上网查查或者找一些相关书籍补充一下,这里就不涉猎了,我们就直奔主题吧,希望使用pt-table...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作