- 内容提要
- 作者简介
- 译者简介
- 前言
- HTTP
- Servlet 和 JSP
- 下载 Spring 或使用 STS 与 Maven/Gradle
- 手动下载 Spring
- 使用 STS 和 Maven/Gradle
- 下载 Spring 源码
- 本书内容简介
- 下载示例应用
- 第 1 章Spring 框架
- 第 2 章模型 2 和 MVC 模式
- 第 3 章Spring MVC 介绍
- 第 4 章基于注解的控制器
- 第 5 章数据绑定和表单标签库
- 第 6 章转换器和格式化
- 第 7 章验证器
- 第 8 章表达式语言
- 第 9 章JSTL
- 第 10 章国际化
- 第 11 章上传文件
- 第 12 章下载文件
- 第 13 章应用测试
- 附录 A Tomcat
- 附录 B Spring Tool Suite 和 Maven
- 附录 C Servlet
- 附录 D JavaServer Pages
- 附录 E 部署描述符
6.1 Converter
Spring 的 Converter 是可以将一种类型转换成另一种类型的一个对象。例如,用户输入的日期可能有许多种形式,如“December 25,2014”“12/25/2014”和“2014-12-25”,这些都表示同一个日期。默认情况下,Spring 会期待用户输入的日期样式与当前语言区域的日期样式相同。例如,对于美国的用户而言,就是月/日/年格式。如果希望 Spring 在将输入的日期字符串绑定到 LocalDate 时,使用不同的日期样式,则需要编写一个 Converter,才能将字符串转换成日期。java.time.LocalDate 类是 Java 8 的一个新类型,用来替代 java.util.Date。还需使用新的 Date/Time API 来替换旧有的 Date 和 Calendar 类。
为了创建 Converter,必须编写实现 org.springframework.core.convert.converter. Converter 接口的一个 Java 类。这个接口的声明如下:
public interface Converter<S, T>
这里的 S 表示源类型,T 表示目标类型。例如,为了创建一个可以将 Long 转换成 Date 的 Converter,要像下面这样声明 Converter 类:
public class MyConverter implements Converter<Long, LocalDate> {
}
在类实体中,需要编写一个来自 Converter 接口的 convert 方法实现。这个方法的签名如下:
T convert(S source)
例如,清单 6.1 展示了一个适用于任意日期样式的 Converter。
清单 6.1 String To LocalDate Converter
package converter;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import org.springframework.core.convert.converter.Converter;
public class StringToLocalDateConverter implements Converter<String,
LocalDate> {
private String datePattern;
public StringToLocalDateConverter(String datePattern) {
this.datePattern = datePattern;
}
@Override
public LocalDate convert(String s) {
try {
return LocalDate.parse(s, DateTimeFormatter.ofPattern(
datePattern));
} catch (DateTimeParseException e) {
// the error message will be displayed in <form:errors>
throw new IllegalArgumentException(
"invalid date format. Please use this pattern\""
+ datePattern + "\"");
}
}
}
注意清单 6.1 中的 Converter 方法,它利用传给构造器的日期样式,将一个 String 转换成 LocalDate。
为了使用 Spring MVC 应用程序中定制的 Converter,需要在 Spring MVC 配置文件中编写一个名为 conversionService 的 bean。bean 的类名称必须为 org.springframework.context. support.ConversionServiceFactoryBean。这个 bean 必须包含一个 converters 属性,它将列出要在应用程序中使用的所有定制 Converter。例如,下面的 bean 声明在清单 6.1 中注册了 StringToDateConverter。
< bean id="conversionService" class="org.springframework.context.support.
→ConversionServiceFactoryBean">
< property name="converters">
< list>
< bean class="converter.StringToLocalDateConverter">
< constructor-arg type="java.lang.String"
value="MM-dd-yyyy"/>
< /bean>
< /list>
< /property>
< /bean>
随后,要给 annotation-driven 元素的 conversion-service 属性赋值 bean 名称(本例中是 conversionService),如下所示:
<mvc:annotation-driven
conversion-service="conversionService"/>
converter-demo 是一个范例应用程序,它利用 StringToLocalDateConverter 将 String 转换成 Employee 对象的 birthDate 属性。Employee 类如清单 6.2 所示。
清单 6.2 Employee 类
package domain;
import java.io.Serializable;
import java.time.LocalDate;
public class Employee implements Serializable {
private static final long serialVersionUID = -908L;
private long id;
private String firstName;
private String lastName;
private LocalDate birthDate;
private int salaryLevel;
// getters and setters not shown
}
清单 6.3 中的 EmployeeController 类是 domain 对象 Employee 的控制器。
清单 6.3 converter-demo 中的 EmployeeController 类
package controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import domain.Employee;
@Controller
public class EmployeeController {
@RequestMapping(value="/add-employee")
public String inputEmployee(Model model) {
model.addAttribute(new Employee());
return "EmployeeForm";
}
@RequestMapping(value="/save-employee")
public String saveEmployee(@ModelAttribute Employee employee,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
return "EmployeeForm";
}
// save employee here
model.addAttribute("employee", employee);
return "EmployeeDetails";
}
}
EmployeeController 类有 inputEmployee 和 saveEmployee 两个处理请求的方法。inputEmployee 方法返回清单 6.4 中的 EmployeeForm.jsp 页面。saveEmployee 方法取出在提交 Employee 表单时创建的一个 Employee 对象。有了 StringToLocalDateConverter converter,就不需要劳驾控制器类将字符串转换成日期了。
saveEmployee 方法的 BindingResult 参数中放置了 Spring 的所有绑定错误。该方法利用 BindingResult 记录所有绑定错误。绑定错误也可以利用 errors 标签显示在一个表单中,如 EmployeeForm.jsp 页面所示。
清单 6.4 EmployeeForm.jsp 页面
<%@ taglib prefix="form"uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML>
<html>
<head>
<title>Add Employee Form</title>
<style type="text/css">@import url("<c:url
value="/css/main.css"/>");</style>
</head>
<body>
<div id="global">
<form:form commandName="employee" action="save-employee" method="post">
<fieldset>
<legend>Add an employee</legend>
<p>
<label for="firstName">First Name: </label>
<form:input path="firstName"/>
</p>
<p>
<label for="lastName">First Name: </label>
<form:input path="lastName"/>
</p>
<p>
<form:errors path="birthDate" cssClass="error"/>
</p>
<p>
<label for="birthDate">Date Of Birth: </label>
<form:input path="birthDate" />
</p>
<p id="buttons">
<input id="reset" type="reset">
<input id="submit" type="submit"
value="Add Employee">
</p>
</fieldset>
</form:form>
</div>
</body>
</html>
在浏览器中打开以下 URL,可以对这个转换器进行测试:
http://localhost:8080/converter-demo/add-employee
试着输入一个无效的日期,将会被转到同一个 Employee 表单,并且可以在表单中看到错误消息,如图 6.1 所示。
图 6.1 Employee 表单中的转换错误
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论