软件开发实训(720科技)――第六课:转换器和格式化、验证器

软件开发实训(720科技)――第六课:转换器和格式化、验证器

内容关键词:转换、格式化、验证器
授课老师:张森鹏

一、知识笔记

1. Coonnveerrtteer r

     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)

2. Fo or r ma at tt te er r
      Formatter 就像 Converter 一样,也是将一种类型转换成另一种类型。但是,Formatter 的源类型必须是一个 String,而 Converter 则适用于任意的源类型。Formatter 更适合 Web 层,而Converter 则可以用在任意层中。为了转换 Spring MVC 应用程序表单中的用户输入,始终应该选择 Formatter,而不是 Converter。
    为了创建Formatter,要编写一个实现org.springframework.format.Formatter接口的Java类。下面是这个接口的声明:
       public interface Formatter<T>
     这里的 T 表示输入字符串要转换的目标类型。该接口有 parse 和 print 两个方法,所有实现都必须覆盖它们。
          T parse(String text, java.util.Locale locale)
          String print(T object, java.util.Locale locale)

     parse 方法利用指定的 Locale 将一个 String 解析成目标类型。print 方法与之相反,它返回目标对象的字符串表示法。例如,formatter-demo 应用程序中用一个 LocalDateFormatter 将 String 转换成 Date。其作用与 converter-demo 中的 StringToLocalDateConverter 一样。

3.验 证 概 览
    Converter 和 Formatter 作用于字段级。在 MVC 应用程序中,它们将 String 转换或格式化成另一种 Java 类型,如 java.time.LocalDate。验证器则作用于对象级。它决定某一个对象中的所有字段是否均是有效的,以及是否遵循某些规则。一个典型的 Spring MVC 应用会同时应用到 formatters/converters 和 validators。
     如果一个应用程序中既使用了 Formatter,又有 validator(验证器),那么,应用中的事件顺序是这样的:在调用 Controller 期间,将会有一个或者多个 Formatter,试图将输入字符串转换成 domain 对象中的 field 值。一旦格式化成功,验证器就会介入。
       例如,Order 对象可能会有一个 shippingDate 属性(其类型显然为 LocalDate),它的值绝对不可能早于今天的日期。当调用 OrderController 时,DateFormatter 会将字符串转化成 Date,并将它赋予 Order 对象的 shippingDate 属性。如果转换失败,用户就会被转回到前一个表单。如果转换成功,则会调用验证器,查看 shippingDate 是否早于今天的日期。
      现在,你或许会问,将验证逻辑转移到 LocalDateFormatter 中是否更加明智为比较一下日期并非难事,但答案却是否定的。首先,LocalDateFormatter 还可用于将其他字符串格式化成日期,如 birthDate 或者 purchaseDate。这两个日期的规则都不同于 shippingDate。事实上,比如,员工的出生日期绝对不可能晚于今日。其次,验证器可以检验两个或更多

字段之间的关系,各字段均受不同的 Formatter 支持。例如,假设 Employee 对象有 birthDate属性和 startDate 属性,验证器就可以设定规则,使任何员工的入职日期均不可能早于他的出生日期。因此,有效的 Employee 对象必须让它的 birthDate 属性值早于其 startDate 值。这就是验证器的任务。

二、重要笔记

1.用 用 R Re eg gi is st tr ra ar r 注册 册 F Fo or r ma at tt te er r

package formatter;
import org.springframework.format.FormatterRegistrar;
import org.springframework.format.FormatterRegistry;
public class MyFormatterRegistrar implements FormatterRegistrar {
private String datePattern;
public MyFormatterRegistrar(String datePattern) {
this.datePattern = datePattern;
}
@Override
public void registerFormatters(FormatterRegistry registry) {
registry.addFormatter(new LocalDateFormatter(datePattern));
// register more formatters here
}
}
有了 Registrar,就不需要在 Spring MVC 配置文件中注册任何 Formatter 了,只在 Spring

配置文件中注册 Registrar 就可以了。

2.选择 择 C Co on nv ve er rt te er r , 还是 是 F Fo or r ma at tt te er r

Converter 是一般工具,可以将一种类型转换成另一种类型。例如,将 String 转换成
LocalDate,或者将 Long 转换成 LocalDate。Converter 既可以用在 Web 层,也可以用在其他
层中。
Formatter 只能将 String 转换成另一种 Java 类型。例如,将 String 转换成 LocalDate,但
它不能将 Long 转换成 LocalDate。因此,Formatter 适用于 Web 层。为此,在 Spring MVC 应

用程序中,选择 Formatter 比选择 Converter 更合适。

3. Sp pr ri in ng g 的 的 V Va al li id da at to or r 范

    spring-validator 应用程序中包含一个名为 ProductValidator 的验证器,用于验证 Product 对

象。Spring-validator 的 Product 类如清单 7.2 所示。ProductValidator 类如清单 7.3 所示。

清单 

a、 Product 类

package domain;
import java.io.Serializable;
import java.math,BigDecimal;
import java.time.LocalDate;
public class Product implements Serializable {
private static final long serialVersionUID = 1L;
private String name;
private String description;
private BigDecimal price;
private LocalDate productionDate;
//getters and setters methods not shown
}
b、 ProductValidator 类
package validator;
import java.math,BigDecimal;
import java.time.LocalDate;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;
import domain.Product;
public class ProductValidator implements Validator {
@Override
public boolean supports(Class<gt; klass) {
return Product.class.isAssignableFrom(klass);
}
@Override
public void validate(Object target, Errors errors) {
Product product = (Product) target;
ValidationUtils.rejectIfEmpty(errors, “name”,
“productname.required”);
ValidationUtils.rejectIfEmpty(errors, “price”,”price.required”);
ValidationUtils.rejectIfEmpty(errors, “productionDate”,
“productiondate.required”);
BigDecimal price = product.getPrice();
if (price != null && price.compareTo(BigDecimal.ZERO) < 0) {
errors.rejectValue(“price”, “price.negative”);
}
Local Date productionDate = product.getProductionDate();
if (productionDate != null) {
if (productionDate.isAfter(LocalDate.now())) {
errors.rejectValue(“productionDate”,
“productiondate.invalid”);
}
}
}
}
ProductValidator 验证器是一个非常简单的验证器。它的 validate 方法会检验 Product 是否

有名称和价格,并且价格是否不为负数。它还会确保生产日期不晚于今天。

4. JS SR R 3 30 03 3 V Va al li id da at to or r 范 例
     jsr303-validator 应用程序展示了 JSR 303 输入验证的例子。这个应用程序是对 spring-
validator 进行修改之后的版本,与之前的版本有一些区别。首先,它没有 ProductValidator 类。
其次,来自 Hibernate Validator 库的 jar 文件已经被添加到了 WEB-INF/lib 中。
清单 7.6 Product 类的 name 和 productionDate 字段已经用 JSR 303 注解类型进行了注解。
   清单 7.6 Product 类
package domain;
import java.io.Serializable;
import java.math.BigDecimal
import java.time.LocalDate;
import javax.validation.constraints.Past;
import javax.validation.constraints.Size;
public class Product implements Serializable {
private static final long serialVersionUID = 78L;
@Size(min=1, max=10)
private String name;
private String description;
private BigDecimal price;
@Past
private LocalDate productionDate;
// getters and setters not shown
}
在 ProductController 类的 saveProduct 方法中,必须用@Valid 对 Product 参数进行注解,
如清单 7.7 所示。
清单 7.7 ProductController 类
package controller;
import javax.validation.Valid;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.Product;
@Controller
public class ProductController {
private static final Log logger = LogFactory
.getLog(ProductController.class);
@RequestMapping(value = “/add-product”)
public String inputProduct(Model model) {
model.addAttribute(“product”, new Product());
return “ProductForm”;
}
@RequestMapping(value = “/save-product”)
public String saveProduct(@Valid @ModelAttribute Product product,
BindingResult bindingResult, Model model) {
if (bindingResult.hasErrors()) {
FieldError fieldError = bindingResult.getFieldError();
logger.info(“Code:” + fieldError.getCode() + “, object:”
+ fieldError.getObjectName() + “, field:”
+ fieldError.getField());
return “ProductForm”;
}
// save product here
model.addAttribute(“product”, product);
return “ProductDetails”;
}
}
为了定制来自验证器的错误消息,要在 messages.properties 文件中使用两个键。

三、学习参考
https://m.2cto.com/kf/201707/654979.html
https://blog.csdn.net/slowly_come_faster

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2018年3月22日
下一篇 2018年3月22日

相关推荐