返回介绍

6.1 Converter

发布于 2025-04-22 20:10:00 字数 6446 浏览 0 评论 0 收藏

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 所示。

图片 2

图 6.1 Employee 表单中的转换错误

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。