Spring MVC通过自定义JSP表单标签库提供了表单处理方法,要想使用该库内的标签,需要在JSP文件中添加该标签库的定义
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
此处把mvc定义为标签库的前缀,使用标签库内标签时遵循
下用一个处理用户注册表单的例子来示范这些标签的使用
首先使用maven创建webapp工程,将servlet版本调整至3.1,工程最终目录结构如下
pom.xml配置上一节已经讲过,现在继续先在web.xml中定义DispatcherServlet。
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>springmvcservlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServletservlet-class>
<load-on-startup>1load-on-startup>
servlet>
<servlet-mapping>
<servlet-name>springmvcservlet-name>
<url-pattern>*.mvcurl-pattern>
servlet-mapping>
web-app>
然后在springmvc-servlet.xml文件中配置好DispatcherServlet
<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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="com.lonelyquantum.wileybookch3" />
<context:annotation-config />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
bean>
beans>
储存数据所用的User类以及存放性别数据使用的Gender枚举如下
public class User {
private String name;
private String lastname;
private String password;
private String detail;
@DateTimeFormat(pattern="yyyy-MM-dd")
private LocalDate birthDate;
private Gender gender;
private String country;
private boolean nonSmoking;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public LocalDate getBirthDate() {
return birthDate;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public Gender getGender() {
return gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public boolean isNonSmoking() {
return nonSmoking;
}
public void setNonSmoking(boolean nonSmoking) {
this.nonSmoking = nonSmoking;
}
}
public enum Gender {
Male,
Female,
Other,
RefuseToAnswer;
}
此处为了照顾性少数者,性别栏添加了Other和RefuseToAnswer两项
然后就可以创建作为控制器的UserController类了。
@Controller
public class UserController {
private static final String[] countries = { "Turkey", "United States", "Germany", "China", "Japan", "The United Kingdom" };
@RequestMapping(value = "/form")
public ModelAndView user() {
ModelAndView modelAndView = new ModelAndView("userForm", "user", new User());
modelAndView.addObject("genders", Gender.values());
modelAndView.addObject("countries", countries);
return modelAndView;
}
@RequestMapping(value = "/result")
public ModelAndView processUser(User user) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("userResult");
modelAndView.addObject("u", user);
return modelAndView;
}
}
添加了几个国家~
两个方法分别返回注册界面和注册结果界面,下面就是这两个界面的JSP文件
注册界面userForm.jsp
<%@ page contentType="text/html; charset=ISO-8859-1" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<html>
<head>
<title>Spring MVC Form Handlingtitle>
head>
<body>
<h2>User Registration Formh2>
<mvc:form modelAttribute="user" action="result.mvc">
<table>
<tr>
<td><mvc:label path="name">Namemvc:label>td>
<td><mvc:input path="name" />td>
tr>
<tr>
<td><mvc:label path="lastname">Last Namemvc:label>td>
<td><mvc:input path="lastname" />td>
tr>
<tr>
<td><mvc:label path="password">Passwordmvc:label>td>
<td><mvc:password path="password" />td>
tr>
<tr>
<td><mvc:label path="detail">Detailmvc:label>td>
<td><mvc:textarea path="detail" />td>
tr>
<tr>
<td><mvc:label path="birthDate">Birth Datemvc:label>td>
<td><mvc:input path="birthDate" />td>
tr>
<tr>
<td><mvc:label path="gender">Gendermvc:label>td>
<td><mvc:radiobuttons path="gender" items="${genders}" />td>
tr>
<tr>
<td><mvc:label path="country">Countrymvc:label>td>
<td><mvc:select path="country" items="${countries}" />td>
tr>
<tr>
<td><mvc:label path="nonSmoking">Non Smokingmvc:label>td>
<td><mvc:checkbox path="nonSmoking" />td>
tr>
<tr>
<td colspan="2">
<input type="submit" value="Submit" />
td>
tr>
table>
mvc:form>
body>
html>
首先通过
表单中用
以上标签之前都有
最后用(HTML的标签)定义了表单提交的按钮。
接下来,类似地创建userResult.jsp来显示用户输入的注册信息
<%@ page contentType="text/html; charset=ISO-8859-1" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<html>
<head>
<title>Spring MVC Form Handlingtitle>
head>
<body>
<h2>User Registration Resulth2>
<table>
<tr>
<td>Nametd>
<td>${u.name}td>
tr>
<tr>
<td>Last nametd>
<td>${u.lastname}td>
tr>
<tr>
<td>Passwordtd>
<td>${u.password}td>
tr>
<tr>
<td>Detailtd>
<td>${u.detail}td>
tr>
<tr>
<td>Birth Datetd>
<td>${u.birthDate}td>
tr>
<tr>
<td>Gendertd>
<td>${u.gender}td>
tr>
<tr>
<td>Countrytd>
<td>${u.country}td>
tr>
<tr>
<td>Non-Smokingtd>
<td>${u.nonSmoking}td>
tr>
table>
body>
html>
注意此时从UserController传入视图的是一个被命名为“u”的User实例,在视图中通过${u.xxx}来获得其属性。
将项目部署到Tomcat服务器并运行,在浏览器中输入http://localhost:8080/FormRegister/form.mvc得到如下页面
单击Submit按钮跳转至信息显示页面
刚才的例子中已经用到了一系列注解,此处将解释他们的作用
在域类的属性上添加如下注解可以定义他们应当通过的验证:
我们在User类中用以上注解来规定几个属性的限制条件
public class User {
@Size(min=3, max=20,message = "error.username")
String username;
@Email
String email;
@CreditCardNumber(message = "error.ccNumber")
String ccNumber;
@Pattern(regexp = "^[a-zA-Z]\\w{3,14}$",message = "error.password")
String password;
//getters and setters
}
启动验证需要在pom.xml中添加如下依赖
<dependency>
<groupId>org.hibernategroupId>
<artifactId>hibernate-validatorartifactId>
<version>6.0.2.Finalversion>
dependency>
为了在输入注册信不满足条件的时候返回注册界面显示错误信息,processUser方法需要进行修改
@Controller
public class UserController {
@RequestMapping(value = "/form")
public ModelAndView user() {
return new ModelAndView("userForm", "user", new User());
}
@RequestMapping(value = "/result", method= RequestMethod.POST)
public ModelAndView processUser(@Valid User user, BindingResult result) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("u", user);
if (result.hasErrors()) {
modelAndView.setViewName("userForm");
}
else {
modelAndView.setViewName("userResult");
}
return modelAndView;
}
}
其中的@Valid注解用于触发对user参数的验证,且方法接受一个BindingResult实例作为输入参数来检查验证是否有误,有误则返回添加了错误信息的注册界面
为了配置验证,还要在Web上下文中添加LocalValidatorFactoryBean和ReloadableResourceBundleMessageSource的定义,以及在mvc命名空间的annotation-driven标签中定义验证程序
<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-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<context:component-scan base-package="com.lonelyquantum.wileybookch3" />
<context:annotation-config />
<mvc:annotation-driven validator="validator" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/pages/" />
<property name="suffix" value=".jsp" />
bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename" value="classpath:messages" />
bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
<property name="validationMessageSource" ref="messageSource"/>
bean>
beans>
加入了Bean验证后的userForm.jsp文件如下
<%@ page contentType="text/html; charset=ISO-8859-1" %>
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
<html>
<head>
<title>Spring MVC Form Validationtitle>
<style type="text/css">
.formFieldError { background-color: #FFC; }
style>
head>
<body>
<h2>User Registration Formh2>
<mvc:form modelAttribute="user" action="result.mvc">
<table>
<tr>
<td><mvc:label path="username">User Namemvc:label>td>
<td><mvc:input path="username" cssErrorClass="formFieldError" />td>
<td><mvc:errors path="username" />td>
tr>
<tr>
<td><mvc:label path="email">E-Mailmvc:label>td>
<td><mvc:input path="email" cssErrorClass="formFieldError" />td>
<td><mvc:errors path="email" />td>
tr>
<tr>
<td><mvc:label path="ccNumber">Credit Card Numbermvc:label>td>
<td><mvc:input path="ccNumber" cssErrorClass="formFieldError" />td>
<td><mvc:errors path="ccNumber" />td>
tr>
<tr>
<td><mvc:label path="password">Passwordmvc:label>td>
<td><mvc:password path="password" cssErrorClass="formFieldError" />td>
<td><mvc:errors path="password" />td>
tr>
<tr>
<td colspan="3">
<input type="submit" value="Submit" />
td>
tr>
table>
mvc:form>
body>
html>
其中每一个样式的errors标签的path都被设置为模型类的属性名称,不设置则看不到相关输入字段的错误消息,想要在一个地方显示所有错误可将path值设置为*。例子中还定义了样式表类formFieldError,并将每个输入字段的cssErrorClass特性设置为该类,开头通过style标签将该类字段背景设置为黄色。
验证注解中使用message属性返回对应的错误消息,消息所在位置由ReloadableResourceBundleMessageSource设定,此处为src/main/resource文件夹下的message.property文件。
Pattern.user.password=Password should meet the requirements.
Size.user.username=Size must be between 3 and 20.
CreditCardNumber.user.ccNumber=invalid credit card number.
不难发现message.property文件中定义错误消息的格式为 注解名.实例名.属性名 = 错误消息内容
在浏览器中输入http://localhost:8080/BeanValidator/result.mvc,直接提交空表单可以获得如下结果
可看到未通过验证的输入栏背景变成黄色,旁边出现错误信息