Converter(转换器)与Formatter(格式化)都可以用于将一种对象类型转换为另一种对象类型。Converter是通用元件,可以在应用程序的任意层中使用,而Fotermatter这是专门为Web层设计的。Validator(验证器)主要用于校验输入。

Converter(转换器)

创建Converter,必须编写实现org.springframework.core.convert.converter.Converter接口的一个Java类。该接口的实现声明如下:

public interface Converter<S,T>

这里的S标识源类型,T表示目标类型。这是一个将String转为Employee对象的转换器:

public class EmployeeConveter implements Converter<String,Employee> {}

为了使用springMVC应用程序中定制的Converter,需要在springMVC配置文件中编写一个名为conversionService的bean。bean的类名称必须为org.springframeword.context.support.ConversionServiceFactoryBean。这个bean必须包含一个converters属性,它将列出要在应用程序中使用的所有定制Converter。

<!-- 配置自定义类型转换器 -->
<bean id="employeeConveter" class="cn.lynu.converter.EmployeeConveter"></bean>
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="employeeConveter"/>
</set>
</property>
</bean>

注意:不要忘了将这个employeeConveter 加入到IOC的控制中:<bean id="employeeConveter" class="cn.lynu.converter.EmployeeConveter"></bean>  亦或者使用@Component 注解配置该类加入到IOC容器中,这样就不需要在XML中配置了:

二者必须选择一种配置方法,将employeeConveter 加入到IOC容器中,因为我们在设置converters 的时候需要用到,不然就会报出找不到这个bean的异常:

随后,要是annotation-driver元素的conversion-service属性赋值bean名称,如下:

<mvc:annotation-driven conversion-service="conversionService"></mvc:annotation-driven>

Formatter(格式化)

Formatter就像Converter一样,也是将一种类型转换为另一种类型。但是,Formatter的源类型必须是一个String,而Converter则适用用于任意源类型。Formatter更适合Web层,而Converter则可以用在任意层,为了转换SpringMVC应用程序表单中的用户输入,始终应该选择Formatter,而不是Converter。

为了创建Formatter,要编写一个实现org.springframework.format.Formatter接口的Java类。下面是这个接口的声明:

public interface Formatter<T>

这里的T表示输入字符串要转换的目标类型。

public class LocalDateFormatter implements Formatter<LocalDate> {}

该接口有parse和print两个方法。所有实现都必须覆盖它们。

T parse(String text,java.util.Locale locale)

String print(T object,java.util.Local local)

parse方法利用值当的Locale将一个String解析为String解析成目标类型。print方法与之相反,他返回目标对象的字符串表示法。

为了在springMVC中使用Formatter,需要利用名为conversionService的bean对它进行注册。bean的类名称必须为org.springframework.format.support.FormatterConversionServiceFactoryBean,这个bean可以用一个·formatters属性注册formatter,用一个converters属性注册converter。

    <bean id="conversionService"
class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<property name="formatters">
<set>
<!--注册formatters-->
</set>
</property>
</bean>

注意:formatters/converters都是set类型,我们还需要给这个Formatter添加一个component-scan元素:

<context:component-scan base-package="cn.lynu.formatter" />

或者是使用@Component注解

随后,还要是annotation-driver元素的conversion-service属性赋值bean名称,如下:

<mvc:annotation-driven conversion-service="conversionService" />

Validator (验证器)

在springMVC中,有两种方式可以验证输入,即利用Spring自带的验证框架,或者利用JSR303实现。可以这样理解:Converter和Formatter作用于字段级。在MVC应用程序中,它们将一种类型转换为另一种;类型。而验证器则作用对象级,它决定某一对象的所有字段是否均有效,以及是否遵循某些规则。

一个典型的springMVC应用会同时用到formatters/converters和validators。

如果一个应用程序即使用了Formatter,又有validator(验证器),那么,应用中的事件顺序是这样的:在调用Controller期间,将会有一个或者多个Formatter,试图将输入字符串转换为domain对象中的field值。一但格式化成功,验证器就会开始介入。

Spring验证器

从一开始,Spring就设计了输入验证,甚至早于JSR303(Java验证规范),因此,因此可能一些老的springMVC项目还在使用,对于新的项目,还是建议使用JSR303

为了创建Spring验证器,要实现org.springframework.validation.Validator接口,并重写supports和validate两个方法。

package org.springframework.validation;
public interface Validator{
boolean supports(Class<?> clazz);
void validate(Object target,Errors error);
}

如果验证器可以指定的Class,supports方法将返回true。validate方法会验证目标对象,并将错误消息填入Errors对象。

Errors对象是org.springframework.validation.Errors接口的一个实例。Errors对象中包含一系列FieldError和ObjectError对象。FieldError表示被验证对象中的某个属性相关的错误。

编写验证器时,不需要直接创建Error对象,因为实例化ObjectError或FieldError花费了大量编程精力。这是因为ObjectError类的构造器需要4个参数,FieldError类构造器则需要7个参数。

Errors对象中的错误消息,可以利用springMVC表单标签库的Errors标签显示在HTML页面中。错误消息可以通过Spring支持国际化特征本地化(springMVC表单标签,国际化本地化随后再说)。

org.springframework.validation.ValidationUtis类是一个工具,有助于编写Spring验证器,我们直接使用它里面提供的验证方法完成Validator类的验证过程。

配置文件

验证器不需要显示注册,但是想要从某个属性文件中获得错误消息,则需要通过声明messagesSource bean,告诉spring要去哪里寻找这个文件:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="120"/>
</bean>

建议都配上defaultEncoding,并将其设置为UTF-8,这样读取properties文件内容到页面显示就不会有乱码出现了。而且如果使用Maven构建项目时,properties文件如果放在src/main/resources下,都建议在写着文件路径的时候都加上classpath。

所有的验证出错信息都将放在BindingResult对象中,我们可以调用其方法判断验证时候出错:

if(bindingResult.hasErrors()){
//有错误出现
System.out.println("错误个数:"+bindingResult.getErrorCount());
System.out.println("错误为:");
for(FieldError error:bindingResult.getFieldErrors()) {
System.out.println(error.getField()+"\t"+error.getDefaultMessage());
}
}

其实这个BindingResult对象使用是有要求的,我们在下面介绍过JSR303之后再说

JSR303验证

JSR303通过租借给对象属性添加约束,但是JSR303只是一个规范,所以我们需要使用它的实现产品,目前两个实现:第一个时Hibernate Validator,第二个实现时Apache BVal。JSR303方便之处就在于不需要编写验证器,但要利用JSR303注解类型潜入约束。这些注解大都是javax.validation包下的类.

部分JSR303验证注解:

注解 描述 范例
@AssertTrue 应用于boolean属性,该属性必须为True

@AssertTrue

boolean isEmpty;

@DecimalMax 该属性的值必须为小于或等于指定值的小数

@DecimalMax("1.1")

BigDecimal price;

@Max 该属性值必须为一个小于或等于指定值的整数

@Max(150)

int age;

@Future 该属性必须为未来的一个日期  

@Future

Date shippingDate;

@Past 该属性值必须是过去的一个日期

@Past

Date birthDay;

@Size 该属性值必须在指定范围类

@Size(min=2,max=140)

String areaCode;

@NotNull

该属性值不能是null(建议使用Hibernate Validation的@NotEmpty,

因为页面字段为空会被封装为[] 而非null)

@NotNull

String firstName;

@Patter

该属性可以与指定的表达式相匹配(其实就是与正则匹配)

@Pattern(regext="\\d{3}")

String areaCode;

我们还是需要在springMVC中配置ReloadableResourceBundleMessageSource:

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:messages</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
<property name="cacheSeconds" value="120"/>
</bean>

像使用Spring验证器一样,可以在messages.properties属性文件以下面格式来使用property键值,覆盖来自JSR303验证器的错误消息:

constraint.object.property

但是在5.2.4版本Hibernate Validation仍然无法验证使用@Part和@Future注解的LocalDate或LocalDateTime类型的字段,因为LocalDate/LocalDateTime是Java8新增的类型,是想用来替代java.util.Date。因此对于这种新的类型的验证需要使用第一种自定义spring验证器方式,或者是重写Hibernate Validation中的ConstraintHelper类。

JSR303验证的后台Java代码

注意:我们上面说到所有验证错误信息都会存在BindingResult这个对象中,但是这个对象使用是有要求的:它必须在放在验证对象(验证对象需要使用@Valid注解修饰 javax.validation.Valid)的后面,必须在后面,也就是说它们之间不能存在其他任何的参数:

    /**
* BindingResult将显示错误信息
*/
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String save(@Valid Employee employee,BindingResult result,Model model) {
if(result.getErrorCount()>0) {
System.out.println("错误个数:"+result.getErrorCount());
System.out.println("错误为:");
for(FieldError error:result.getFieldErrors()) {
System.out.println(error.getField()+"\t"+error.getDefaultMessage());
}
//输出错误信息
List<ObjectError> allErrors = result.getAllErrors();
List<String> errorList=new ArrayList<String>();
for (ObjectError objectError : allErrors) {
try {
errorList.add(objectError.getDefaultMessage());
} catch (Exception e) {
e.printStackTrace();
}
}
//将错误信息传递到页面
model.addAttribute("allErrors", errorList);
model.addAttribute("departments", departmentDao.getDepartments());
return "input";
}
employeeDao.save(employee);
return "redirect:/list";
}

Converter(转换器)与Formatter(格式化) ,Validator(验证器)的更多相关文章

  1. springMVC的 Converter转换器 和 Formatter

    Converter转换器 spring的Converter是可以将一种类型转换成另一种类型的一个对象, 自定义Converter需要实现Converter接口 日期转换器 import java.te ...

  2. spring-Formatter(格式化器)-validator(验证器)-错误信息定制

    项目结构

  3. How to create XML validator(验证器;验证程序) from XML schema

    In order to check XML data for validity we have to prepare its schema XSD-file. This file will be lo ...

  4. springMVC中使用 JSR-303验证器( Validation 接口 )

    在pom.xml,添加validator验证器的依赖 <dependency> <groupId>org.hibernate</groupId> <artif ...

  5. [Swift]LeetCode591. 标签验证器 | Tag Validator

    Given a string representing a code snippet, you need to implement a tag validator to parse the code ...

  6. vue props 下有验证器 validator 验证数据返回true false后,false给default值

    vue props 下有验证器 validator 验证数据返回true false后,false给default值 props: { type: { validator (value) { retu ...

  7. PHP验证器类Validator

    Particle\Validator是一个小巧优雅的实用的PHP验证类库,提供了一个非常简洁的API.它无需依赖其他组件,提供友好的文档,并且有利于扩展. 安装 composer require pa ...

  8. Spring MVC -- 验证器

    输入验证是Spring处理的最重要Web开发任务之一.在Spring MVC中,有两种方式可以验证输入,即利用Spring自带的验证框架,或者利用JSR 303实现.本篇博客将介绍这两种输入验证方法. ...

  9. (翻译)Angular 1.3中的验证器管道

    原文地址:VALIDATORS PIPELINE IN ANGULAR 1.3 我们知道在Angular中操作表单是很爽的.因为Angular本身的作用域模型,我们总能在相应的作用域中获取到表单当前的 ...

随机推荐

  1. Jenkins分享

    2016-02-26 小马哥 程序员之路   PPT下载地址:http://pan.baidu.com/s/1i4pw6oP   Jenkins 是一个开源软件项目,旨在提供一个开放易用的软件平台,使 ...

  2. Bireme:一个 Greenplum数据仓库的增量同步工具

    https://hashdatainc.github.io/bireme/ Bireme 是一个 Greenplum / HashData 数据仓库的增量同步工具.目前支持 MySQL.Postgre ...

  3. Sqlserver 存储过程 返回-6

    存储过程中没有返回 手动返回-6的代码,但是一直接收到-6返回值. 经最后研究发现,是粗心导致的,Insert插入数据时在非空字段插入了Null值导致出现异常,所以返回了-6. 所以说在事务中,可能会 ...

  4. Scikit-learn方法使用总结

    在机器学习和数据挖掘的应用中,scikit-learn是一个功能强大的python包.在数据量不是过大的情况下,可以解决大部分问题.近期在学习使用scikit-learn的过程中,我自己也在补充着机器 ...

  5. I.MX6 Linux eGTouch TouchScreen porting

    I.MX6 Linux eGTouch TouchScreen porting 一.Download Driver: http://www.eeti.com.tw/drivers_Linux.html ...

  6. http协议知识整理

    HTTP 协议 作为web开发人员,了解一些http协议的知识很有必要.本文简单介绍了HTTP协议的知识,若有错误的地方,望大家指正. 1.HTTP协议是什么? http协议是一个应用层的协议.规定了 ...

  7. 新手向——关于Python3.5在Windows 10 系统下发布模块的终极讲解

    博主自己在发布Python模块的时候也是摸索了好久啊,因为跟着书上写的步骤一步一步来终究会跪的节奏有木有啊!!!几经波折终于搞出来了,贴下来与诸君共勉.之前的步骤相信大家都已经知道了,那我们就直接跳过 ...

  8. 使用LinkedBlockingQueue来实现生产者消费者的例子

    工作中,经常有将文件中的数据导入数据库的表中,或者将数据库表中的记录保存到文件中.为了提高程序的处理速度,可以设置读线程和写线程,这些线程通过消息队列进行数据交互.本例就是使用了LinkedBlock ...

  9. erl_0017 《硝烟中的erlang》 读书笔记004 “锁和阻塞”

    如果某个进程需要持续地接收新任务,那么其在执行耗时过长的锁或者阻塞操作时,就会出现问题. 最为常见的例子之一就是:某个进程使用了TCP socket,阻塞在了接收新的连接或者等待消息上面.在执行此类阻 ...

  10. 使用 ExceptionDispatchInfo 捕捉并重新抛出异常

    当你跑起了一个异步线程,并用 await 异步等待时,有没有好奇为什么能够在主线程 catch 到异步线程的异常? 当你希望在代码中提前收集好异常,最后一并把收集到的异常抛出的时候,能不能做到就像在原 ...