SpringMVC(12)——数据验证

目录

概述

客户端验证

服务器端验证

Spring验证器

概述

实例

JSR 303验证

概述

标注类型

空检查

boolean检查

长度检查

日期检查

数值检查

实例


概述

对于用户输入的表单数据必须进行验证,以保证数据的合法性。

数据验证分为客户端验证和服务器端验证,客户端验证主要是过滤正常用户的误操作,通过JavaScript代码完成;服务器端验证是整个应用阻止非法数据的最后防线,通过在应用中编程实现。

客户端验证

客户端验证使用JavaScript进行验证:

  • 编写验证函数
  • 在提交表单的事件中调用验证函数
  • 根据验证函数来判断是否进行表单提交

服务器端验证

在spring mvc中,先进行数据类型的转换,然后再进行数据验证。

在Spring MVC框架中有两种方法可以验证输入数据,一种是利用Spring自带的验证框架,另一种是利用JSR 303实现。

Spring验证器

概述

创建自定义Spring验证器实现的Validator接口:

package springmvcdemo.validator;

import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

public class TestValidator implements Validator {
    @Override
    public boolean supports(Class<?> aClass) {
        // 当supports方法返回true时,验证器可以处理指定的Class
        return false;
    }

    @Override
    public void validate(Object object, Errors errors) {
        // 验证目标对象object,并将验证错误信息存入Errors对象
    }
}

往Errors对象存入错误消息的方法是reject或rejectValue,其方法有如下:

除此之外,还有ValidationUtils工具类,该类中有几个方法判断是否为空。

如:

if(student.getUsername()==null||student.getUsername().isEmpty()){
            errors.reject("username","student.username.required");
        }

使用ValidationUtils工具类后可以简化成如下代码:
 

ValidationUtils.rejectIfEmpty(errors,"username","student.username.required");

实例

创建springmvc项目并按照下图创建文件夹及文件:

说明:

验证要求:

  • 姓名必须填写;
  • 密码必须填写;
  • 年龄必须大于0岁,小于150岁

JSP页面

register.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>注册</title>
    <style>
        .red {
            color: red;
        }
    </style>
</head>
<body>
<form:form modelAttribute="student" action="/register" method="post">
    姓名:<form:input path="username"/><form:errors path="username" cssClass="red"/><br/>
    密码:<form:password path="password"/><form:errors path="password" cssClass="red"/> <br/>
    年龄:<form:input path="age"/><form:errors path="age" cssClass="red"/> <br/>
    <input type="reset">
    <input type="submit" value="注册"><br>
    <%--显示所有的错误--%>
    <form:errors path="*" cssClass="red"/>
</form:form>
</body>
</html>

studentsList.jsp

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<table>
    <tr>
        <td>姓名</td>
        <td>密码</td>
        <td>年龄</td>
    </tr>
    <c:forEach items="${studentsList}" var="student">
        <tr>
            <td>${student.username}</td>
            <td>${student.password}</td>
            <td>${student.age}</td>
        </tr>
    </c:forEach>
</table>
</body>
</html>

编写实体类

Student.java

package pojo;

public class Student {
    private String username;
    private String password;
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

编写验证器类

验证器类即是实现Validator接口。使用@Component注解将RegisterValidator类声明为验证组件。

RegisterValidator.java

package validator;

import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import pojo.Student;
@Component
public class RegisterValidator implements Validator {
    @Override
    public boolean supports(Class<?> aClass) {
        return Student.class.isAssignableFrom(aClass);
    }

    @Override
    public void validate(Object object, Errors errors) {
        Student student=(Student)object;
        ValidationUtils.rejectIfEmpty(errors,"username","student.username.required");
        ValidationUtils.rejectIfEmpty(errors,"password","student.password.required");
        if(student.getAge()<=0||student.getAge()>150){
            errors.rejectValue("age","age.invalid");
        }
    }
}

编写错误消息属性文件

errorMessages.properties

student.username.required=请输入用户名
student.password.required=请输入密码
age.invalid=年龄必须大于0岁,小于150岁

Unicode编码(IDEA将中文转换成Unicode编码需要进行配置)属性文件内容如下:

student.username.required=请输入用户名
student.password.required=请输入密码
age.invalid=年龄必须大于0岁,小于150岁

在属性文件创建完成后需要告诉Spring MVC从该属性文件中获取错误消息,则需要在配置文件中声明一个messageSource bean。因此,配置

<!-- 配置消息属性文件 -->   
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    	<property name="basename" value="/WEB-INF/resource/errorMessages"/>
    </bean>

springmvc-servlet.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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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:component-scan base-package="controller"/> 
    <context:component-scan base-package="service"/> 
    <context:component-scan base-package="validator"/>
    <!-- 注册格式化转换器,因为用到日期转换-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
    <mvc:annotation-driven conversion-service="conversionService"/>
    <!-- 配置消息属性文件 -->   
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    	<property name="basename" value="/WEB-INF/resource/errorMessages"/>
    </bean>
  	<!-- 配置视图解析器 -->
  	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
       <!-- 前缀 -->
       <property name="prefix" value="/WEB-INF/jsp/" />
       <!-- 后缀 -->
       <property name="suffix" value=".jsp" />
  </bean>
</beans>

编写Service层

RegisterService.java

package service;

import pojo.Student;

import java.util.ArrayList;

public interface RegisterService {
    boolean register(Student student);
    ArrayList<Student> getStudentsList();
}

RegisterServiceImpl.java

package service;

import org.springframework.stereotype.Service;
import pojo.Student;

import java.util.ArrayList;
@Service
public class RegisterServiceImpl implements RegisterService {
    static ArrayList<Student> students = new ArrayList<>();

    @Override
    public boolean register(Student student) {
        if (!"hello".equals(student.getUsername())) {
            students.add(student);
            return true;
        }
        return false;
    }

    @Override
    public ArrayList<Student> getStudentsList() {
        return students;
    }
}

编写控制器类

在该类中使用@Resource注解注入自定义验证器。

package controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import pojo.Student;
import service.RegisterService;

import javax.annotation.Resource;

@Controller
public class RegisterController {

    @Autowired
    private RegisterService registerService;

    @Resource
    private Validator validator;

    @RequestMapping("toRegister")
    public String toRegister(Model model) {
        model.addAttribute("student", new Student());
        return "register";
    }

    @RequestMapping("register")
    public String register(@ModelAttribute Student student, BindingResult result, Model model) {
        this.validator.validate(student, result);
        if (result.hasErrors()) {
            return "register";
        }
        registerService.register(student);
        model.addAttribute("studentsList", registerService.getStudentsList());
        return "studentsList";
    }

}

创建web.xml文件

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <!-- 避免中文乱码 -->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <param-name>encoding</param-name>
      <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
      <param-name>forceEncoding</param-name>
      <param-value>true</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>characterEncodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

运行效果

输入地址:http://localhost:8080/toRegister填写注册信息

如果什么也不填写,点击【注册】按钮,就会进行数据验证

如果只是填写一部分也会进行验证

填写全部数据,注册成功,验证通过。

 

如果对完整源码有兴趣。

可搜索微信公众号【Java实例程序】或者扫描下方二维码关注公众号获取更多。

注意:在公众号后台回复【CSDN201911161949】可获取本节源码。

 

JSR 303验证

概述

对于JSR 303验证,分别有两个实现:Hibernate Validator和Apache BVal。

这里使用的是Hibernate Validator,在使用之前要进行配置。

点击超链接:https://sourceforge.net/projects/hibernate/files/hibernate-validator/进行下载

点击蓝色版本后进入下载

即链接为:https://sourceforge.net/projects/hibernate/files/hibernate-validator/6.0.17.Final/hibernate-validator-6.0.17.Final-dist.zip/download

将下载压缩包解压

因此所需要的包为:

  • hibernate-validator-6.0.17.Final.jar
  • classmate-1.3.4.jar
  • javax.el-3.0.1-b09.jar
  • jboss-logging-3.3.2.Final.jar
  • validation-api-2.0.1.Final.jar

标注类型

JSR 303不需要编写验证器,使用标注类型即可。

空检查

  • @Null:验证对象是否为null。
  • @NotNull:验证对象是否不为null,无法检查长度为0的字符串。
  • @NotBlank:检查约束字符串是不是null,以及被trim后的长度是否大于0,只针
    对字符串,且会去掉前后空格。
  • @NotEmpty:检查约束元素是否为null或者是empty。

例:

// student.username.required为属性文件的错误代码        
@NotBlank(message="{student.username.required}")
private String username;

boolean检查

  • @AssertTrue:验证Boolean属性是否为true。
  • @AssertFalse:验证boolean属性是否为false。

例:

@AssertTrue
private boolean isLogin;

长度检查

  • @Size(min=,max=):验证对象(Arrya、Collection、Map、String)长度是否在给定的范围之内。
  • @Length(min=,max=):验证字符串长度是否在给定的范围之内。

例:

@Length(min=1,max=100)
private String memo;

日期检查

  • @Past:验证Date和Calendar对象是否在当前时间之前。
  • @Future:验证Date和Calendar对象是否在当前时间之后。
  • @Pattem:验证String对象是否符合正则表达式的规则。

例:

@Past(message="{birthDate.invalid}")
private Date birthDate;

数值检查

  • @Min:验证Number和String对象是否大于指定的值。
  • @Max:验证Number和String对象是否小于指定的值。
  • @DecimalMax:被标注的值必须不大于约束中指定的最大值,这个约束的参数是一
    个通过BigDecimal定义的最大值的字符串表示,小数存在精度。
  • @DecimalMin:被标注的值必须不小于约束中指定的最小值,这个约束的参数是一
    个通过BigDecimal定义的最小值的字符串表示,小数存在精度。
  • @Digits:验证Number和String的构成是否合法。
  • @Digits(integer=,fraction=):验证字符串是否符合指定格式的数字,integer指定整数
    精度,fraction指定小数精度。
  • @Range(min=,max=):检查数字是否介于min和max之间。
  • @Valid:对关联对象进行校验,如果关联对象是个集合或者数组,那么对其中的元
    素进行校验,如果是一个map,则对其中的值部分进行校验。
  • @CreditCardNumber:信用卡验证。
  • @Email:验证是否为邮件地址,如果为null,不进行验证,通过验证。

例:

@Range(min=0,max=100,message="{score.invalid}")
private float score;

实例

本项目中所要用到的jar包如下:

创建springmvc项目并按照下图创建文件夹及文件(也可以修改上面的实例项目代码)。

本项目和上面实例项目的区别是:不需要创建验证器类RegisterValidator,除实体类Student.java、控制器RegisterController.java及springmvc-servlet.xml配置文件不同之外,其他文件都是相同的。

实体类Student.java

package pojo;

import org.hibernate.validator.constraints.NotBlank;
import org.hibernate.validator.constraints.Range;

public class Student {
    @NotBlank(message = "{student.username.required}")
    private String username;
    @NotBlank(message = "{student.password.required}")
    private String password;
    @Range(min = 1, max = 150, message = "{age.invalid}")
    private int age;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

控制器类RegisterController.java

使用@Valid对实体对象进行验证。

package controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import pojo.Student;
import service.RegisterService;

import javax.annotation.Resource;
import javax.validation.Valid;

@Controller
public class RegisterController {

    @Autowired
    private RegisterService registerService;

    @Resource
    private Validator validator;

    @RequestMapping("toRegister")
    public String toRegister(Model model) {
        model.addAttribute("student", new Student());
        return "register";
    }

    @RequestMapping("register")
    public String register(@Valid @ModelAttribute Student student, BindingResult result, Model model) {
        this.validator.validate(student, result);
        if (result.hasErrors()) {
            return "register";
        }
        registerService.register(student);
        model.addAttribute("studentsList", registerService.getStudentsList());
        return "studentsList";
    }

}

配置文件springmvc-servlet.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"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    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:component-scan base-package="controller"/> 
    <context:component-scan base-package="service"/> 
    <!-- 注册格式化转换器,因为用到日期转换-->
    <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"/>
    <mvc:annotation-driven conversion-service="conversionService"/>

    <!--配置属性文件-->
    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <!--资源文件名-->
        <property name="basenames">
            <list>
                <value>/WEB-INF/resource/errorMessages</value>
            </list>
        </property>
        <!--资源文件编码格式-->
        <property name="fileEncodings" value="utf-8"/>
        <!--对资源文件内容缓存的时间,单位为秒-->
        <property name="cacheSeconds" value="120"/>
    </bean>
    <!--注册校验器-->
    <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <!--hibernate校验器-->
        <property name="providerClass" value="org.hibernate.validator.HibernateValidator"/>
        <!--指定校验使用的资源文件,在文件中配置校验错误信息,如果不指定则默认使用-->
        <property name="validationMessageSource" ref="messageSource"/>
    </bean>
    <!--开启Spring的Valid功能-->
    <mvc:annotation-driven conversion-service="conversionService" validator="validator"/>

  	<!-- 配置视图解析器 -->
  	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
       <!-- 前缀 -->
       <property name="prefix" value="/WEB-INF/jsp/" />
       <!-- 后缀 -->
       <property name="suffix" value=".jsp" />
  </bean>
</beans>

其他文件的代码可以查看上面的实例的内容,未修改的文件代码都是一样的,或者通过下面的二维码获取完整代码。

运行项目进行测试

通过地址:http://localhost:8080/toRegister访问注册页面

如果什么也不输入就会报验证错误提示

点击【注册】按钮注册成功

 

如果对完整源码有兴趣。

可搜索微信公众号【Java实例程序】或者扫描下方二维码关注公众号获取更多。

注意:在公众号后台回复【CSDN201911162115】可获取本节源码。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值