6 数据绑定流程
1、数据绑定流程
- SpringMVC框架将ServletRequest对象及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder实例对象。
- DataBinder调用装配在SpringMVC上下文中的ConversionService组件进行数据类型转换、数据格式化工作。将Servlet中的请求信息填充到入参对象中。
- 调用Validator组件对已经绑定了请求消息的入参对象进行数据合法性校验,并最终生成数据绑定结果BindingData对象。
- SpringMVC抽取BindingResult中的入参对象和校验错误对象,将它们赋给处理方法的响应入参。
- SpringMVC通过反射机制对密保方法进行解析,将请求消息绑定到处理方法的入参中。数据绑定的核心部件是DataBinder,运行机制如下:
2、mvc:annotation-driven
- 自动注册RequestMappingHandlerMapping、RequestMappingHandlerAdapter、ExceptionHandlerExceptionResolver三个Bean。
- 提供以下支持:
- 支持ConversionService实例对表单参数进行类型转换。
- 支持使用@NumberFormat、@DateTimeFormat完成数据类型的格式化。
- 支持使用@Valid对JavaBean实例进行JSR 303验证。
- 支持使用@RequestBody和@ResponseBody。
3、@InitBinder
由@InitBinder标识的方法,可以对WebDataBinder对象进行初始化。
WebDataBinder是DataBinder的子类,用于完成由表单字段到JavaBean属性的绑定。
@InitBinder方法不能有返回值。
@InitBinder方法的参数通常是WebDataBinder。
@InitBinder public void initBinder(WebDataBinder binder) { binder.setDisallowedFields("lastName"); }
4、数据格式化
步骤一:配置dispatcher-servlet.xml
<mvc:annotation-driven/>
步骤二:配置实体类
import java.util.Date; public class Employee { @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birth; @NumberFormat(pattern = "#,###,###.#") private float salary; }
5、数据校验:JSR 303
JSR 303是Java为Bean数据合法性校验提供的标准框架,它已经包含在JavaEE6.0中。
JSR 303通过在Bean属性上标注类似于@NotNull、@Max等标准的注解指定校验规则,并通过标准的验证接口对Bean进行验证。
Hibernate Validator是JSR 303的一个参考实现,除支持所有标准的校验注解外,它还支持以下的扩展注解:
- @Email:必须是电子邮箱地址。
- @Length:字符串大小必须在指定的范围内。
- @NotEmpty:字符串必须非空。
- @Range:元素必须在合适的范围内。
Spring4.0拥有自己独立的数据校验框架,同时支持JSR303标准的校验框架。
Spring在进行数据绑定时,可同时调用校验框架完成数据校验工作。在SpringMVC中,可直接通过注解驱动的方式进行数据校验。
Spring的LocalValidatorFactoryBean既实现了Spring的Validator接口,也实现了JSP303的Validator接口。只要在Spring容器中定义一个LocalValidatorFactoryBean,即可将其注入到需要数据校验的Bean中。
Spring本身并没有提供JSP303的实现,所以必须将JSR303的实现者的jar包放到类路径下。
mvc:annotatioin-driven/会默认装配好一个LocalValidatorFactoryBean,通过在处理方法的入参撒花姑娘标注@Valid注解即可让SpringMVC在完成数据绑定后执行数据校验的工作。
在已经标注了JSR303注解的表单/命令对象前标注一个@Valid,SpringMVC框架在请求参数绑定到该入参对象后,就会调用校验框架根据注解声明的校验规则实施校验。
SpringMVC是通过对处理方法签名的规则来保存校验结果的:前一个表单/命令对象的校验结果保存到随后的入参中,这个保存校验结果的入参必须是BindingResult或Errors类型,这两个类都位于org.springframework.validation包中。
需校验的Bean对象和其绑定结果对象或错误对象是承兑出现的,它们之间不允许声明其他的入参。
Errors接口提供了获取错误信息的方法,如getErrorCount()、getFieldErrors(String field)。
BindingResult扩展了Errors接口。
如何校验?
1、使用JSR 303校验标准。
2、加入hibernate validator校验框架jar包。
3、在SpringMVC配置文件中添加mvc:annotation-driven/。
4、在Bean的属性上添加对应的注解。
import java.util.Date; public class Employee { @NotEmpty private String lastName; @Email private String email; @Past @DateTimeFormat(pattern = "yyyy-MM-dd") private Date birth; }
5、 在目标方法Bean类型的前面添加@Valid。
@RequestMapping("/test") public String test(@Valid Employee employee, BindingResult result) { return "test"; }
校验出错转向哪个页面?
- 根据BindingResult对象的结果进行定制转向页面。
6、JSON(HttpMessageConvertor)
添加json相关jar包。
jackson-annotations-2.10.3.jar jackson-core-2.10.3.jar jackson-databind-2.10.3.jar
编写目标方法,使其返回JSON对应的对象或集合。
在方法上添加@RequestBody。
@RequestMapping("/testJson") @ResponseBody public Employee testJson() { return new Employee(1001, "E-AA", "aa@qq.com", 1, new Department(101, "D-AA")); }
使用HttpMessageConverter<t>将请求信息转化并绑定到处理方法的入参中或将响应结果转为对应类型的响应信息,Spring提供了两种途径:</t>
- 使用@RequestBody/@ResponseBody对处理方法进行标注。
- 使用HttpEntity<t>/ResponseEntity<t>作为处理方法的入参或返回值。</t></t>
当控制器处理方法使用到@RequestBody/@ResponseBody或HttpEntity<t>/ResponseEntity<t>时,Spring首先根据请求头或响应类型的Accept属性选择匹配的HttpMessageConverter,进而根据参数类型或泛型的过滤得到匹配的HttpMessageConverter,若找不到可用的HttpMessageConverter将报错。</t></t>
@RequestBody和@ResponseBody不需要成对出现。
/** * 文件下载 * @param session * @return * @throws IOException */ @RequestMapping("/testResponseEntity") public ResponseEntity<byte[]> testResponseEntity(HttpSession session) throws IOException { byte[] body = null; ServletContext servletContext = session.getServletContext(); InputStream input = servletContext.getResourceAsStream("/files/abc.txt"); body = new byte[input.available()]; input.read(body); HttpHeaders headers = new HttpHeaders(); headers.add("Content-Disposition", "attachment;filename=abc.txt"); HttpStatus statusCode = HttpStatus.OK; ResponseEntity<byte[]> response = new ResponseEntity<>(body, headers, statusCode); return response; }
7、国际化
关于国际化:
- 在页面撒花姑娘能够根据浏览器语言设置的情况对文本(不是内容)、时间、数值进行本地化处理。
- 可以在Bean中获取国际化资源文件Locale对应的消息。
- 可以通过超链接切换Locale,而不再依赖于浏览器的语言设置情况。
解决:
- 使用JSTL的fmt标签。
- 在Bean中注入ResourceBundleMessageSource的实例,使用其对应的getMessage方法。
- 配置LocalResolver和LocaleChangeInterceptor。