一:分析springmvc绑定数据类型源码
1:问题:
2:数据转换牵扯到以下操作;
3:分析源码
3.1:ConversionService组件:负责数据类型的转换以及格式化功能;
3.2:validators负责数据校验工作;
3.3:bindingResult负责保存以及解析数据绑定期间数据校验产生的错误;
4:图解数据绑定流程
二:自定义类型转换;
1:原理步骤
2:实际操作步骤
2.1:实现Converter接口,做一个自定义类型的转换器
2.2:将这个Converter配置在ConversionService中
2.3:告诉SpringNMVC使用这个ConversionService
2.4:源码上WebDataBinder上的ConversionService组件就替换了;并且还自动添加了默认的转换器
三:《mvc:annotation-driven》
1:《mvc:annotation-driven/》在那配置
2:《mvc:annotation-driven》的作用
2.1:《mvc:default-servlet-handler/》 《mvc:annotation-driven/》都不配置
2.2:只配置《mvc:default-servlet-handler/》
2.3:加上《mvc:default-servlet-handler/》,加上《mvc:annotation-driven/》
四:数据格式化
1:数据格式化概述
2:日期格式化
3:数字格式化
五:数据校验-JSR303校验
1:如何校验
①使用JSR 303验证标准
②加入hibernate validator验证框架-导包
③在SpringMVC配置文件中增加
④需要在bean的属性上增加对应验证的注解
⑤在目标方法bean类型的前面增加@Valid注解
2:检验错误信息展示
3:使用原生表单提示数据校验错误信息
4:提示检验错误信息的国际化配置
4.1:先编写国际化配置文件
4.2:注册配置国际化文件
4.3:如果使用springmvc的表单标签,springmvc会自动提该配置信息
4.4:高级国际化,动态的传入消息参数
5:通过注解属性,确定错误提示信息
分析springmvc绑定数据类型源码
- SpringMVC封装自定义类型对象的时候?javaBean要和页面提交的数据进行一一绑定?
public final Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer, NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {
Assert.state(mavContainer != null, ModelAttributeMethodProcessor requires ModelAndViewContainer);
Assert.state(binderFactory != null, ModelAttributeMethodProcessor requires WebDataBinderFactory);
String name = ModelFactory.getNameForParameter(parameter);
ModelAttribute ann = (ModelAttribute)parameter.getParameterAnnotation(ModelAttribute.class);
if (ann != null) {
mavContainer.setBinding(name, ann.binding());
}
Object attribute = null;
BindingResult bindingResult = null;
if (mavContainer.containsAttribute(name)) {
attribute = mavContainer.getModel().get(name);
} else {
try {
attribute = this.createAttribute(name, parameter, binderFactory, webRequest);
} catch (BindException var10) {
if (this.isBindExceptionRequired(parameter)) {
throw var10;
}
if (parameter.getParameterType() == Optional.class) {
attribute = Optional.empty();
}
bindingResult = var10.getBindingResult();
}
}
if (bindingResult == null) {
//将页面提交过来的数据封装到javaBean的属性中
WebDataBinder binder = binderFactory.createBinder(webRequest, attribute, name);
if (binder.getTarget() != null) {
if (!mavContainer.isBindingDisabled(name)) {
this.bindRequestParameters(binder, webRequest);
}
this.validateIfApplicable(binder, parameter);
if (binder.getBindingResult().hasErrors() && this.isBindExceptionRequired(binder, parameter)) {
throw new BindException(binder.getBindingResult());
}
}
if (!parameter.getParameterType().isInstance(attribute)) {
attribute = binder.convertIfNecessary(binder.getTarget(), parameter.getParameterType(), parameter);
}
bindingResult = binder.getBindingResult();
}
Map bindingResultModel = bindingResult.getModel();
mavContainer.removeAttributes(bindingResultModel);
mavContainer.addAllAttributes(bindingResultModel);
return attribute;
}
-
WebDataBinder:数据绑定器负责数据绑定工作; 数据绑定期间产生的类型转换、格式化、数据校验等问题;
-
ConversionService组件:负责数据类型的转换以及格式化功能; ConversionService中有非常多的converter;不同类型的转换和格式化用它自己的converter
-
validators负责数据校验工作;
-
bindingResult负责保存以及解析数据绑定期间数据校验产生的错误;
图解数据绑定流程
自定义类型转换
1:原理步骤 ConversionService::是一个接口; 它里面有Converter(转换器)进行工作: Converter是ConversionService中的组件; 1、你的Converter得放进ConversionService 中; 2、将WebDataBinder中的ConversionService设置成我们这个加了自定义类型转换器的ConversionService; 需要写的步骤
2:实际操作步骤 2.1:实现Converter接口,做一个自定义类型的转换器 Spring 定义了 3 种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到 ConversionServiceFactoryBean 中:
Converter:将 S 类型对象转为 T 类型对象 ConverterFactory:将相同系列多个 “同质” Converter 封装在一起。如果希望将一种类型的对象转换为另一种类型及其子类的对象(例如将 String 转换为 Number 及 Number 子类(Integer、Long、Double 等)对象)可使用该转换器工厂类 GenericConverter:会根据源类对象及目标类对象所在的宿主类中的上下文信息进行类型转换
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import com.atguigu.springmvc.crud.entities.Department;
import com.atguigu.springmvc.crud.entities.Employee;
/**
* 将字符串转换为Employee对象类型
*/
@Component
public class StringToEmployeeConverter implements Converter {
@Override
public Employee convert(String source) {
if(source!=null){
String[] strs = source.split(-);
if(strs!=null && strs.length == 4){
String lastName = strs[0];
String email = strs[1];
Integer gender = Integer.parseInt(strs[2]);
Integer deptId = Integer.parseInt(strs[3]);
Department dept = new Department();
dept.setId(deptId);
Employee employee = new Employee(null,lastName,email,gender,dept);
System.out.println(source+--converter--+employee);
return employee ;
}
}
return null;
}
}
- 将这个Converter配置在ConversionService中
<!-- 告诉SpringMVC别用默认的ConversionService,
而用我自定义的ConversionService、可能有我们自定义的Converter; -->
<!-- 以后写自定义类型转换器的时候,就使用FormattingConversionServiceFactoryBean来注册;
既具有类型转换还有格式化功能 -->
<bean id=conversionService class=org.springframework.format.support.FormattingConversionServiceFactoryBean>
<!--converters转换器中添加我们自定义的类型转换器 -->
<property name=converters>
<set>
<bean class=com.atguigu.component.MyStringToEmployeeConverter></bean>
</set>
</property>
</bean>
- 告诉SpringNMVC使用这个ConversionService
<!-- conversion-service=conversionService:使用我们自己配置的类型转换组件 -->
<mvc:annotation-driven conversion-service=conversionService></mvc:annotation-driven><!-- conversion-service=conversionService:使用我们自己配置的类型转换组件 -->
<mvc:annotation-driven conversion-service=conversionService></mvc:annotation-driven>
- 源码上WebDataBinder上的ConversionService组件就替换了;并且还自动添加了默认的转换器