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,直接提交空表单可以获得如下结果
结果
可看到未通过验证的输入栏背景变成黄色,旁边出现错误信息

阅读全文
0 0
原创粉丝点击