Spring 6【数据校验Validation、JSR 303 和 Hibernate 实现】(十三)-全面详解(学习总结---从入门到深化)

news2024/9/27 15:33:53

 

目录

数据校验Validation

2.JSR 303 和 Hibernate 实现


 

数据校验Validation

1.数据校验介绍

数据校验分为客户端数据校验和服务端数据校验。都是为了保证数据完整性的。 客户端数据校验直接使用客户端脚本校验即可。例如在B/S模型项目中,可以选择使用JavaScript或 jQuery进行客户端数据校验。 在京东商城中,如果用户名和密码都没有输入,直接点击登录会提示输入账户名和密码,这就是客户端校验。

一个项目只有客户端数据校验是不严谨的,为了防止不法人员直接通过URL或HTTP工具非法访问服务端,发送非法数据,保险起见,服务端也应该具有数据校验,这种客户端和服务端都有数据校验时,称为双重校验。 

在服务端可以使用Spring框架的数据校验。无论是web环境和是非web环境都可以使用。 在Spring框架的数据校验主要用于web层,但是也可以应用在其他层。实现时需要借助Validator接口和 DataBinder进行实现。

2.Spring框架Validator接口使用 

在代码之前我们先来介绍一下Validator接口

public interface Validator {
    /**
     * 判断校验的类,如果支持对这个类的校验返回true,否则返回false
     * @return 是否支持当前类类型
     */
    boolean supports(Class<?> clazz);
    /**
     * 校验的具体逻辑
     * @param target 目标对象
     * @param errors 校验不同过后的错误信息。可以通过ValidationUtils快速校验和设置错误信息
     */
    void validate(Object target, Errors errors);
}

ValidationUtils是一个工具类,可以快速的判断一个属性是否为null、长度为0、获取全是空格,并把错误绑定上。

2.1 准备好一个实体类 

还是使用People类进行测试。里面给定两个属性。

package com.tong.validation;
import lombok.Data;

@Data
public class People {
      private String name;
      private int age;
}

2.2 新建校验类

新建com.tong.validation.MyValidator。类名和类所在的包都是随意定义的,没有强制要求。

public class MyValidator implements Validator {
     // 定义需要对哪个类进行校验
     @Override
     public boolean supports(Class<?> clazz) {
           if(clazz.equals(People.class)){
                   return true;
            }
         return false;
      }
     // 具体校验规则
     // 简单判断是否为空可以使用工具类。其他的校验规则需要自己定义
 
    @Override
    public void validate(Object target, Errors errors) {
      // rejectIfEmpty(Errors对象,“校验的属性”,"错误码,可以设置为null",“校验不通过时日志打印的消息”):为空校验不通过
      ValidationUtils.rejectIfEmpty(errors,"name",null,"姓名不能为空");
     // 如果希望判断其他逻辑,需要手动编写
     Object ageValue = errors.getFieldValue("age");// 获取age属性的值
     if(ageValue!=null){
           Integer age = Integer.parseInt(ageValue.toString());
           if(age<1||age>150){
              // rejectValue("校验的属性",“错误码”,"校验不通过时日志打印的消息"):表示属性校验不通过
               errors.rejectValue("age",null,"年龄必须是1-150之间的数字");
             }
         }
    }
}

 2.3 测试校验结果

在测试类中编写代码

@Test
void testValidator(){
     People people = new People();
     DataBinder dataBinder = new DataBinder(people);
     dataBinder.setValidator(new MyValidator());
     dataBinder.validate();
     BindingResult bindingResult = dataBinder.getBindingResult();
     bindingResult.getAllErrors().forEach(err->{
     System.out.println(err);
   });
}

2.JSR 303 和 Hibernate 实现

2.1 JSR介绍

JCP(Java Community Process)是一个开发的国际组织,里面包含了一些Java开发者和其他被允许加入的成员。JCP组织主要负责对Java社区进行发展和更新。维护的规范包含:J2ME、J2SE、J2EE、XML等相关规范。组织成员可以提交JSR(Java Specification Requests,Java 规范提案),待组织成员通过提案后会 把相关内容加入到下一个版本的规范中。

 2.2 JSR 303介绍

JSR每个提案都带有数字名称。例如JSR 107、JSR 303等。一定要注意的是,对于JSR提案并不是数字越大就需要包含前面内容。例如JSR 107主要是对缓存的提案、JSR 303是对数据校验的提案,这两个提案 不存在包含和被包含的关系,也不存在版本先后的关系。这个和我国政协会议是类似的,第一个政协委员提出的建议叫做建议1、第二个政协委员提出的建议是建议2。建议1建议提高个税起征点、建议2建议国家分配对象。这俩建议是没有关系的。 JSR 303是Java EE 6规范的子规范。叫做Bean Validation。这些规范都是注解。各大公司可以针对这些规范做具体实现。 在Java开发中使用的最多的JSR 303具体实现就是Hibernate框架中Hibernate-Validator。它对JSR 303的 所有约定(constraint)都做了实现,同时还进行了一定的扩充。

2.3 Hibernate Validator包含的内容 

Hiberante 框架是Java行业曾经风靡一时的ORM框架,目前在企业中只有一些老项目还在使用。 但Hibernate里面却有着一些很好的功能一直被使用。其中就包含hibernate-validator。 hibernate-validator对JSR 303实现都存在于依赖的Validation-api.jar的javax.validation.constraints包 中。 里面所有注解都包含message属性,表示校验不通过后日志打印的信息。但是不建议设置,因为默认的 提示信息就非常好。 Hibernate Validator对JSR 303具体实现的解释:

Hibernate-Validator还有除了JSR 303的额外补充,这些注解都在Hibernate-validator.jar的 org.hibernate.validator.constraints包中。 

 

2.4 hibernate-validator使用 

添加依赖

除了项目正常的依赖以外,额外需要导入Hibernate-validator依赖和EL表达式依赖。

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.0.Final</version>
</dependency>
<dependency>
    <groupId>jakarta.el</groupId>
    <artifactId>jakarta.el-api</artifactId>
    <version>5.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.el</artifactId>
    <version>5.0.0-M1</version>
</dependency>

在实体类属性上添加注解

示例中只是以NotNull和Length和Range进行举例。

(1)@NotNull中message是可选属性,如果设置了message,在违反规则后日志会打印message中内容

(2)@Length是设置字符串长度。

(3)@Range 设置取值范围。可以用在int类型属性上。 所以name必须不能是null的,且长度是2-6位。age取值范围必须是1~150 这些注解虽然可以放在方法、属性、其他注解、构造方法、参数上。我们多把这些注解放在实体类的属 性上面,每个实体类属性都支持配置多个注解,这些注解同时生效。

@Data
public class People {
     @NotNull(message = "姓名不能是null")
     @Length(min = 2,max = 6,message = "长度应该是2-6位")
     private String name;
     @Range(min=1,max=150)
     private int age;
}

编写测试类,测试hibernate-validator

@Test
void testHibernateValidator(){
    ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    Validator validator = factory.getValidator();
    People people = new People();
    Set<ConstraintViolation<People>> constraintViolations = validator.validate(people);
    for (ConstraintViolation<People> constraintViolation : constraintViolations)
     {
        System.out.println("错误:" + constraintViolation.getMessage());
    }
}

运行后控制台输出信息

错误:不能为null

错误:需要在1和150之间

3.Spring框架对Hibernate-validator的集成 

在Spring框架中有LocalValidatorFactoryBean类,这个类实现了ValidatorFactory接口和Validator接口。所以我们在Spring框架中可以直接使用这个类作为Validator实例化的对象。

通过使用LocalValidatorFactoryBean可以简化Hibernate实例化Validator的两行代码,其他使用方式都一样。

 

public class LocalValidatorFactoryBean extends SpringValidatorAdapter
implements ValidatorFactory, ApplicationContextAware, InitializingBean,
DisposableBean {

3.1 保证项目包含hibernate-validator依赖

在上面学习Hibernate-validator使用时已经导入过了

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.0.Final</version>
</dependency>
<dependency>
    <groupId>jakarta.el</groupId>
    <artifactId>jakarta.el-api</artifactId>
    <version>5.0.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.el</artifactId>
    <version>5.0.0-M1</version>
</dependency>

3.2 创建一个类

创建com.tong.validation.Student,添加几个注解进行测试

@Data
public class Student {
    @NotBlank
    private String name;
    @Positive
    private int age;
}

 3.3 编写配置

创建配置文件applicationContext-validation.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
  </bean>

   <bean id="student" class="com.tong.validation.Student"></bean>
</beans>

3.4 编写测试类

在com.tong.test.ValidationTest中测试

@SpringJUnitConfig
@ContextConfiguration("classpath:applicationContext-validation.xml")
public class ValidationTest {
    @Autowired
    LocalValidatorFactoryBean validator;
    @Autowired
    Student student;
    @Test
    void test(){
       Set<ConstraintViolation<Student>> constraintViolations = validator.validate(student);
       for (ConstraintViolation<Student> constraintViolation : constraintViolations) {
              System.out.println("错误:" + constraintViolation.getMessage());
           }
      }
}

 3.5 观察运行结果

在IDEA控制台可以看到

错误:不能为空
错误:必须是正数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/809188.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Flowable中间事件-中间信号捕获事件

定义 信号中间事件分为 Catching 事件和 Throwing 事件&#xff0c;即信号中间捕获事件&#xff08;Signal Intermediate Catch Event&#xff09;和信号中间抛出事件&#xff08;Signal Intermediate Throwing Event&#xff09;。 当流程执行到信号中间捕获事件时就会中断在…

ESP32(MicroPython) 四足机器人(一)

最近决定研究一下四足机器人&#xff0c;但市面上的产品&#xff0c;要么性价比低&#xff0c;要么性能达不到要求。本人就另外买了零件&#xff0c;安装到之前的一个麦克纳姆轮底盘的底板上。&#xff08;轮子作为装饰&#xff0c;使用铜柱固定&#xff09; 舵机使用MG996R&a…

Stability AI推出Stable Diffusion XL 1.0,文本到图像模型

Stability AI宣布推出Stable Diffusion XL 1.0&#xff0c;这是一个文本到图像的模型&#xff0c;该公司将其描述为迄今为止“最先进的”版本。 Stability AI表示&#xff0c;SDXL 1.0能生成更加鲜明准确的色彩&#xff0c;在对比度、光线和阴影方面做了增强&#xff0c;可生成…

在 Amazon EMR 上构建实时数据湖

前言 当公司业务发展遇到瓶颈时&#xff0c;业务分析师以及决策者们总会希望通过交叉分析大量的业务数据和用户行为数据&#xff0c;以解答“为什么利润会下滑&#xff1f;”“为什么库存周转变慢了&#xff1f;”等问题&#xff0c;最终整点“干货”出来从而促进业务发展。 …

一、Postfix[安装与配置、smtp认证、Python发送邮件以及防垃圾邮件方法、使用腾讯云邮件服务]

Debian 11 一、安装 apt install postfix 二、配置 1.dns配置 解释&#xff1a;搭建真实的邮件服务器需要在DNS提供商那里配置下面的dns 配置A记录mail.www.com-1.x.x.x配置MX记录www.com-mail.www.com 解释&#xff1a;按照上面的配置通常邮件格式就是adminwww.com其通过…

2023 年还推荐报计算机专业吗?

计算机科学是一个很好的专业&#xff0c;因为它由各种课程组成&#xff0c;为学生在成熟和新兴专业就业做好准备。以下是一些通常属于计算机科学专业的课程&#xff1a; 基本编程介绍了用于构建和维护数字架构和基础设施的编程语言和标准。 微积分为制定高级计算和设计概念提供…

使用vim-cmd工具给ESXi虚机定期打快照

VMware虚拟化 - 建设篇 第四章 使用vim-cmd工具给ESXi虚机定期打快照 VMware虚拟化 - 建设篇系列文章回顾使用vim-cmd工具给ESXi虚机定期打快照前言前提条件ESXi新增执行快照备份的sh脚本ESXi添加crond任务并使其生效ESXi指定部分虚拟机不执行定期快照(附加)虚拟机自定义属性…

【数据分享】1999—2021年地级市学校数、教师数和学生数(Shp/Excel格式)

在之前的文章中&#xff0c;我们分享过基于2000-2022年《中国城市统计年鉴》整理的1999-2021年地级市的人口相关数据、各类用地面积数据、污染物排放和环境治理相关数据、房地产投资情况和商品房销售面积、社会消费品零售总额和年末金融机构存贷款余额、地方一般公共预算收支状…

(树) 剑指 Offer 26. 树的子结构 ——【Leetcode每日一题】

❓剑指 Offer 26. 树的子结构 难度&#xff1a;中等 输入两棵二叉树 A 和 B&#xff0c;判断 B 是不是 A 的子结构。(约定空树不是任意一个树的子结构) B 是 A 的子结构&#xff0c; 即 A 中有出现和B相同的结构和节点值。 例如: 给定的树 A: 3/ \4 5/ \1 2给定的树 B&…

【Linux】用户相关内容

如果命令ll 出现以上信息&#xff0c;UID为具体的数字&#xff0c;代表之前UID为502的用户被删除了。 更改目录或文件所属用户和所属组 在Linux中&#xff0c;创建一个文件时&#xff0c;该文件的拥有者都是创建该文件的用户。 更改所属用户 chown 用户名 文件名/目录名 更…

【环境配置】Windows下WSL将ubuntu挪位置-系统盘清理

问题–垃圾太多&#xff0c;系统盘空间占用太大 最近 C 盘空间暴涨&#xff0c;用工具 WinDirStat-强烈推荐的工具 查看发现 WSL 子系统占用了6个多 G 的空间&#xff0c;遂想办法挪个位置&#xff1b; 【关键字】将 Windows 里的子系统挪到非系统盘 D 盘&#xff1b; 解决 打…

认清现实重新理解游戏的本质

认清现实重新理解游戏的本质 OVERVIEW 认清现实重新理解游戏的本质现实两条小路的启发四个动机1.当前的学习任务或工作任务太艰巨2.完美主义3.对未来太过于自信/无知4.大脑小看未来的收益 四个方法1.让未来的收益足够巨大2.让未来的收益感觉就在眼前3.玩游戏有恶劣的结果4.玩游…

转行车载做开发,首先得掌握好Android Framework~

前言 在当今社会&#xff0c;科技的快速发展推动了各行各业的变革。移动设备作为人们生活、工作、学习的重要工具&#xff0c;其市场份额逐年攀升。Android作为全球最受欢迎的移动操作系统之一&#xff0c;为开发者提供了广阔的发展空间。但是现在Android发展比较尴尬&#xf…

【Python基础】- 自定义函数和匿名函数(文末送书3本)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

Nginx下载、安装与使用

Nginx下载 简介&#xff1a; Nginx是一个高性能的HTTP和反向代理web服务器&#xff0c;同时也提供了IMAP/POP3/SMTP服务&#xff08;邮件服务&#xff09;。 官网下载地址&#xff1a; https://nginx.org/en/download.html 国内镜像地址&#xff1a; https://mirrors.huawe…

认识数组指针

文章目录 数组指针的定义数组指针的应用 数组指针的定义 类比 整形数组——存放整形的数组 指针数组——存放指针的数组 整形指针——存放整形地址的指针 数组指针——存放数组地址的指针 深度理解 在之前我们知道&#xff1a;数组名表示首元素地址&#xff0c;但是有&#xf…

iostat工具使用

文章目录 iostat命令简介iostat命令参数 iostat输出信息CPU利用率输出信息磁盘利用率输出信息更详细的磁盘利用率输出信息 iostat命令使用示例iostat -kdx 1 iostat数据来源相关参考 iostat命令简介 iostat工具可用于CPU使用统计信息和设备的输入输出统计信息。iostat能支持显…

操作系统专栏1-内存管理from 小林coding

操作系统专栏1-内存管理 虚拟地址内存管理方案分段分页页表单级页表多级页表TLB 段页式内存管理Linux内存管理 malloc工作方式操作系统内存回收回收的内存种类 预读失败和缓存污染问题预读机制预读机制失效解决方案缓存污染 内核对虚拟内存的表示内核对内核空间的表示直接映射区…

一个字符驱动示例 -- 微秒级别周期 反转GPIO

仅作为自我记录的一个demo 本次GPIO以微妙级别频率的反转实验有以下几个启示&#xff1a; 一开始在应用层做延时&#xff0c;来实现2微妙周期&#xff0c;占空比50%的GPIO反转&#xff0c;发现波形的频率一直上不去&#xff0c;只能在25hz徘徊&#xff0c;后来索性去掉延时&am…