专栏首页程序猿的大杂烩在SpringMVC中使用数据验证组件——hibernate-validator

在SpringMVC中使用数据验证组件——hibernate-validator

在做web开发的时候,经常需要对客户端发送过来的数据进行一个验证,以防数据不合法。而SpringMVC支持的数据校验是JSR303的标准,通过在bean的属性上打上annotation @NotNull @Max等注解进行验证。JSR303提供有很多annotation借口,而SpringMVC对于这些验证是使用hibernate的实现,所以我们需要添加hibernate的一个validator包:

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

Spring配置文件内容如下:

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

    <context:annotation-config/>
    <context:component-scan base-package="org.zero01"/>
    <mvc:annotation-driven/>

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/" p:suffix=".jsp"
    />

</beans>

hibernate除了JSR303的标准之外还额外提供了其他的验证注解。下表是JSR303支持的验证注解:

Hibernate Validator 附加的注解:

下面我们来写个小demo,具体演示一下如何使用。例如,我要验证一些字段不能为空,那么就可以使用@NotNull这个注解,如下示例:

package org.zero01.test;

import javax.validation.constraints.NotNull;

public class UserRegister {

    @NotNull(message = "用户名不能为空")
    private String userName;
    @NotNull(message = "密码不能为空")
    private String password;
    @NotNull(message = "联系地址不能为空")
    private String address;
    @NotNull(message = "电话号码不能为空")
    private String phone;
    ...getter and setter...

在控制器的方法参数中,需要通过声明BindingResult参数来获得验证出错的信息,然后使用@Valid注解来配置哪个pojo对象需要校验,控制器代码如下:

package org.zero01.test;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.validation.Valid;

@Controller
public class Test {

    @RequestMapping(value = "/test.do", method = RequestMethod.GET)
    // 注意,@Valid和BindingResult是配对出现,并且形参顺序是固定的(一前一后),不然就会返回400状态码
    public String test(@Valid UserRegister userRegister, BindingResult bindingResult, Model model) {
        // 判断是否有异常
        if (bindingResult.hasErrors()) {
            System.out.println("客户端的请求数据异常,所有的异常如下:");
            // 取出所有的异常对象
            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                // 打印异常的字段以及异常信息
                System.out.println(fieldError.getField() + " : " + fieldError.getDefaultMessage());
            }
            return "register";
        }
        return "index";
    }
}

使用Postman进行访问,什么参数都不写:

控制台输出结果如下:

客户端的请求数据异常,所有的异常如下:
address : 联系地址不能为空
userName : 用户名不能为空
password : 密码不能为空
phone : 电话号码不能为空

下面再来演示一下其他常用的注解:

package org.zero01.test;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

public class UserRegister {

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

    @NotNull(message = "密码不能为空")
    @Length(max = 12, min = 6, message = "密码长度需在6-12位之间")
    private String password;

    @NotNull(message = "联系地址不能为空")
    private String address;

    @NotNull(message = "电话号码不能为空")
    // 指定正则表达式验证格式
    @Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\d{8}$", message = "电话号码格式错误")
    private String phone;

    @Email(message = "邮箱格式错误")
    private String email;

    @Size(max = 10, min = 1, message = "成绩单列表长度需在1-10之间")
    public List resultList;
    ...getter and setter...

控制器代码和之前一致,略。

使用Postman进行访问,如下:

控制台输出结果如下:

客户端的请求数据异常,所有的异常如下:
address : 联系地址不能为空
userName : 用户名不能为空
password : 密码长度需在6-12位之间
phone : 电话号码格式错误
email : 邮箱格式错误
resultList : 成绩单列表长度需在1-10之间

以上我们都是对所有的字段进行验证,如果我希望有些字段不被验证或者分开验证该怎么办呢?这时候我们就需要到分组验证了,首先编写一个接口:

package org.zero01.test;

public interface Group {
}

然后在需要分组的字段上的注解中加上groups属性,该属性的值为以上我们所定义的接口类,如下示例:

package org.zero01.test;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.Length;

import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;

public class UserRegister {

    // groups 属性用于指定分组,值为一个接口类
    @NotNull(message = "用户名不能为空", groups = Group.class)
    private String userName;

    @NotNull(message = "密码不能为空", groups = Group.class)
    @Length(max = 12, min = 6, message = "密码长度需在6-12位之间", groups = Group.class)
    private String password;

    @NotNull(message = "联系地址不能为空")
    private String address;

    @NotNull(message = "电话号码不能为空")
    @Pattern(regexp = "^((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\\\\d{8}$", message = "电话号码格式错误")
    private String phone;

    @Email(message = "邮箱格式错误")
    private String email;
    ...getter and setter...

控制器代码如下:

package org.zero01.test;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.validation.Valid;

@Controller
public class Test {

    @RequestMapping(value = "/test.do", method = RequestMethod.GET)
    // 分组的情况下需要使用Validated注解来指定接口
    public String test(@Validated(Group.class) UserRegister userRegister, BindingResult bindingResult, Model model) {

        if (bindingResult.hasErrors()) {
            System.out.println("客户端的请求数据异常,所有的异常如下:");

            for (FieldError fieldError : bindingResult.getFieldErrors()) {
                System.out.println(fieldError.getField() + " : " + fieldError.getDefaultMessage());
            }
            return "register";
        }
        return "index";
    }
}

访问方式和之前一致,略。

控制台输出结果如下:

客户端的请求数据异常,所有的异常如下:
password : 密码长度需在6-12位之间
userName : 用户名不能为空

如上,从控制台的打印结果中,可以看到只有password以及userName两个字段受到了验证,这是因为我们只在这两个字段上的注解中指定了groups 属性。所以分组验证就是只验证指定组的字段,而这个组的划分是以接口来划分的。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Spring Cloud 集成 RabbitMQ

    前言:我们现在有一个用微服务架构模式开发的系统,系统里有一个商品服务和订单服务,且它们都是同步通信的。

    端碗吹水
  • SpringMVC中用于绑定请求数据的注解以及配置视图解析器

    在上一篇文章中我们简单介绍了@RequestMapping与@RequestParam注解,知道了如何去配置地址映射,本篇则介绍一些用于处理request数据的...

    端碗吹水
  • Spring Batch快速入门

    Spring Batch简单来说就是一个轻量级的批处理框架,从名字就可以知道它是Spring 的子项目。我们在企业开发中可能会面临到一些需要处理较大数据量的场景...

    端碗吹水
  • Mybatis+Thymeleaf前端显示时间格式问题解决方法

    我的开发工具是IntelliJ IDEA,然后在SpringBoot集成Mybatis,前端用模块引擎Thymeleaf的过程中遇到几个问题,不过也花了点时间,...

    SmileNicky
  • Spring Cloud Gateway 读取、修改请求体(解决request body内容被截断)

    微服务架构,在网关服务里拦截每个请求,进行日志信息记录与管理,发现当请求体过长时,只能获取到一部分body,查看拦截过滤器,发现Spring Cloud Gat...

    一滴水的眼泪
  • springboot缓存之使用redis作为缓存管理

    (1)使用docker安装redis,可参照之前的docker安装使用,然后输入以下命令下载安装redis镜像。

    西西嘛呦
  • FreeMarker整合Springmvc

    用户5927264
  • Springboot 整合RabbitMQ ---基于Class的开发

    用户5927264
  • Spring Cloud学习(3)——服务发现与消费以及客户端负载均衡Ribbon

    在《Spring Cloud学习(2)——高可用Eureka Server》中,我搭了一个双节点的服务注册中心集群。

    胡了了
  • Spring Batch快速入门

    Spring Batch简单来说就是一个轻量级的批处理框架,从名字就可以知道它是Spring 的子项目。我们在企业开发中可能会面临到一些需要处理较大数据量的场景...

    端碗吹水

扫码关注云+社区

领取腾讯云代金券