您的位置:首页 > 编程语言 > Java开发

SpringMVC-8 数据类型转换、数据格式化与数据校验

2017-03-28 17:21 477 查看
  数据类型转换、数据格式化与数据校验的具体实现代码下载地址:http://download.csdn.net/download/bingbeichen/9796699

1. 数据绑定流程

  SpringMVC通过反射机制对目标处理方法进行解析,将请求消息绑定到处理方法的入参中。其中,数据绑定的核心部件是DataBinder,运行机制如下:

  


  数据绑定的具体流程说明如下:

SpringMVC主框架将ServletRequest对象和目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象;

DataBinder调用装配在SpringMVC上下文中的ConversionService组件进行数据类型转换与格式化操作,并将Servlet中的请求信息填充到入参对象中;

SpringMVC进而调用Validator组件对已经绑定请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData对象;

SpringMVC抽取BindingResult中的入参对象和校验错误对象,将其赋给处理方法的响应入参中。

// ModelAttributeMethodProcessor的resolveArgument()方法的核心代码:
WebDataBinder binder = binderFactory.createBinder(request, attribute, name);
if (binder.getTarget() != null) {
bindRequestParameters(binder, request); //绑定请求数据到入参中
validateIfApplicable(binder, parameter); //校验入参中数据的合法性
if (binder.getBindingResult().hasErrors()) {
if (isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
}


2. 数据类型转换

  SpringMVC上下文中内建了许多数据类型转换器,可完成大多数Java类型的换工作,具体可通过调试模式查看binder的conversionService属性值。

  


3. 自定义数据类型转换器

  明确需求:

// 将表单输入的name-email-gender-department.id字符串转换为Employee对象
@RequestMapping("/testEmployeeConverter")
public String testEmployeeConverter(Employee employee) {
System.out.println(employee);
return "redirect:/emps";
}


  第一步:自定义实现Converter接口的数据类型转换器类,并添加到Spring的IoC容器中;

package com.qiaobc.springmvc.converter;

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

import com.qiaobc.springmvc.domain.Department;
import com.qiaobc.springmvc.domain.Employee;

// 三种类型的数据转换器接口:Converter<S,T>、ConverterFactory、GenericConverter
@Component
public class EmployeeConverter implements Converter<String, Employee>{

@Override
public Employee convert(String source) {
if(source != null) {
String[] strs = source.split("-");
if(strs != null && strs.length == 4) {
String name = strs[0];
String email = strs[1];
String gender = strs[2];
Department department = new Department();
department.setDeptId(Integer.parseInt(strs[3]));
return new Employee(null, name, email, gender, department);
}
}
return null;
}

}


  第二步:在SpringMVC的配置文件中,通过ConversionServiceFactoryBean的converters属性注册自定义的类型转换器;

<!--
配置数据类型转换器:
1). ConversionService是SpringMVC类型转换体系的核心接口;
2). 可以利用ConversionServiceFactoryBean在Spring的IoC容器中定义一个ConversionService;
3). Spring将自动识别IOC容器中的ConversionService,并在Bean属性配置及SpringMVC处理方法入参绑定等场合使用其进行数据类型转换。
-->
<bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<set>
<ref bean="employeeConverter"/>
</set>
</property>
</bean>


  第三步:通过mvc:annotation-driven标签的conversion-service属性,将ConversionServiceFactoryBean注册到SpringMVC的上下文中。

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


4. 关于mvc:annotation-driven

  
<mvc:annotation-driven/>
会自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter与ExceptionHandlerExceptionResolver三个bean,其还将提供如下支持:

支持使用ConversionService实例对表单参数进行类型转换;

支持使用@NumberFormat@DateTimeFormat注解完成数据类型的格式化;

支持使用@Valid注解对JavaBean实例进行JSR 303验证;

支持使用@RequestBody@ResponseBody注解。



5. @InitBinder注解

  由@InitBinder注解标识的方法,可以对WebDataBinder对象进行初始化;WebDataBinder是DataBinder的子类,用于完成由表单字段到JavaBean属性的绑定。注意@InitBinder方法不能有返回值,其入参通常是WebDataBinder对象。

/**
* 在进行数据绑定时,不自动绑定对象中的name属性
* 注意:其对自定义类型转换器并不起作用
* @param binder
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.setDisallowedFields("name");
}


6. 数据格式化

6.1 FormattingConversionServiceFactroyBean

  主要作用:用于在Spring上下文中构造FormattingConversionService。

  其中,FormattingConversionServiceFactroyBean工厂类的内部已经注册:

NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用@NumberFormat注解;

JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用@DateTimeFormat注解;

6.2 mvc:annotation-driven

mvc:annotation-driven默认创建的ConversionService实例即为FormattingConversionServiceFactroyBean;

故配置mvc:annotation-driven后即可在SpringMVC入参绑定及模型数据输出时使用注解驱动,以实现数据类型转换和数据格式化。

6.3 FormattingConversionService

该类是Spring格式化模块中实现了ConversionService接口的实现类;

该类扩展了GenericConversionService,既具有类型转换的功能,又具有格式化的功能。

6.4 日期格式化

  @DateTimeFormat注解可对java.util.Date、java.util.Calendar和java.long.Long时间

类型的属性进行标注,其具有如下属性:

pattern属性:字符串类型,用于指定解析/格式化字段数据的模式,如”yyyy-MM-dd hh:mm:ss”;

iso属性:类型为DateTimeFormat.ISO,用于指定解析/格式化字段数据的ISO模式,包括ISO.NONE(不使用,默认)、ISO.DATE(yyyy-MM-dd) 、ISO.TIME(hh:mm:ss.SSSZ)和ISO.DATE_TIME(yyyy-MM-dd hh:mm:ss.SSSZ);

style属性:字符串类型,用于指定日期时间的格式,由两位字符组成,第一位表示日期的格式,第二位表示时间的格式;S表示短日期/时间格式、M表示中日期/时间格式、L表示长日期/时间格式、F表示完整日期/时间格式、-表示忽略日期或时间格式。

6.5 数值格式化

  @NumberFormat注解可对类似数字类型的属性进行标注,其具有两个互斥的属性:

pattern属性:字符串类型,用于自定义样式,如”#,###,###.#”;

style属性:类型为NumberFormat.Style,用于指定样式类型,包括Style.NUMBER(正常数字类型)、Style.CURRENCY(货币类型)、Style.PERCENT(百分数类型)。

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


7. JSR303数据校验

  JSR 303 是Java为Bean数据合法性校验提供的标准框架,其已经包含在JavaEE 6.0中;JSR 303 通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。

  JSR 303 支持的校验注解如下:

注解功能说明
@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 Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,还支持一下扩展注解:

注解功能说明
@Email被注释的元素必须是电子邮箱地址
@Length被注释的字符串的大小必须在指定的范围内
@NotEmpty被注释的字符串必须非空
@Range被注释的元素必须在合适的范围内

8. SpringMVC数据校验

8.1 基本概念

  ① 关于所需要的jar包

  Spring4.0拥有独立的数据校验框架,同时支持 JSR 303 标准的校验框架;但其本身并没有提供 JSR 303 的实现,故必须将 JSR 303 的实现者的jar包放到类路径下

  ② 关于LocalValidatorFactoryBean工厂类

  该工厂类既实现了Spring的Validator接口,也实现了 JSR 303 的Validator接口;故需要在 Spring 容器中定义LocalValidatorFactoryBean,即可将其注入到需要数据校验的Bean中。

  ③ 关于@Valid注解

  
<mvc:annotation-driven/>
会默认装配LocalValidatorFactoryBean,通过在处理方法的入参上标注@Valid注解即可让SpringMVC在进行数据绑定时,同时调用校验框架完成数据校验工作。

  ④ 关于校验结果

  前一个表单/命令对象的校验结果保存到随后处理方法的入参中,该入参必须是BindingResult或Errors类型;且需注意,需校验的Bean对象和其绑定结果对象或错误对象是成对出现的,其之间不允许声明其他的入参。

8.2 具体实现

  第一步:添加Hibernate Validator验证框架所依赖的jar包,具体如下图所示:

    


  第二步:在SpringMVC配置文件中添加mvc:annotation-driven标签;

  第三步:在需要校验的JavaBean属性上添加相应的校验注解,以Employee为例:

public class Employee {

@NotNull
private String name;

@Email
private String email;

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

// ……
}


  第四步:在处理器目标方法的Bean类型的入参前添加@Valid注解,并添加保存校验结果的对象:

@RequestMapping(value="/emp", method=RequestMethod.POST)
public String save(@Valid Employee employee, BindingResult result, Map<String, Object> map) {
System.out.println(employee);

if(result.getErrorCount() > 0) {
for(FieldError error : result.getFieldErrors()) {
System.out.println(error.getField() + " : " + error.getDefaultMessage());
}

// 指定校验错误时所转向的定制页面
map.put("departments", departmentDao.getDepartments());
return "emp-edit";
}

employeeDao.save(employee);
return "redirect:/emps";
}


9. 校验错误消息的显示

  SpringMVC还会将所有校验结果保存到隐含模型中,该模型中的所有数据最终将通过HttpServletRequest的属性列表暴露给JSP视图对象,故在JSP页面上可以获取错误信息。

<form:form action="${pageContext.request.contextPath }/emp" method="post" modelAttribute="employee">

<!-- 显示所有错误消息 -->
<form:errors path="*"></form:errors><br><br>

Name:<form:input path="name"/>
<!-- 在指点字段后显示当前字段的错误消息 -->
<form:errors path="name"></form:errors>
<br><br>

Email:<form:input path="email"/>
<form:errors path="email"></form:errors>
<br><br>

Birthday:<form:input path="birth"/>
<form:errors path="birth"></form:errors>
<br><br>

<input type="submit" name="submit">

</form:form>


10. 校验错误消息的国际化

  当某属性校验失败后,SpringMVC校验框架会为该属性生成4个消息代码,其以校验注解类名为前缀,结合modelAttribute、属性名及属性类型名;如NotNull.employee.name、NotNull.name、NotNull.java.lang.String和NotNull。

  错误代码前缀除了校验注解类名外,还有如下几种:

错误代码前缀具体说明
required必要的参数不存在;如@RequiredParam(“name”)标注入参,但该参数不存在时发生的错误
typeMismatch在数据绑定时,发生数据类型转换或格式化错误
methodInvocationSpringMVC在调用处理方法时发生错误
  具体实现步骤:

  第一步:创建国际化资源文件i18n.properties,文件内容如下所示:

NotNull.employee.name=\u7528\u6237\u540D\u4E0D\u80FD\u4E3A\u7A7A
Email.employee.email=\u7535\u5B50\u90AE\u7BB1\u683C\u5F0F\u9519\u8BEF
Past.employee.birth=\u51FA\u751F\u65E5\u671F\u4E0D\u80FD\u662F\u5C06\u6765\u65F6\u95F4


  第二步:在SpringMVC配置文件中注册国际化资源文件,具体如下:

<!-- 配置国际化资源文件 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n"></property>
</bean>


  说明:当使用SpringMVC标签显示错误消息时,SpringMVC先查看WEB上下文是否装配对应的国际化消息,若有则显示国际化消息,否则显示默认的错误消息。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐