SpringMVC 学习(十一)之数据校验

目录

[1 数据校验介绍](#1 数据校验介绍)

[2 普通校验](#2 普通校验)

[3 分组校验](#3 分组校验)

[4 参考文档](#4 参考文档)


1 数据校验介绍

在实际的项目中,一般会有两种校验数据的方式:客户端校验和服务端校验

  • 客户端校验:这种校验一般是在前端页面使用 JS 代码进行校验,主要是验证输入数据的合法性,不合法的数据则没有必要再发送至服务端了。前端校验可以有效的提高用户体验,但是无法确保数据完整性,因为前端用户可以方便的拿到请求地址,然后直接发送请求,传递非法参数
  • 服务端校验:可以有效的保证数据安全与完整性,但是用户体验要差一点,所以客户端校验和服务端校验通常两者结合使用

SpringMVC 提供了两种方法来对用户的输入数据进行校验:一种是 SpringMVC 自带的 Validation 校验框架,它提供了简洁的注解和验证规则,易于使用,并且与 SpringMVC 框架集成良好;另一种是利用 JRS-303 验证框架进行验证,JRS-303 验证框架的优势在于它的灵活性和可扩展性,可以与其他框架或技术进行集成。

注解 作用
@Null 标注的属性必须为null
@NotNull 标注的属性必须不为null
@AssertTrue 标注的属性必须为true
@AssertFalse 标注的属性必须为false
@Min(value) 标注的属性必须是一个数字,并且其值必须大于或等于value
@Max(value) 标注的属性必须是一个数字,并且其值必须小于或等于value
@DecimalMin(value) 必须大于或等于value
@DecimalMax(value) 必须小于或等于value
@Size(max,min) 大小必须在max和min限定的范围内
@Digits(integer,fratction) 值必须是一个数字,且必须在可接受的范围内
@Past 只能用于日期型,且必须是过去的日期
@Future 只能用于日期型,且必须是将来的日期
@Pattern(value) 必须符合指定的正则表达式
@Email 必须是格式正确的Email地址
@Length 被注释的字符串大小必须在指定的范围内
@NotEmpty 被注释的字符串不能是空字符串
@Range 被注释的元素必须在指定的范围内

@NotEmpty、@NotNull 和 @NotBlank 三种的区别:

  • @NotNull:一般用在基本数据类型上(包括包装类),对象不能为 null,但可以为 empty,即为空集(size = 0)。
  • @NotEmpty:可以作用在 String、List、Map 和 Array 等,对象不能为 null,而且长度必须大于0 (size > 0)
  • @NotBlank:只能作用在 String 上,不能为 null,而且调用 trim() 后,长度必须大于 0 ,即必须有实际字符

2 普通校验

导入依赖

XML 复制代码
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.2.0.Final</version>
</dependency>

在 SpringMVC 配置文件中配置校验器并注入到处理器适配器中

XML 复制代码
<!-- 配置MVC注解驱动,配置注入校验器 -->
<mvc:annotation-driven validator="validator"/>

<!-- 配置校验器 -->
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
    <!-- 校验器-->
    <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
    <!-- 指定校验使用的资源文件,如果不指定则默认使用classpath下的ValidationMessages.properties -->
    <property name="validationMessageSource" ref="messageSource"/>
</bean>
<!-- 校验错误信息配置文件 -->
<bean id="messageSource"
      class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <!-- 资源文件名-->
    <property name="basenames">
        <list>
            <value>classpath:CustomValidationMessages</value>
        </list>
    </property>
    <!-- 资源文件编码格式 -->
    <property name="defaultEncoding" value="utf-8"/>
    <!-- 对资源文件内容缓存时间,单位秒 -->
    <property name="cacheSeconds" value="120"/>
</bean>

创建 CustomValidationMessages.properties 配置文件,和上述代码中的校验错误信息配置文件名对应 (也可以将错误提示信息放在一个类中)

XML 复制代码
#添加校验错误提示信息
user.id.isEmpty="用户的ID不能为空!"
user.userName.isEmpty="用户名不能为空!"
user.userName.length="用户名为1~6个字符!"
user.userPwd.isEmpty="密码不能为空!"
user.userPwd.length="密码的长度为5~15个字符!"
user.userEmail.isEmpty="邮箱不能为空!"
user.userEmail.format="输入的邮箱格式不正确!"

需要校验的类 User

java 复制代码
public class User {

    @NotNull(message = "{user.id.isEmpty}")
    private Integer id;

    @NotEmpty(message = "{user.userName.isEmpty}")
    @Length(min = 1, max = 6, message = "{user.userName.length}")
    private String userName;

    @NotEmpty(message = "{user.userPwd.isEmpty}")
    @Length(min = 5, max = 15, message = "{user.userPwd.length}")
    private String userPwd;

    @NotEmpty(message = "{user.userEmail.isEmpty}")
    @Email(message = "{user.userEmail.format}")
    private String userEmail;

    // 省略了 Getter、Setter 方法

校验控制器

@Validated 注解和 BindingResult 是成对出现的,中间不能穿插其它的形参,否则会报 400错误,其他形参只能加在它们后面

java 复制代码
@Controller
public class ValidateController {

    @ResponseBody
    @RequestMapping("/validate")
    // 形参前面加上 @Validated 注解表示这个实体类需要进行数据校验
    // BindingResult 封装数据绑定的校验结果
    public void validate(@Validated User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            //校验未通过,获取所有的异常信息并展示出来
            List<ObjectError> allErrors = bindingResult.getAllErrors();
            for (ObjectError allError : allErrors) {
                System.out.println(allError.getObjectName() + ":" + allError.getDefaultMessage());
            }
        }
    }
}

index.jsp

<input name="userName"/> 与 private String userName; 对应

java 复制代码
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>添加用户</title>
    </head>
    <body>
        <form action="${pageContext.request.contextPath}/validate" method="post">
            ID号:<input type="text" name="id" placeholder="请输入ID号"/> <br>
            姓名:<input type="text" name="userName" placeholder="请输入姓名"/> <br>
            密码:<input type="password" name="userPwd" placeholder="请输入密码"/> <br>
            邮箱:<input type="text" name="userEmail" placeholder="请输入邮箱"/> <br>
            <input type="submit" value="提交" />
        </form>
    </body>
</html>

执行结果

3 分组校验

某个属性设置了多种 数据校验,可以将这些校验 分组 ,然后 Controller 方法选择校验分组对数据进行校验

首先定义校验组,所谓的校验组,它其实就是空接口:

java 复制代码
// 分组校验接口1
public interface ValidationGroup1 {
}

// 分组校验接口2
public interface ValidationGroup2 {
}

对校验进行分组

java 复制代码
public class User {

    // groups属性表示校验属于哪个组,可以定义多个
    @NotNull(message = "{user.id.isEmpty}", groups = {ValidationGroup2.class})
    private Integer id;

    @NotEmpty(message = "{user.userName.isEmpty}", groups = {ValidationGroup1.class, ValidationGroup2.class})
    @Length(min = 1, max = 6, message = "{user.userName.length}", groups = {ValidationGroup1.class, ValidationGroup2.class})
    private String userName;

    @NotEmpty(message = "{user.userPwd.isEmpty}", groups = {ValidationGroup1.class})
    @Length(min = 5, max = 15, message = "{user.userPwd.length}", groups = {ValidationGroup1.class})
    private String userPwd;

    @NotEmpty(message = "{user.userEmail.isEmpty}", groups = {ValidationGroup2.class})
    @Email(message = "{user.userEmail.format}", groups = {ValidationGroup2.class})
    private String userEmail;

    // getter setter 构造器 toString 省略...
}

执行结果

4 参考文档

SpringMVC入门学习(十五)----数据校验 - 唐浩荣 - 博客园 (cnblogs.com)

springMVC如何对输入数据校验实现代码_java_脚本之家 (jb51.net)

相关推荐
_BugMan11 分钟前
【IDEA】干活?一个IDEA即可,集成开发平台打造攻略
java·ide·intellij-idea
YA3331 小时前
java设计模式二、工厂
java·开发语言·设计模式
金色天际线-1 小时前
Nginx 优化与防盗链配置指南
java·后端·spring
我爱挣钱我也要早睡!2 小时前
Java 复习笔记
java·开发语言·笔记
AD钙奶-lalala4 小时前
Mac OS上搭建 http server
java
知识分享小能手5 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
茯苓gao7 小时前
STM32G4 速度环开环,电流环闭环 IF模式建模
笔记·stm32·单片机·嵌入式硬件·学习
是誰萆微了承諾8 小时前
【golang学习笔记 gin 】1.2 redis 的使用
笔记·学习·golang
皮皮林5518 小时前
SpringBoot 全局/局部双模式 Gzip 压缩实战:14MB GeoJSON 秒变 3MB
java·spring boot
weixin_456904278 小时前
Spring Boot 用户管理系统
java·spring boot·后端