一、Spring MVC 工程搭建
- 创建Maven项目,添加Spring MVC依赖
- 添加Web Application
- 配置web.xml
- 配置Spring MVC配置文件dispatcher-servlet.xml
- 新建controller,增加HelloController,增加hello方法,返回page/success.jsp页面
- 在WEB-INF下创建pages目录,该目录下新增加success.jsp
- 打开Artifact,新建lib包,将依赖全部导入lib包下
- 配置tomcat,启动Tomcat,输入localhost:8080/hello,成功返回success.jsp页面
二、Spring MVC 中数据绑定
Spring MVC会将页面请求的数据转换成自定义的类型,如将页面提交的POST表单数据"employeeName=stark&age=40&gender=1&email=stark@gmail.com"转换成Employee对象。
Spring MVC将自定义对象和页面请求绑定时主要涉及以下操作:
- 数据类型转换,页面提交的都是字符串,要将字符串转换成自定义对象的不同类型的属性
- 格式化问题,如日期格式的转换等
- 数据校验,对页面提交的数据进行校验
Debug新增员工时,员工的email是如何赋值给Employee对象的
// 将页面提交的数据封装到Java Bean中 bindRequestParameters(binder, request); 复制代码
封装的过程中发生了数据转换、格式化和校验的操作
WebDataBinder:既数据绑定器,负责数据绑定工作,涉及了类型转换、格式化、数据校验等
- conversionService组件:负责数据类型转换以及格式化
- validators组件:负责数据校验
- bindingResult组件:负责保存解析数据绑定期间数据校验产生的错误
Spring MVC数据绑定流程 Spring MVC通过反射机制对目标方法进行解析,将请求数据绑定到处理方法的入参中,数据绑定的核心是DataBinder。
三、自定义类型转换器
ConversionService组件负责数据转换和格式化,ConversionService中有非常多的converter转换器,可以将页面提交的String类型数据转换成各种类型的数据,也可以通过实现Converter接口自定义类型转换器。
将spring-mvc-crud工程复制并重命名为spring-mvc-data;在list页面增加添加员工表单,向后台quickadd方法提交”empAdmin-admin@qq.com-1-101“这种类型的数据
<form action="/quickadd"> <%--将员工信息都填上,自动封装对象--%> <input name="empinfo" value="empAdmin-admin@qq.com-1-101"> <input type="submit" value="快速添加"> </form> 复制代码
Controller方法中增加quickAdd方法
@RequestMapping("/quickadd") public String quickAdd(@RequestParam("empinfo") Employee employee){ // 输出的封装对象为null System.out.println("封装的对象:"+ employee); return "redirect:/emps"; } 复制代码
重启Tomcat,在list页面执行快速添加操作
点击快速添加,页面报错Spring MVC无法将一段字符串“empAdmin-admin@qq.com-1-101”转换为Employee,这就需要自定义一个类型转换器,将String转换为Employee
Spring定义了3种类型的转换器接口,实现任意一个转换器接口都可以作为自定义转换器注册到ConversionServiceFactoryBean中:
- Converter<S,T>:将S类型转换为T类型
- ConverterFactory:将相同系列多个同质Converter封装在一起,如果希望将一种类型的对象转换为另一种类型及其子类的对象可使用该转换器工厂类
- GenericConverter:会根据源类对象及目标类对象所在的宿主类中上下文信息进行类型转换
3-1 实现自定义类型转换器
新建converter包,增加String转换为Employee的转换器类StringToEmployeeConverter
public class StringToEmployeeConverter implements Converter<String, Employee> { @Autowired private DepartmentDao departmentDao; @Override public Employee convert(String source) { System.out.println("将提交的String类型转换为Employee类型"); if (!source.contains("-")){ return null; } String[] empInfo = source.split("-"); Employee employee = new Employee(); employee.setLastName(empInfo[0]); employee.setEmail(empInfo[1]); employee.setGender(Integer.parseInt(empInfo[2])); Department department = departmentDao.getDepartment(Integer.parseInt(empInfo[3])); employee.setDepartment(department); return employee; } } 复制代码
通过实现Converter接口实现转换,接口的泛型分别为源数据类型和目标数据类型,convert方法返回要转换的类,通过将String类型拆分并赋值给新建的一个Employee对象实现String到Employee的转换。
注册自定义的转换器
<mvc:annotation-driven conversion-service="conversionServiceFactory"></mvc:annotation-driven> <!--使用自定义的ConverterService--> <bean id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean"> <!--将自定义的转换器加入到converters中--> <property name="converters"> <set> <bean class="com.citi.converter.StringToEmployeeConverter"></bean> </set> </property> </bean> 复制代码
完成EmployeeController中的quickAdd方法
@RequestMapping("/quickadd") public String quickAdd(@RequestParam("empinfo") Employee employee){ // 输出的封装对象为null System.out.println("封装的对象:"+ employee); employeeDao.save(employee); return "redirect:/emps"; } 复制代码
重启Tomcat,执行添加操作
自定义转换器步骤
- 实现Converter接口,实现convert方法
- 将自定义的Converter配置在ConversionService中
- 注册添加了自定义Converter的ConversionService
3-2 mvn:annotation-driven 标签
mvn:annotation-driver 标签支持以下这些功能:
- 自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter及ExceptionHandlerExceptionResolver三个组件
- 支持ConversionService实例对表单参数进行类型转换
- 支持@NumberFormat、@DataTimeFormat注解完成数据类型格式化
- 支持@Valid注解对Bean进行数据校验
- 支持@RequstBody和@ResponseBody注解