Beginning Spring学习笔记——第3章(二)表单处理
来源:互联网 发布:天干地支年算法 编辑:程序博客网 时间:2024/06/07 04:51
使用JSP处理表单
Spring MVC通过自定义JSP表单标签库提供了表单处理方法,要想使用该库内的标签,需要在JSP文件中添加该标签库的定义
<%@taglib uri="http://www.springframework.org/tags/form" prefix="mvc" %>
此处把mvc定义为标签库的前缀,使用标签库内标签时遵循<mvc:tagname>的格式
下用一个处理用户注册表单的例子来示范这些标签的使用
首先使用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>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>*.mvc</url-pattern> </servlet-mapping></web-app>
然后在springmvc-servlet.xml文件中配置好DispatcherServlet
<?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-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类了。
@Controllerpublic 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 Handling</title></head><body><h2>User Registration Form</h2><mvc:form modelAttribute="user" action="result.mvc"> <table> <tr> <td><mvc:label path="name">Name</mvc:label></td> <td><mvc:input path="name" /></td> </tr> <tr> <td><mvc:label path="lastname">Last Name</mvc:label></td> <td><mvc:input path="lastname" /></td> </tr> <tr> <td><mvc:label path="password">Password</mvc:label></td> <td><mvc:password path="password" /></td> </tr> <tr> <td><mvc:label path="detail">Detail</mvc:label></td> <td><mvc:textarea path="detail" /></td> </tr> <tr> <td><mvc:label path="birthDate">Birth Date</mvc:label></td> <td><mvc:input path="birthDate" /></td> </tr> <tr> <td><mvc:label path="gender">Gender</mvc:label></td> <td><mvc:radiobuttons path="gender" items="${genders}" /></td> </tr> <tr> <td><mvc:label path="country">Country</mvc:label></td> <td><mvc:select path="country" items="${countries}" /></td> </tr> <tr> <td><mvc:label path="nonSmoking">Non Smoking</mvc: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>
首先通过<mvc:form>标签创建一个表单,在其中定义表单内的元素.该标签的modelAttribute特性向内部标签公开了一个绑定路径,该特性所指定的模型类将向视图公开,表单内标签的path特性将指向该模型类的属性,如name,lastname,gender等。而它的action特性则表示表单提交后跳转至的URL。
表单中用<mvc:input>标签定义了输入框,用于姓名、密码、生日的输入。
<mvc:textarea>标签定义了输入文本区域,用于详细介绍的输入。
<mvc:radiobutton>定义了选择性别的一系列单选按钮,与User中的gender属性对应,接受名为genders的数据作为选项的输入。
<mvc:select>定义了选择国家的下拉栏,与User中的country属性对应,接受名为countries的数据作为选项输入。
<mvc:checkbox>定义的复选框用于勾选是否吸烟。
以上标签之前都有<mvc:label>标签来给栏目进行说明。
最后用<input>(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 Handling</title></head><body> <h2>User Registration Result</h2> <table> <tr> <td>Name</td> <td>${u.name}</td> </tr> <tr> <td>Last name</td> <td>${u.lastname}</td> </tr> <tr> <td>Password</td> <td>${u.password}</td> </tr> <tr> <td>Detail</td> <td>${u.detail}</td> </tr> <tr> <td>Birth Date</td> <td>${u.birthDate}</td> </tr> <tr> <td>Gender</td> <td>${u.gender}</td> </tr> <tr> <td>Country</td> <td>${u.country}</td> </tr> <tr> <td>Non-Smoking</td> <td>${u.nonSmoking}</td> </tr> </table></body></html>
注意此时从UserController传入视图的是一个被命名为“u”的User实例,在视图中通过${u.xxx}来获得其属性。
将项目部署到Tomcat服务器并运行,在浏览器中输入http://localhost:8080/FormRegister/form.mvc得到如下页面
单击Submit按钮跳转至信息显示页面
使用注解的强大功能
刚才的例子中已经用到了一系列注解,此处将解释他们的作用
- @Controller:表示被注解的类为MVC框架的一个Controller,DispatcherServlet扫描被@Controller注解的类并将Web请求映射到其被相应@RequestMapping注解的方法上
- @RequestMapping:标记用来将用户请求映射到处理器的类或者方法,可在类或方法级别使用,Value属性代表被映射的URL值的一部分
- @ModelAttribute:使用一个向视图公开的键将一个返回值和一个参数绑定,可以在方法或方法参数级别使用
- @PathVariable:将一个方法参数绑定到一个URL模板
- @ControllerAdvice:将代码集中,一遍跨控制器共享代码。使用该注解的类可以包含带有@ExceptionHandler、@InitBinder和@ModelAttribute注解的方法
- @InitBinder:确定用来初始化WebDataBinder的方法
- @ExceptionHandler:确定处理控制器类中发生的异常的方法
验证用户输入
在域类的属性上添加如下注解可以定义他们应当通过的验证:
- @Size注解定义长度
- @Email注解根据e-mail的正则表达式来验证输入
- @CreditCardNumber注解根据Luhn算法验证输入数字
- @Pattern注解根据其regexp属性定义的正则表达式来验证输入
我们在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中添加如下依赖
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-validator --><dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> <version>6.0.2.Final</version></dependency>
为了在输入注册信不满足条件的时候返回注册界面显示错误信息,processUser方法需要进行修改
@Controllerpublic 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标签中定义验证程序
<?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-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 Validation</title> <style type="text/css"> .formFieldError { background-color: #FFC; } </style></head><body><h2>User Registration Form</h2><mvc:form modelAttribute="user" action="result.mvc"> <table> <tr> <td><mvc:label path="username">User Name</mvc:label></td> <td><mvc:input path="username" cssErrorClass="formFieldError" /></td> <td><mvc:errors path="username" /></td> </tr> <tr> <td><mvc:label path="email">E-Mail</mvc: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 Number</mvc:label></td> <td><mvc:input path="ccNumber" cssErrorClass="formFieldError" /></td> <td><mvc:errors path="ccNumber" /></td> </tr> <tr> <td><mvc:label path="password">Password</mvc: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,直接提交空表单可以获得如下结果
可看到未通过验证的输入栏背景变成黄色,旁边出现错误信息
- Beginning Spring学习笔记——第3章(二)表单处理
- Beginning Spring学习笔记——第5章(二)Spring的JPA支持
- Beginning Spring学习笔记——第2章(二)依赖注入
- Beginning Spring学习笔记——第3章(三)文件上传、异常处理和个性化
- Beginning Spring学习笔记——第3章(一)Spring MVC基础
- Beginning Spring学习笔记——第4章(二)使用Spring执行数据访问操作
- Beginning Spring学习笔记——第6章(二)使用Spring进行声明式事务管理
- Beginning Spring学习笔记——第1章
- Beginning Spring学习笔记——第9章 SpEL
- Beginning Spring学习笔记——第10章 缓存
- Beginning Spring学习笔记——第2章(一)Spring IoC容器
- Beginning Spring学习笔记——第2章(三)Spring的Bean管理
- Beginning Spring学习笔记——第4章(一)Spring JDBC连接的配置
- Beginning Spring学习笔记——第6章(一)Spring事务管理基础
- Beginning Spring学习笔记——第5章(一)ORM和JPA基础
- Beginning Spring学习笔记——第7章 使用Spring进行测试驱动开发
- Beginning Spring学习笔记——第8章 Spring AOP
- Beginning Spring学习笔记——第6章(三)使用Spring进行编程式事务管理
- Jquey Deferred 独立实现版本不依赖jquery
- (六)懒加载和依赖注入树
- 鼠标悬浮(一段时间)才处理
- HDU 6171 Admiral (DFS + 剪枝)
- 正则校验汇总(js)
- Beginning Spring学习笔记——第3章(二)表单处理
- 教你解决Eclipse中SVN比较乱码问题
- 使用eclipes中遇到的问题
- (七)共享模块和依赖注入
- windows 下常用的命令
- 3D麻将游戏开发通用算法
- 新人打卡
- shiro 如何让一个页面既可以让admin查看,又可以让user查看
- python 结构与字符串