数据格式化概述
- 对属性对象的输入/输出进行格式化,从其本质上讲依然属于 “类型转换” 的范畴。
- Spring 在格式化模块中定义了一个实现 ConversionService 接口的 FormattingConversionService 实现类,该实现类扩展了 GenericConversionService,因此它既具有类型转换的功能,又具有格式化的功能
- FormattingConversionService 拥有一个 FormattingConversionServiceFactroyBean 工厂类,后者用于在 Spring 上下文中构造前者,FormattingConversionServiceFactroyBean 内部已经注册了 :
- NumberFormatAnnotationFormatterFactroy:支持对数字类型的属性使用 @NumberFormat 注解
- JodaDateTimeFormatAnnotationFormatterFactroy:支持对日期类型的属性使用 @DateTimeFormat 注解
- 装配了 FormattingConversionServiceFactroyBean 后,就可以在 Spring MVC 入参绑定及模型数据输出时使用注解驱动了。
- mvc:annotation-driven/ 默认创建的 ConversionService 实例即为 DefaultFormattingConversionService
//日期格式化
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birth;
//数值格式化
@NumberFormat(pattern="#,###.#")
private double salary;
BindingResult 获取失败结果
如果页面出现400的错误代码,说明填写的数据格式不正确 后台打印出错信息:借助BindingResult类
@RequestMapping(value = "/testFormat", method = RequestMethod.POST)
public String save(Employee employee, BindingResult bindingResult) {
System.out.println(employee.toString());
if (bindingResult != null && bindingResult.getFieldErrorCount() > 0) {
List<FieldError> fieldErrors = bindingResult.getFieldErrors();
for (FieldError fieldError : fieldErrors) {
System.out.println(fieldError.getField() + "\t" + fieldError.getDefaultMessage());
}
throw new RuntimeException("数据出错......");
}
return "redirect:/emps";
}
JSR303数据校验
JSR 303 是 Java 为 Bean 数据合法性校验提供的标准框架,它已经包含在 JavaEE 6.0 中 . JSR 303 通过在 Bean 属性上标注类似于 @NotNull、@Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean 进行验证
①使用JSR 303验证标准 ②加入hibernate validator验证框架 ③在SpringMVC配置文件中增加mvc:annotation-driven/ ④需要在bean的属性上增加对应验证的注解 ⑤在目标方法bean类型的前面增加@Valid注解
- Hibernate Validator 是 JSR 303 的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解
Spring MVC 数据校验
- Spring 4.0 拥有自己独立的数据校验框架,同时支持 JSR 303 标准的校验框架。
- Spring 在进行数据绑定时,可同时调用校验框架完成数据校验工作。在 Spring MVC 中,可直接通过注解驱动的方式进行数据校验
- Spring 的 LocalValidatorFactroyBean 既实现了 Spring 的 Validator 接口,也实现了 JSR 303 的 Validator 接口。只要在 Spring 容器中定义了一个 LocalValidatorFactoryBean,即可将其注入到需要数据校验的 Bean 中。
- Spring 本身并没有提供 JSR303 的实现,所以必须将 JSR303 的实现者的 jar 包放到类路径下。
- mvc:annotation-driven/ 会默认装配好一个 LocalValidatorFactoryBean,通过在处理方法的入参上标注 @Valid 注解即可让 Spring MVC 在完成数据绑定后执行数据校验的工作 在已经标注了 JSR303 注解的表单/命令对象前标注一个 @Valid,Spring MVC 框架在将请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验
- 加入jar包
hibernate-validator-5.0.0.CR2\dist
hibernate-validator-5.0.0.CR2.jar
hibernate-validator-annotation-processor-5.0.0.CR2.jar
hibernate-validator-5.0.0.CR2\dist\lib\required (EL就不需要加了)
classmate-0.8.0.jar
jboss-logging-3.1.1.GA.jar
validation-api-1.1.0.CR1.jar
在验证属性上增加验证注解
public class Employee {
private Integer id;
@NotEmpty
private String lastName;
@Email
private String email;
//1 male, 0 female
private Integer gender;
private Department department;
//关于类型转换
@Past //被标注的日期必须是一个过去的日期
@DateTimeFormat(pattern="yyyy-MM-dd")
private Date birthDay ;
@NumberFormat(pattern="#,###,###.#")
private double salary ;
}
//对employee的校验结果会保存在对象bindingResult中,在方法的入参中bindingResult必须紧跟在employee之后
@RequestMapping(value="/emp",method=RequestMethod.POST)
public String save(@Valid Employee employee,BindingResult bindingResult,Map<String,Object> map){
if(bindingResult.getErrorCount() > 0){
List<FieldError> list = bindingResult.getFieldErrors();
for (FieldError fieldError : list){
System.out.println(fieldError.getField()+"\t"+fieldError.getCode()+"\t"+fieldError.getDefaultMessage());
}
//出错后跳转回录入页面
map.put("departments",departmentDao.getDepartments());
map.put("genders", getGenders());
return "input";
}
System.out.println("===="+employee.toString());
employeeDao.save(employee);
return "redirect:/emps";
}
1️⃣需校验的 Bean 对象和其绑定结果对象或错误对象是成对出现的,它们之间不允许声明其他的入参 在这里插入图片描述 2️⃣Errors 接口提供了获取错误信息的方法,如 getErrorCount() 或 getFieldErrors(String field) 3️⃣BindingResult 扩展了 Errors 接口 在表单/命令对象类的属性中标注校验注解,在处理方法对应的入参前添加 @Valid,Spring MVC 就会实施校验并将校验结果保存在被校验入参对象之后的 BindingResult 或 Errors 入参中。BindingResult 或 Errors 常用方法:
FieldError getFieldError(String field)
List<FieldError> getFieldErrors()
Object getFieldValue(String field)
Int getErrorCount()
数据校验的示例:
- 加入jar包 classmate-0.8.0.jar hibernate-validator-5.0.0.CR2.jar hibernate-validator-annotation-processor-5.0.0.CR2.jar jboss-logging-3.1.1.GA.jar validation-api-1.1.0.CR1.jar
- 需验证的属性前加注解
@NotNull
private String name;
@Email
private String email;
- 处理器类接收参数的对象前加注解@Valid,另外要注意验证的对象employee和绑定验证对象验证结果的bingdingResult对象在行参列表中不能被其他形参隔开
@RequestMapping(value = "/testFormat", method = RequestMethod.POST)
public String save(@Valid Employee employee, BindingResult bindingResult, Map<String, Object> map) {
if (bindingResult.getErrorCount() > 0) {
System.out.println("录入信息出错了......");
List<FieldError> list = bindingResult.getFieldErrors();
for (FieldError fieldError : list) {
System.out.println(fieldError.getField() + "\t" + fieldError.getDefaultMessage());
// 出错后跳转回录入页面
map.put("departments", "D-AA");
map.put("genders", "mail");
return "input";
}
}
System.out.println(employee.toString());
return "redirect:/emps";
}
自定义验证错误消息:在国际化资源中配置,格式:注解名+类名+字段名,例如
Email.employee.email=邮箱格式不正确!
<!--国际化信息 配置 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n" /><!-- 国际化信息所在的文件名 -->
</bean>
<!--国际化信息 配置 -->
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="i18n" /><!-- 国际化信息所在的文件名 -->
</bean>
提示消息的国际化
- 每个属性在数据绑定和数据校验发生错误时,都会生成一个对应的 FieldError 对象。
- 当一个属性校验失败后,校验框架会为该属性生成 4 个消息代码,这些代码以校验注解类名为前缀,结合 modleAttribute、属性名及属性类型名生成多个对应的消息代码:例如 User 类中的 password 属性标注了一个 @Pattern 注解,当该属性值不满足 @Pattern 所定义的规则时, 就会产生以下 4 个错误代码: Pattern.user.password Pattern.password Pattern.java.lang.String Pattern
- 当使用 Spring MVC 标签显示错误消息时, Spring MVC 会查看 WEB 上下文是否装配了对应的国际化消息,如果没有,则显示默认的错误消息,否则使用国际化消息。
- 若数据类型转换或数据格式转换时发生错误,或该有的参数不存在,或调用处理方法时发生错误,都会在隐含模型中创建错误消息。其错误代码前缀说明如下:
- required:必要的参数不存在。如 @RequiredParam(“param1”) 标注了一个入参,但是该参数不存在
- typeMismatch:在数据绑定时,发生数据类型不匹配的问题
- methodInvocation:Spring MVC 在调用处理方法时发生了错误
- 注册国际化资源文件