springmvc知识四------数据转换&数据格式化&数据校验

数据转换

数据转换,顾名思义就是数据类型之间的转换,可是对于数据转换,有的是能够进行转化的,例如字符串转整形数,可是有些数据类型之间是不能进行转换的,例如从字符串到日期之间的类型转换。
对于不一样的框架,对于数据转换的类型也有所不一样,对于Springmvc,又是怎么完成数据之间的转换呢,
首先数据的转换,确定是发生在数据绑定中的,那么数据的绑定流程又是如何的呢java

数据绑定流程

一、Springmvc主框架将ServletRequest 对象及目标方法的入参实例传递给WebDataBinderFactory实例,用以建立DataBinder实例对象,DataBinder是数据绑定的核心组件
二、DataBinder 调用装配在Springmvc上下文中的ConversionService组件进行数据类型转换、数据格式化工做。将Servlet 中的请求信息填充到入参对象中。
三、调用Validate组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData 对象
四、Springmvc 抽取BindingResult中的入参对象和校验错误对象,将他们赋给处理方法的响应入参。git

在POJO类中的setter方法中添加断点能够追踪代码进行查看。
当代码中止以后,咱们向前看,能够找到这个【ModelAttributeMethodProcessor】类,而后点进去发现代码停在了108行。如图:
这里写图片描述web

在这里咱们能够看到数据绑定流程过程当中的第一步。正则表达式

而后咱们在变量域中找到binder这个变量,在这个binder变量中存有一系列的值。其中最主要的三个分别是【conversionService】【validators】【bindingResult】
以下图
这里写图片描述spring

这三个变量分别对应流程中的二三四所须要的步骤。mvc

数据转换时在【conversionService】中发生的。并且在这里Springmvc默认了许多转换器,下图所示:
这里写图片描述app

在这里咱们能够完成绝大多数的类型之间的转换。咱们不须要再自定义转换器。框架

ConversionService converters = 
    @org.springframework.format.annotation.DateTimeFormat java.lang.Long -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@786e16,
@org.springframework.format.annotation.NumberFormat java.lang.Long -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    @org.springframework.format.annotation.DateTimeFormat java.util.Calendar -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@786e16
    @org.springframework.format.annotation.DateTimeFormat java.util.Date -> java.lang.String: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@786e16
    @org.springframework.format.annotation.NumberFormat java.lang.Double -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    @org.springframework.format.annotation.NumberFormat java.lang.Float -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    @org.springframework.format.annotation.NumberFormat java.lang.Integer -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    @org.springframework.format.annotation.NumberFormat java.lang.Short -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    @org.springframework.format.annotation.NumberFormat java.math.BigDecimal -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    @org.springframework.format.annotation.NumberFormat java.math.BigInteger -> java.lang.String: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.Boolean -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@de1b36
    java.lang.Character -> java.lang.Number : org.springframework.core.convert.support.CharacterToNumberFactory@166b0df
    java.lang.Character -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@1f9cdda
    java.lang.Enum -> java.lang.String : org.springframework.core.convert.support.EnumToStringConverter@2423ad
    java.lang.Long -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$LongToCalendarConverter@19302fb
    java.lang.Long -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$LongToDateConverter@1d5e499
    java.lang.Number -> java.lang.Character : org.springframework.core.convert.support.NumberToCharacterConverter@139d369
    java.lang.Number -> java.lang.Number : org.springframework.core.convert.support.NumberToNumberConverterFactory@1220b15
    java.lang.Number -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@d76d1e
    java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.lang.Long: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@786e16,java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Long: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.util.Calendar: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@786e16
    java.lang.String -> @org.springframework.format.annotation.DateTimeFormat java.util.Date: org.springframework.format.datetime.DateTimeFormatAnnotationFormatterFactory@786e16
    java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Double: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Float: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Integer: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> @org.springframework.format.annotation.NumberFormat java.lang.Short: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> @org.springframework.format.annotation.NumberFormat java.math.BigDecimal: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> @org.springframework.format.annotation.NumberFormat java.math.BigInteger: org.springframework.format.number.NumberFormatAnnotationFormatterFactory@838143
    java.lang.String -> com.wf.springmvc.crud.entities.Employee : com.wf.springmvc.crud.conversion.EmployeeConversion@134ab9b
    java.lang.String -> java.lang.Boolean : org.springframework.core.convert.support.StringToBooleanConverter@e62a39
    java.lang.String -> java.lang.Character : org.springframework.core.convert.support.StringToCharacterConverter@13ce184
    java.lang.String -> java.lang.Enum : org.springframework.core.convert.support.StringToEnumConverterFactory@1cc946b
    java.lang.String -> java.lang.Number : org.springframework.core.convert.support.StringToNumberConverterFactory@5966f
    java.lang.String -> java.util.Locale : org.springframework.core.convert.support.StringToLocaleConverter@a26638
    java.lang.String -> java.util.Properties : org.springframework.core.convert.support.StringToPropertiesConverter@f0474c
    java.lang.String -> java.util.UUID : org.springframework.core.convert.support.StringToUUIDConverter@151e135
    java.util.Calendar -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToLongConverter@3fcfb
    java.util.Calendar -> java.util.Date : org.springframework.format.datetime.DateFormatterRegistrar$CalendarToDateConverter@89e0c6
    java.util.Date -> java.lang.Long : org.springframework.format.datetime.DateFormatterRegistrar$DateToLongConverter@19b7dfa
    java.util.Date -> java.util.Calendar : org.springframework.format.datetime.DateFormatterRegistrar$DateToCalendarConverter@16bb63e
    java.util.Locale -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@1e4e6db
    java.util.Properties -> java.lang.String : org.springframework.core.convert.support.PropertiesToStringConverter@d8fb2b
    java.util.UUID -> java.lang.String : org.springframework.core.convert.support.ObjectToStringConverter@9875d1
    org.springframework.core.convert.support.ArrayToArrayConverter@13fa2d5
    org.springframework.core.convert.support.ArrayToCollectionConverter@15f1ace
    org.springframework.core.convert.support.ArrayToObjectConverter@dec95c
    org.springframework.core.convert.support.ArrayToStringConverter@2c390c
    org.springframework.core.convert.support.ByteBufferConverter@af9d74
    org.springframework.core.convert.support.ByteBufferConverter@af9d74
    org.springframework.core.convert.support.CollectionToArrayConverter@d8f317
    org.springframework.core.convert.support.CollectionToCollectionConverter@db59df
    org.springframework.core.convert.support.CollectionToObjectConverter@86a58a
    org.springframework.core.convert.support.CollectionToStringConverter@14487c8
    org.springframework.core.convert.support.FallbackObjectToStringConverter@123b9c1
    org.springframework.core.convert.support.IdToEntityConverter@18a5d49,org.springframework.core.convert.support.ObjectToObjectConverter@f2a0ef
    org.springframework.core.convert.support.MapToMapConverter@e969f8
    org.springframework.core.convert.support.ObjectToArrayConverter@75c2be
    org.springframework.core.convert.support.ObjectToCollectionConverter@1de41c3
    org.springframework.core.convert.support.StringToArrayConverter@1556aec
    org.springframework.core.convert.support.StringToCollectionConverter@2e6767

常见的转换器
这里写图片描述ide

【validators】数据域
这里写图片描述svg

【bindingResult】数据域
这里写图片描述

自定义转化器

三步走:
第一步:前台输入框输入符合格式的数据。
第二步: 编写自定义转换器类 实现Converter类。
第三步:springmvc.xml文件注册自定义转换器。

Spring定义了三种类型的转化器接口,实现任意一个转换器接口均可以做为自定义转换器注册到ConversionServiceFactoryBean中。建议使用第一个。
【Converter《S,T》: 将S类型对象转化为T类型对象】
【ConverterFactory:将相同系列多个“同质”Converter封装在一块儿,若是但愿将一种类型的对象转换为另一种类型及其子类的对象(例如将String转化为Number及Number子类Double,Integer等对象)可使用该转换器工厂类】
【GenericConverter:会根据源类对象及目标对象所在的宿主类中的上下文信息进行类型转换】

ConversionService是【Spring类型】转换体系的核心接口。
能够利用ConversionFactoryBean在spring的IOC容器中定义一个ConversionService。spring将自动识别IOC容器中的Conversion,并在bean属性配置及Springmvc处理方法入参绑定等场景使用它进行数据的转换。
能够经过ConversionServiceFactoryBean的converters属性注册自定义的类型转换器。

<!--第一步: 前台输入框输入符合格式的数据 -->

<span>自定义转换器的使用</span>
<form action="testConversionServiceConverer" method="post">
        <!-- GG-GG.163.com-0-105 lastName-email-gender-department.id -->
Employee : <input type="text" name="employee">
<input type="submit" value="Submit">
</form>

<!--第二步 编写自定义转换器类 实现Converter类 -->

@Component
public class EmployeeConversion implements Converter<String, Employee> {
    //Converter<String, Employee> 将String类型转化为employee的类型
    @Override
    public Employee convert(String source) {
        // source 传入的数据
    //  <!-- GG-GG.163.com-0-105 lastName-email-gender-department.id -->
        System.out.println(source);
        if(source!=null){
            String [] vals = source.split("-");
            if(vals!=null && vals.length==4){
                String lastName=vals[0];
                String email=vals[1];
                Integer gender=Integer.parseInt(vals[2]);
                Department department = new Department();
                department.setId(Integer.parseInt(vals[3]));
                Employee employee = new Employee(null, lastName, email, gender, department);
                System.out.println("进入转化器:"+employee);
                return employee;
            }
        }
        return null;
    }
}

<!--springmvc.xml文件注册自定义转换器 -->
<mvc:annotation-driven conversion-service="ConversionServiceFactoryBean"></mvc:annotation-driven>

<bean id="ConversionServiceFactoryBean" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <ref bean="employeeConversion"/>
            </set>
        </property>
    </bean>

注意:
一、 配置自定义的Convert 须要使用 mvc:annotation-driven 而且要使用conversion-service属性进行咱们的转换器注册,不影响内置的转换器的使用。

二、配置conversion-service=”ConversionServiceFactoryBean”属性可能会使 其他须要mvc:annotation-driven的注解失效,格式化失效,解决方法就是 配置自定义转换器时,配置class时要进行不一样的配置。
【org.springframework.format.support.FormattingConversionServiceFactoryBean】
【 org.springframework.context.support.ConversionServiceFactoryBean】

三、 流程是先进入转化器,而后在进入controller。

mvc:annotation-driven

关于mvc:annotation-driven 的使用说明

一、配置页面进行不通过controller处理直接重定向或转发时,咱们利用其使那些通过RequestMapping注解失效的controller处理生效。
二、 为了处理静态资源问题,咱们配置属性,配置以后,RequestMapping注解失效,配置其使其余注解生效。
三、配置自定义转换器,咱们要用到mvc:annotation-driven的属性conversion-service。

为何要配置 mvc:annotation-driven

官方文档中提到:
The above registers a RequestMappingHandlerMapping, a RequestMappingHandlerAdapter,
and an ExceptionHandlerExceptionResolver (among others) in support of processing
requests with annotated controller methods using annotations such as @RequestMapping ,
@ExceptionHandler, and others.
It also enables the following:
1. Spring 3 style type conversion through a ConversionService instance in addition to the JavaBeans PropertyEditors used for Data Binding.
2. Support for formatting Number fields using the @NumberFormat annotation through the
ConversionService.
3. Support for formatting Date, Calendar, Long, and Joda Time fields using the @DateTimeFormat annotation.
4. Support for validating @Controller inputs with @Valid, if a JSR-303 Provider is present on the classpath.
5. HttpMessageConverter support for @RequestBody method parameters and @ResponseBody
method return values from @RequestMapping or @ExceptionHandler methods.
翻译过来便是下文:
【mvc:annotation-driven】会进行自动注册
【RequestMappingHandlerMapping】【RequestMappingHandlerAdapter】【ExceptionHandlerExceptionResolver】三个bean。
此外还将提供支持:
一、支持使用【ConversionService】实例对表单参数及新宁类型转换
二、支持使用【@NumberFormatannotation】【@DateTimeFormat】注解完成数据类型的格式化
三、支持使用【@valid】注解对javaBean实例进行JSR303 验证
四、支持使用【@RequestBody】和【@ResponseBody】注解

建议在项目中的bean的setter方法中添加断点进行调试,而后找到【ModelAttributeMethodProcessor】类观察binder变量【conversionService】,而后再找到任意一个【DispatchServlet】点进去进行观察this变量的【HandlerAdapter】【HandlerMapping】【HandlerExceptionResolver】,而后咱们分别屏蔽和添加配置【mvc:annotation-driven】和【mvc:default-servlet-handler】进行相应的观察,最后咱们得出他们之间的区别:
这里写图片描述
因此这个配置通常都要进行添加的。属于标配、

@InitBinder

一、有@InitBinder标识的方法,能够对WebDataBinder对象进行初始化。WebDataBinder是DataBinder的子类,用于完成表单字段到JavaBean输赢的绑定,因此咱们能够利用这个注解对JavaBean属性进行一些操做。
二、有@InitBinder标识的方法不能有返回值,必须声明为void。
三、有@InitBinder标识的方法的参数一般是WebDataBinder。
四、WebDataBinder中存在一些方法能够对属性进行操做而且也能够利用父类DataBinder中的方法。

@InitBinder
    public void initBinder(WebDataBinder webDataBinder){
        // 不对java bean中的 lastName 属性进行赋值 ,另行处理
        webDataBinder.setDisallowedFields("lastName");
    }

数据格式化

对属性对象的输入/输出进行的格式化,实际上是属于“类型转换”的范畴。Spring 在格式化模块中定义了一个实现【ConversionService接口】的【FormattingConversionService实现类】,因为该实现类又扩展了【GenericConversionService类】,因此它不只仅具备格式化的功能,还具备类型转换的功能。
FormattingConversionService有一个FormattingConversionServiceFactoryBean工厂类,后者主要是用在spring上下文中构造前者。
在FormattingConversionServiceFactoryBean的内部已经注册了【NumberFormatAnnotationFormatterFactory类:支持对数字类型的属性使用@NumberFormat注解】【JodaDateTimeFormatAnnotationFormatterFactory类:支持对日期类型的属性使用@dateTimeFormat注解】
装配了【FormattingConversionServiceFactoryBean】后,就能够在Springmvc入参绑定及模型数据输出时使用上述的注解驱动了。然而【mvc:annotation-driven】默认建立的【ConversionService】实例即为【FormattingConversionServiceFactoryBean】。因此咱们能够直接进行使用。

日期格式化:

@DateTimeFormat注解 能够对【java.util.Date】【java.util.Calendar】【java.long.Long】时间类型进行标注。
属性值:
pattern:字符串类型。指定解析/格式化字段数据的模式,eg:”yyyy-MM-dd”前台传递的String数据为“2017-03-03”最为经常使用pattern
iso:类型为DateTimeFormat.ISO。指定解析/格式化字段数据的ISO模式,包括四种ISO.NONE(不使用)–默认值,ISO.DATE(yyyy-MM-dd),ISO.TIME(HH:mm:ss.SSSZ, e.g. 01:30:00.000-05:00),ISO.DATE_TIME(HH:mm:ss.SSSZ, e.g. 01:30:00.000-05:00.)
style:字符串类型。经过样式指定日期时间的格式,由两位字符组成,第一位表示日期格式,第二位表示时间格式;

数值格式化:

@NumberFormat 能够对相似数字类型的属性进行标注。他的两个属性为互斥的。
style:类型为NumberFormatStyle。用于指定样式类型。包括【Style.CURRENCY,货币类型】【Style.NUMBER,正常数字类型】【Style.PERCENT,百分数类型】
pattern:类型为String,自定义样式 【pattern=”#,###,###.#”】注意这里的匹配用的是#号,经常使用。

@DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birthday;
    @NumberFormat(pattern="#,###,###.#")
    private Double salary;

数据校验

JSR303

JSR303 是Java为Bean数据合法性校验提供的一个标准框架。注意是Java Bean。
JSR303 经过在Bean 属性上标注相似与@NotNull,@Max等标准的注解指定校验规则,并经过标准的验证接口对Bean进行验证。
JSR303注解以下:
@Null 被注释的元素必须为 null

@NotNull 被注释的元素必须不为 null

@AssertTrue 被注释的元素必须为 true

@AssertFalse 被注释的元素必须为 false

@Min(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值

@Max(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值

@DecimalMin(value) 被注释的元素必须是一个数字,其值必须大于等于指定的最小值

@DecimalMax(value) 被注释的元素必须是一个数字,其值必须小于等于指定的最大值

@Size(max, min) 被注释的元素的大小必须在指定的范围内

@Digits (integer, fraction) 被注释的元素必须是一个数字,其值必须在可接受的范围内

@Past 被注释的元素必须是一个过去的日期

@Future 被注释的元素必须是一个未来的日期

@Pattern(value) 被注释的元素必须符合指定的正则表达式hibernate对这个规范作了实现和扩展;

注意:JSR303 虽然是Java为Bean数据合法性校验提供的一个标准框架,可是Spring并无提供JSR303的实现。因此咱们须要本身进行添加jar包实现。

Hibernate Validator 扩展注解

Hibernate Validator 是JSR303 的一个参考实现,除了支持JSR303全部的标准注解以外,他还支持如下的扩展。

@Email 被注释的元素必须是电子邮箱地址

@Length 被注释的字符串的大小必须在指定的范围内

@NotEmpty 被注释的字符串的必须非空

@Range 被注释的元素必须在合适的范围内

Springmvc数据校验

一、对于Spring4.0 拥有本身独立的数据校验框架,同时还支持JSR 303标准的校验框架。
二、Spring在进行数据绑定时,能够同时调用校验框架来完成数据校验工做,在Springmvc中,能够直接经过注解驱动的方式进行数据校验。这也是Struts2 没法比拟的
三、Spring的LocalValidatorFactoryBean既实现了Spring的Validator接口,也实现了JSR 303 的Validator接口。咱们只须要在Spring容器中定义一个LocalValidatorFactoryBean,便可将其注入到须要数据校验的Bean中。
四、Spring自己没有提供JSR303 的实现,因此必须将JSR303 的实现jar包放到类路径下。
五、前面3说到只须要在Spring容器中定义一个LocalValidatorFactoryBean,便可将其注入到须要数据校验的Bean中,那么咱们须要怎么实现呢?其实咱们只须要配置【mvc:annotation-driven】便可,由于它支持使用【@valid】注解对javaBean实例进行JSR303 验证,见上面【mvc:annotation-driven】小节。这个配置会自动给咱们装配一个LocalValidatorFactoryBean,而后咱们能够经过注解【@valid】注解便可完成Springmvc在数据绑定以后执行数据校验的工做。
六、Valid注解标注在表单/命令对象前,通常在Controller的目标方法中进行标注,此时,Springmvc在将请求参数绑定到该入参对象后,就会调用校验框架根据bean注解声明的校验规则进行校验。
七、对于校验结果的保存,Springmvc是经过对处理方法签名的规则来保存到BinderResult后者Errors类型中,因此在配置了Valid注解以后,通常在这个方法的参数中,咱们须要额外的配置一个BinderResult或者Errors类型的参数。【这两个类都位于import org.springframework.validation包】中。
八、若是须要多个bean验证时,须要验证的bean对象和其绑定结果的对象必须是成对出现的,并且他们之间不能有 其余入参的声明。见代码示例

提示消息的国际化

每一个属性在数据校验和数据绑定出现错误时,都会生成一个对应的FieldError对象,并且校验框架会自动为该属性生成4个消息代码,这些代码的规则是一校验注解名为前缀,结合ModelAttribute、属性名以及属性类型名生成多个对应的消息代码【User类中的password属性标注@Pattern注解,当数据不知足该@pattern所定义的规则时,就会产生4个错误代码分别是{Pattern.user.password},{Pattern.password},{Pattern.java.lang.string},{Pattern}】咱们就是根据这些代码信息来进行国际化资源配置的。

使用国际化信息须要在springmvc.xml配置国际化资源文件

JSR303 已经实现了本地化信息显示,可是咱们仍是能够进行错误信息的定制。也能够不进行定制。

当在Springmvc标签显示错误时,Springmvc会查看web上下文是否装配了对应的国际化消息,若是没有则是按照默认的进行显示,若是有则是按照国际化消息显示

若是数据类型转换或者数据格式转换发生错误时,或者是该有的参数不存在时,或者是调用处理方法发生错误时,都会在隐含模型中建立错误消息。其中错误代码前缀以下:
required:必要的参数不存在。【在入参时@RequiredParam(“param1”)标注一个入参必须存在,可是该参数不存在】
typeMismatch:在数据绑定时,发生数据类型不匹配的错误。
methodInvocation:Springmvc在调用处理方法时发生了错误。

数据校验流程

1)如何校验
            a.使用JSR303验证标准
            b.加入 hibernate validate验证框架
            c.在springmvc中配置annotation
            d.在须要的bean的属性上添加对应的注解
            e .在目标方法bean 类型的前面添加@Valid 注解
    2)验证出错转向页面
    3)<form:errors/>标签显示错误信息及国际化标准

所须要的jar包以下,并且要注意jar包之间的冲突问题、、
冲突报错信息【java.lang.NoSuchMethodError: javax.el.ExpressionFactory.newInstance()Ljavax/el/ExpressionFactory;】

这里写图片描述

<!--在springmvc中配置annotation -->
<mvc:annotation-driven></mvc:annotation-driven>

<!--在须要的bean的属性上添加对应的注解 记得是bean-->

    @NotEmpty
    private String lastName;

    @Email
    private String email;   

    @Past
    @DateTimeFormat(pattern="yyyy-MM-dd")
    private Date birthday;

    @NumberFormat(pattern="#,###,###.#")
    private Double salary;

<!--在目标方法bean 类型的前面添加@Valid 注解 -->

//新增一个数据, 第二步 进行提交到后台处理  模拟数据发生错误,当数据发生错误时,咱们要进行记录在BindingResult中
    @RequestMapping(value="/emp",method=RequestMethod.POST)
    public String save(@Valid Employee employee,BindingResult result,Map<String, Object>maps, @Valid User user,BindingResult userresult){
        System.out.println(employee);

        if(result.getErrorCount()>0){ // 检查是否存在 验证出错信息 后台不须要存储错误信息,下面代码只是为了在控制台打印
            System.out.println("出错了");
            for(FieldError error:result.getFieldErrors()){
                System.out.println(error.getField()+":"+error.getDefaultMessage());
            }
            // 验证出错,指向定制的页面 
            maps.put("departments",departmentDAO.getDepartments() );
            return "addemp";
        }   
        employeeDAO.save(employee);
        return "redirect:/list";  // 记得必定是redirect小写的,大写的识别不出来
    }

<!-- 配置国际化资源文件 , 同时根目录下也应该有对应的国际化文件 下图-->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basename" value="i18n"></property>
</bean>



<!-- 前台错误消息输出 path值为 对应的属性值-->
<span>----错误显示区域-----</span><br>
    <form:errors path="*"></form:errors><br><!--总体显示错误 -->
<span>----错误显示区域-----</span>
<!-- 单个显示错误,注意path属性值与input一致 -->
BirthDay:<form:input path="birthday"/> <form:errors path="birthday"/> <br>

这里写图片描述

总结: 数据转换和数据格式化 是对前台数据到后台数据类型的转化与格式,而数据校验则是对前台数据进行必定规则的检查。