SpringMVC-表单验证

本文详细介绍了SpringMVC中如何进行表单数据的格式化和校验,包括`mvc:annotation-driven`配置、`InitBinder`注解、数据格式化的`@NumberFormat`和`@DateTimeFormat`注解、使用JSR303进行数据校验以及配置数据校验步骤。此外,还讲解了如何在页面上回显错误信息和定制错误信息,帮助开发者更好地实现表单验证和用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.mvc:annotation-driven
实际开发时建议都配置该参数。
配置<mvc:annotation-driven/>后,SpringMVC会自动注册RequestMappingHandlerMapping,
RequestMappingHandlerAdapter,ExceptionHandlerExceptionResolver三个bean。
还将提供一下支持
-支持用ConversionServices实例对表单参数进行类型转换,通过配置conversion-service属性自定义类型转换。
-支持使用@NumberFormat注解,@DateTimeFormat注解完成数据类型格式化
-支持使用@Valid注解对JavaBean实例进行JSR303验证
-支持使用@ReqeustBody和@ResponseBody注解
2.InitBinder注解
WebDataBinder用于完成表单字段到JavaBean属性的绑定,而@InitBinder注解则可以对WebDataBinder对象进行初始化,
以及数据设定的相关限制。被InitBinder注解修饰的方法不能有返回值,且参数通常为WebDataBinder。
如下例子,规定name属性不会被表单字段自动绑定。
package spring;

import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class TestController {
	
	@RequestMapping(value="/test", method=RequestMethod.GET)
	public String testGet(Map<String, Object>map){
		Person person = new Person();
		map.put("person", person);
		return "form";
	}
	
	@RequestMapping(value="/test", method=RequestMethod.POST)
	public String testPost(Person person){
		System.out.println(person);
		return "success";
	}
	
	@InitBinder
	public void testBinder(WebDataBinder dataBinder){
		dataBinder.setDisallowedFields("name");
	}
}
3.数据格式化

表单的数据转换是将字符串形式的表单数据转换为JavaBean对象,如果是简单的对象不需要格式,则不需要特殊指定,但是比如日期类型的格式,如果不指定,则无法进行格式化,因为不知道是2016/6/4格式,还是2016-6-4格式。为了让SpringMVC在进行格式化时知道具体的目标,只需要在JavaBean对象中使用合适的注解进行类型,格式化标注即可。

注解类型有:

-@NumberFormat
     有两个互斥的属性,style:Style.NUMBER 正常数字,Style.PERCENT 百分数,Style.CURRENCY 货币
     pattern:类型为String,可以进行自定义样式比如“#,###”

-@DateTimeFormat 可以对Date,Calendar,Long时间类型进行标注,有一个pattern属性,可以赋值比如“yyyy-MM-dd hh:mm:ss"的格式。

public class Person {
	@NumberFormat(pattern="##,##") //注意.是小数的关键字,不能用.分割。
	private Integer id;
	
	@DateTimeFormat(pattern="YYYY-mm-dd")
	private Date birth;

4.数据校验

使用JSR303进行校验,JSR303是Java为Bean数据合法性校验提供的标准框架,在JavaEE6.0中已经实现。
通过在JavaBean属性上加上注解,即可为属性提供校验功能。注解有如下内容

@Null 必须为空
@NotNull 必须非空
@AssertTrue 必须为True
@AssertFalse 必须为False
@Min(value)  @Max(value) 这两个注解的属性必须是数字,且大于等于最小,小于等于最大
@DecimalMin(value) @DecimalMax(value) 同上
@Size(max,min)被注解的属性必须在之间。
@Digits(Integer, fraction) 注解的属性为数字,且在可接受范围内
@Past被注解的属性必须是过去时间,比如生日
@Future 必须是以后的时间。
@Pattern(value) 必须是符合指定的正则表达式
HibernateValidator的实现中,在JSR303基础上还提供了下面的几个注解:
@Email 有效的Email
@Length 字符串必须在指定的长度内
@NotEmpty 非空
@Range 元素必须在有效范围内。

5.配置数据校验步骤
1)SpringMVC的配置文件中需要加入<mvc:annotation-driven/>配置,这个配置用来装配LocalValidatorFactoryBean。
2)由于Spring中没有实现JSR303,所以需要加入其他实现的jar包
hibernate-validator-5.2.4.Final.jar
hibernate-validator-annotation-processor-5.2.4.Final.jar
hibernate-validator-cdi-5.2.4.Final.jar
lib/required/validation-api-1.1.0.Final.jar
lib/required/jboss-logging-3.2.1.Final.jar
lib/required/classmate-1.1.0.jar
3)在Person Bean的name属性上添加@NotEmpty注解
4)在RequestMapping注解的方法参数上添加@Valid注解。
public String testValidator(@Valid Person person)
5)注意下面例子中, 参数①要验证的person,②验证结果personValidateResult之间不能有其他参数。

	@RequestMapping(value="/test", method=RequestMethod.POST)
	public String testValidate(@Valid Person person, /*BindingResult error,*/ BindingResult personValidateResult){
		if(personValidateResult.getErrorCount() > 0){
			System.out.println("Error");
			for(FieldError fieldError:personValidateResult.getFieldErrors()){
				System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
				return "form";
			}
		}else{
			System.out.println(person);
		}
		return "success";
	}
6.在页面上回显错误信息

只需要使用<form:errors path="指定属性的错误信息">即可在网页中回显。

7.定制错误信息
每个属性的数据绑定和数据校验发生错误时,都会生成一个对应的FieldError对象。
当一个属性校验失败后,校验框架会为该属性生成四个错误消息代码。注解前缀,ModelAttribute,属性名即属性类型名:以Person类中name属性标注了@Pattern注解为例,会生成一下四个错误代码
  -Pattern.person.name //注意person是Person类定义的实际变量参数的名字
  -Pattern.name
  -Pattern.java.lang.String
  -Pattern
当使用SpringMVC进行错误显示时,会查看WEB上下文是否制定了国际化配置,有则用,无则显示默认值。
另外三个特殊的信息:
  -@RequiredParam() 参数不存在的错误,用required.前缀
  -数据绑定类型错误时,typeMismatch前缀
  -methodInvocation:SpringMVC在调用处理方法时发生错误
完整的代码清单如下:
1.Person Bean的定义
package spring;

import java.util.Date;

import javax.validation.constraints.Past;

import org.hibernate.validator.constraints.NotEmpty;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.format.annotation.NumberFormat;

public class Person {
	@NumberFormat(pattern="##,##") //注意.是小数的关键字,不能用.分割。
	private Integer id;
	
	@Past //表单校验,生日必须发生在今天以前
	@DateTimeFormat(pattern="YYYY-mm-dd") //数据格式化
	private Date birth;
	
	@NotEmpty //表单校验,名字不能为空
	private String name;

	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Date getBirth() {
		return birth;
	}
	public void setBirth(Date birth) {
		this.birth = birth;
	}
	public Person(Integer id, String name, Date birth) {
		super();
		this.id = id;
		this.name = name;
		this.birth = birth;
	}
	
	public Person(){}
	@Override
	public String toString() {
		return "Person [id=" + id + ", name=" + name + ", birth=" + birth + "]";
	}
}
2.配置文件
<?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/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
		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-4.2.xsd">

	<context:component-scan base-package="spring"></context:component-scan>
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/views/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>

	<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
		<property name="basename" value="i18n"></property>
	</bean>
	
	<mvc:default-servlet-handler/>
	<mvc:annotation-driven></mvc:annotation-driven>
</beans>
3.i18n.properties
在配置文件中指定了basename为i18n,则必须定义i18n.properties的配置文件。由于是UTF-8的,汉字都会被转码

NotEmpty.person.name=\u4EBA\u7684\u540D\u5B57\u4E0D\u80FD\u4E3A\u7A7A //<span style="color:red;">人的名字不能为空</span>
Past.person.birth=\u51FA\u751F\u65E5\u671F\u6709\u95EE\u9898 //<span style="color: red; font-family: Arial, Helvetica, sans-serif; font-size: 12px;">出生日期有问题</span>
4.index.jsp
<body>
	<a href="/spring/test">Add New</a>
</body>
5.form.jsp
用<form:xxx>定义表单成员时,必须配置modelAttribute,或者使用默认的command。为了获取这个数据,必须先经过下面@RequestMapping中先设置command,或者modelAttribute的数据,然后经过转发跳转到该页面。
form:errors用来回显错误信息。
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page import="java.util.Map,java.util.HashMap" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
	<form:form method="POST" action="/spring/test" modelAttribute="person">
		ID:<form:input path="id"/><font color="red"><form:errors path="id"/></font><br>
		Name:<form:input path="name"/><font color="red"><form:errors path="name"/></font><br>
		birth:<form:input path="birth"/><font color="red"><form:errors path="birth"/></font><br>
		<input type="submit" value="submit">
	</form:form>
</body>
</html>
6.控制器代码
package spring;
import java.util.Map;
import javax.validation.Valid;

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.bind.annotation.RequestMethod;

@Controller
public class TestController {
	@RequestMapping(value="/test", method=RequestMethod.GET)
	public String testGet(Map<String, Object>map){
		Person person = new Person();
		map.put("person", person);
		return "form";
	}
	
	@RequestMapping(value="/test", method=RequestMethod.POST)
	public String testValidate(@Valid Person person, /*BindingResult error,*/ BindingResult personValidateResult){
		if(personValidateResult.getErrorCount() > 0){
			System.out.println("Error");
			for(FieldError fieldError:personValidateResult.getFieldErrors()){
				System.out.println(fieldError.getField() + ":" + fieldError.getDefaultMessage());
				return "form";
			}
		}else{
			System.out.println(person);
		}
		return "success";
	}
}
<完>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值