前言

Jakarta Bean Validation到底是什么?我们不妨先看看其官网的相关介绍。

Bean Validation 2.0 is a spec!
It is done — after one year of hard work, and a bit more than four years after the previous revision, the final release of Bean Validation 2.0 (JSR 380) is out!

Last week, the JSR passed the Final Approval Ballot by the executive committee of the JCP unanimously with 25 “Yes” votes. After the ballot we’ve released version 2.0.0.Final of the specification, the API as well as the TCK. At the same time, the final version of the reference implementation, Hibernate Validator 6, was released, too.

Within the next few days, the final specification will also be available on the JSR 380 page on jcp.org, after which the work on this JSR is complete and the expert group officially will disband.

Posted by Gunnar Morling | 07 Aug 2017
参考网址:https://beanvalidation.org/news/2017/08/07/bean-validation-2-0-is-a-spec/

由上可知,Jakarta Bean Validation是JCP通过的JSR380规范,在2017年8月7日,Bean Validation 2.0最终版本已经发布,参考该规范的Hibernate Validator 6实现最终版本也已发布。

一句话总结:“Jakarta Bean Validation是规范,Hibernate Validator是该约束的一种实现”。

截至今日(2021年4月1日,愚人节),Hibernate Validator 6实现已经更新到6.2.0.Final,对应的Jakarta Bean Validation规范版本为2.0.2


看到又有版本更新了,是不是很开心?但是,这还不够。因为还有更高版本!学习的速度永远赶不上变化的速度啊!Hibernate Validator实现已经更新到7.0.1.Final,对应的Jakarta Bean Validation规范版本为3.0.0


而且,Jakarta Bean Validation的2.0.23.0.0差异还是蛮大的,不仅仅是3比2大了1个版本号,简直就不是一个东西!


1、Jakarta Bean Validation 2

pox.xml

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

package和class


2、Jakarta Bean Validation 3

pox.xml

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

package和class


注意,在Jakarta Bean Validation 3中,包名是jakarta.validation开头。而在Jakarta Bean Validation 2中,包名是javax.validation开头。


3、Hibernate Validator

Hibernate Validator,The Bean Validation reference implementation.
Express validation rules in a standardized way using annotation-based constraints and benefit from transparent integration with a wide variety of frameworks.
–Hibernate Validator官网
翻译:Hibernate Validator是Bean Validation的参考实现。
使用基于注解的约束以标准化的方式表达验证规则,并从与各种框架的透明集成中获益。

3.1、Constraints


3.2、验证实践

3.2.1、pom.xml

本次实践中我们以Hibernate Validator 6.2.0.Final为基准版本进行pom.xml依赖配置,然后,再不需要任何其它配置,即可启动项目,Service部分输出参考如下:

...
Connected to server
[2021-04-02 12:58:37,580] Artifact SpringMvc0401Validation:war: Artifact is being deployed, please wait...
INFO [2021/04/02 00:58:39.105] [RMI TCP Connection(3)-127.0.0.1]:  org.springframework.web.context.ContextLoader Root WebApplicationContext: initialization started
INFO [2021/04/02 00:58:39.605] [RMI TCP Connection(3)-127.0.0.1]:  org.springframework.web.context.ContextLoader Root WebApplicationContext initialized in 485 ms
INFO [2021/04/02 00:58:39.716] [RMI TCP Connection(3)-127.0.0.1]:  org.springframework.web.servlet.DispatcherServlet Initializing Servlet 'springmvc'
INFO [2021/04/02 00:58:40.335] [RMI TCP Connection(3)-127.0.0.1]:  com.company.project.controller.HelloJspController 正在创建HelloJspController
INFO [2021/04/02 00:58:40.815] [RMI TCP Connection(3)-127.0.0.1]:  org.hibernate.validator.internal.util.Version HV000001: Hibernate Validator 6.0.18.Final
INFO [2021/04/02 00:58:41.696] [RMI TCP Connection(3)-127.0.0.1]:  org.springframework.web.servlet.DispatcherServlet Completed initialization in 1980 ms
[2021-04-02 12:58:41,722] Artifact SpringMvc0401Validation:war: Artifact is deployed successfully
[2021-04-02 12:58:41,722] Artifact SpringMvc0401Validation:war: Deploy took 4,142 milliseconds
...

在上述输出日志中,有非常关键的一句输出,说明Hibernate Validator已随着项目成功启动:

INFO [2021/04/02 00:58:40.815] [RMI TCP Connection(3)-127.0.0.1]:  org.hibernate.validator.internal.util.Version HV000001: Hibernate Validator 6.0.18.Final

3.2.2、Model

约束都被定义在javax.validation.constraints包,我们在Model的被验证字段上以注解方式直接添加即可,代码参考如下:

import javax.validation.constraints.*;public class UserInfoModel {//必须是0到100之间@Min(value = 0, message = "成绩最小值为{value}")@Max(value = 100, message = "成绩最大值为{value}")private Integer score;//手机号码不为空@NotBlank(message = "手机号不能为空")@Pattern(regexp = "^1[3,4,5,6,7,8,9]\\d{9}$", message = "手机号码不正确")private String phone;//用户名 不为空@NotEmpty(message = "用户名不能为空NotEmpty")@NotBlank(message = "用户名不能为空")@Size(min = 6, message = "名称至少6个字符")private String name;...Getter\Setter\hashCode\equals\toString}

3.2.3、Controller

Controller在进行验证和处理验证结果时,需要遵循如下规则:

  • 在控制器方法上要有Model和BindingResult 类型的入参;
  • 在Model参数增加@Valid注解;
  • 通过BindingResult 获取验证错误的数量和信息;
  • 通过ModelAndView 将错误信息传递给视图;

代码实现参考如下:


import com.company.project.model.UserInfoModel;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.validation.Valid;
//import jakarta.validation.Valid;@Controller
@RequestMapping(value = "/user-info")
public class UserInfoController {@RequestMapping("/mothod01")public ModelAndView mothod01(@Valid UserInfoModel userInfoModel,BindingResult bindingResult) {ModelAndView modelAndView = new ModelAndView();modelAndView.setViewName("/validator");int errorCount = bindingResult.getErrorCount();if (errorCount > 0) {FieldError score = bindingResult.getFieldError("score");FieldError phone = bindingResult.getFieldError("phone");FieldError name = bindingResult.getFieldError("name");if (score != null) {modelAndView.addObject("scoremsg", score.getDefaultMessage());}if (phone != null) {modelAndView.addObject("phonemsg", phone.getDefaultMessage());}if (name != null) {modelAndView.addObject("namemsg", name.getDefaultMessage());}modelAndView.setViewName("/validator");}return modelAndView;}
}

3.2.4、View

3.2.4.1、表单页面

<%--Created by IntelliJ IDEA.User: goldenunion@qq.comDate: 2021/3/24Time: 16:26To change this template use File | Settings | File Templates.
--%><%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="author" content="goldenunion@qq.com"/><meta name="Keywords" content="WWW,HTML,CSS,Javascript,XML,Json,JavaEE,Jsp,SpringMvc"/><meta name="Description" content="该文档演示了JSP文档的基本结构。"/><title>Title</title>
</head>
<body bgcolor="deepskyblue"><h1>数据校验</h1>
<form action="${pageContext.request.contextPath}/user-info/mothod01" method="post">成绩:<input name="score" /> <span>${scoremsg }</span><br/><br/>姓名:<input name="name"/><span>${namemsg }</span><br/><br/>电话:<input name="phone"/><span>${phonemsg }</span><br/><br/><input type="submit" value="注册"/>
</form></body>
</html>

3.2.4.2、显示页面

在jsp中,使用EL表达式通过对象名称取出其值,简单参考如下:

${scoremsg} <br/>${phonemsg} <br/>${namemsg} <br/>

页面运行效果:

手机号码不正确
名称至少6个字符

4、SpringMVC

4.1、LocalValidatorFactoryBean

LocalValidatorFactoryBean的完整包路径为

org.springframework.validation.beanvalidation.LocalValidatorFactoryBean。它是javax.validation.validatororg.springframework.validation.Validator的实现。

4.1.1、javax.validation.validator

4.1.2、org.springframework.validation.Validator

4.2、org.springframework.validation.Validator

package org.springframework.validation;/*** A validator for application-specific objects.** <p>This interface is totally divorced from any infrastructure* or context; that is to say it is not coupled to validating* only objects in the web tier, the data-access tier, or the* whatever-tier. As such it is amenable to being used in any layer* of an application, and supports the encapsulation of validation* logic as a first-class citizen in its own right.** <p>Find below a simple but complete {@code Validator}* implementation, which validates that the various {@link String}* properties of a {@code UserLogin} instance are not empty* (that is they are not {@code null} and do not consist* wholly of whitespace), and that any password that is present is* at least {@code 'MINIMUM_PASSWORD_LENGTH'} characters in length.** <pre class="code"> public class UserLoginValidator implements Validator {**    private static final int MINIMUM_PASSWORD_LENGTH = 6;**    public boolean supports(Class clazz) {*       return UserLogin.class.isAssignableFrom(clazz);*    }**    public void validate(Object target, Errors errors) {*       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "userName", "field.required");*       ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "field.required");*       UserLogin login = (UserLogin) target;*       if (login.getPassword() != null*             && login.getPassword().trim().length() < MINIMUM_PASSWORD_LENGTH) {*          errors.rejectValue("password", "field.min.length",*                new Object[]{Integer.valueOf(MINIMUM_PASSWORD_LENGTH)},*                "The password must be at least [" + MINIMUM_PASSWORD_LENGTH + "] characters in length.");*       }*    }* }</pre>** <p>See also the Spring reference manual for a fuller discussion of* the {@code Validator} interface and its role in an enterprise* application.** @author Rod Johnson* @see SmartValidator* @see Errors* @see ValidationUtils*/
public interface Validator {/*** Can this {@link Validator} {@link #validate(Object, Errors) validate}* instances of the supplied {@code clazz}?* <p>This method is <i>typically</i> implemented like so:* <pre class="code">return Foo.class.isAssignableFrom(clazz);</pre>* (Where {@code Foo} is the class (or superclass) of the actual* object instance that is to be {@link #validate(Object, Errors) validated}.)* @param clazz the {@link Class} that this {@link Validator} is* being asked if it can {@link #validate(Object, Errors) validate}* @return {@code true} if this {@link Validator} can indeed* {@link #validate(Object, Errors) validate} instances of the* supplied {@code clazz}*/boolean supports(Class<?> clazz);/*** Validate the supplied {@code target} object, which must be* of a {@link Class} for which the {@link #supports(Class)} method* typically has (or would) return {@code true}.* <p>The supplied {@link Errors errors} instance can be used to report* any resulting validation errors.* @param target the object that is to be validated* @param errors contextual state about the validation process* @see ValidationUtils*/void validate(Object target, Errors errors);}

5、JSR303

变化太快,如果没有老项目牵挂,是该痛痛快快和JSR303说分手了!


6、参考来源

  • Jakarta Bean Validation官网:https://beanvalidation.org/

  • Hibernate官网:http://hibernate.org/validator/

  • Spring官网:https://docs.spring.io

Jakarta Bean Validation,Constrain once, validate everywhere!相关推荐

  1. 1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知

    乔丹是我听过的篮球之神,科比是我亲眼见过的篮球之神.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免 ...

  2. 详解Bean Validation

    理性阅读,欢迎探讨 1. Bean Validation是什么? Bean Validation 是一个数据验证规范,属于Java EE 6的子规范,详情参考维基百科,这里不做赘述. 既然是规范,那么 ...

  3. java validation_java bean validation 参数验证

    一.前言 在后台开发过程中,对参数的校验成为开发环境不可缺少的一个环节.比如参数不能为null,email那么必须符合email的格式,如果手动进行if判断或者写正则表达式判断无意开发效率太慢,在时间 ...

  4. JSR-303 Bean Validation 介绍及 Spring MVC 服务端验证最佳实践

    任何时候,当要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情. 应用程序必须通过某种手段来确保输入参数在上下文来说是正确的. 分层的应用在很多时候,同样的数据验证逻辑会出现在不同的层, ...

  5. Spring4新特性——集成Bean Validation 1.1(JSR-349)到SpringMVC

    http://sishuok.com/forum/blogPost/list/7798.html 在之前的<跟我学SpringMVC>中的<第七章 注解式控制器的数据验证.类型转换及 ...

  6. JSR 303 – Bean Validation 介绍及最佳实践

    关于 Bean Validation 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下 ...

  7. JSR 303 - Bean Validation 介绍及最佳实践

    关于 Bean Validation 在任何时候,当你要处理一个应用程序的业务逻辑,数据校验是你必须要考虑和面对的事情.应用程序必须通过某种手段来确保输入进来的数据从语义上来讲是正确的.在通常的情况下 ...

  8. Java数据校验(Bean Validation / JSR303)

    文档: http://beanvalidation.org/1.1/spec/ API : http://docs.jboss.org/hibernate/beanvalidation/spec/1. ...

  9. Java Bean Validation 最佳实践

    <h1 class="postTitle"><a id="cb_post_title_url" class="postTitle2& ...

最新文章

  1. html左右飘窗高度不一致,飘窗的最佳尺寸,你可知道?不懂的留着吧!
  2. 与VS集成的若干种代码生成解决方案[博文汇总(共8篇)]
  3. 图论 —— 稳定婚姻问题与延迟认可算法
  4. azure devops中文显示乱码_Azure DevOps Server:Git权限设置
  5. Python中的类属性和类方法(静态方法、私有属性和私有方法)
  6. 机器学习读书笔记(一)k-近邻算法
  7. RabbitMQ ACK 机制的意义是什么?
  8. Spring Boot @ServletComponentScan 扫描 @WebServlet、@WebFilter、@WebListener
  9. c++矩阵的转置和快速转置
  10. CTP: 找ActionDay 和TradingDay说点事
  11. c语言从入门到精通 PPT,C语言从入门到精通第1章讲述.ppt
  12. ECharts - dataset组件的用法详解
  13. 计算机内存128毫升,内存换算公式(内存怎么换算)
  14. vue搭配three.js创建3D旋转方块
  15. Golang的chan阻塞测试
  16. 导入Android 项目,按钮点击事件,添加okhttp三合一,android动态修改标题
  17. 人脸识别登录:加强系统认证
  18. win10网络可以ping 通,不能进网页
  19. KSM(Kernel samepage merging)
  20. 软件产品案例分析——福州大学微信小程序

热门文章

  1. Python语言程序设计笔记(全)
  2. 纯css更改图片颜色的技巧
  3. Petalinux快速入门向导 (15) 第十四章.硬盘速度测试
  4. 【旅游热点】金秋十月 “额济纳胡杨林”登内蒙古景区热度榜首
  5. Elasticsearch 7.10 之 Similarity module
  6. 论文浅尝 | PAKDD2020 - 利用支持集中匹配信息的 few shot 事件分类方法
  7. 【面经】米哈游数据开发面经
  8. iOS 卡顿原因及优化思路
  9. KingbaseES V8R6集群管理运维案例之---repmgr standby switchover故障
  10. [BZOJ3460]Jc的宿舍