Spring MVC 进阶应用
参数绑定
客户端发送请求时传递的参数默认是键值对格式,Spring MVC
通过参数绑定组件将请求的参数串进行类型转换。
Spring MVC
使用Controller方法的形参接收请求传来的参数。
1. Spring MVC默认内置的形参类型
- HttpServletRequest
- HttpServletResponse
- HttpSession
- Model 一个接口,可以将数据填充到request域对象中。
- ModelMap Model接口的实现。
这5个对象可以直接通过形参注入并使用。
2. 简单数据类型绑定
前端页面表单中的name或者URL中的key与Controller方法中的形参名称一致,即可完成绑定。
如果名称不一致,可以使用@RequestParam
注解指定名称完成绑定。
例如:
|
|
RequestParam注解
- value:参数名,即传入参数的名称。
- required:默认为true,表示请求中要有相应的参数,否则报错:Status 400 - Required Integer parameter ‘XXXX’ is not present
- defaultValue:默认值,没有同名参数时,则使用默认值。
3. JavaBean对象类型绑定
前端页面表单中的name或者URL中的key与JavaBean中的属性名进行匹配。
如果参数名称一致,则将参数绑定到JavaBean中的属性上。
如果JavaBean中包装了对象类型,传入参数的名称则需要按照 对象.属性 的格式编写,并且属性要与JavaBean中包装的对象中的属性名称一致。
4. 集合类型绑定
数组类型绑定
使用checkbox复选框时,会将参数绑定到一个数组中。
例如:
|
|
List集合类型绑定
Controller不能直接在形参中定义List,需要在包装类中定义List。
页面中的编写格式: list名[index].属性名
例如:
|
|
Map集合类型绑定
Controller不能直接在形参中定义Map,需要在包装类中定义Map。
页面中的编写格式:map名[‘key’]
例如:
|
|
Converter
当请求参数中含有日期类型时,需要自定义一个类型转换器转换成我们需要的日期格式。
创建一个类实现Converter接口就可以自定义一个类型转换器。
|
|
之后需要在处理器适配器中注册Converter
|
|
Validation
Spring MVC本身没有实现表现层校验的部分,它本身支持JSR 303校验规范,而这个规范的官方参考实现是hibernate validator。
所以Spring MVC想要实现校验,需要导入Hibernate-validator jar包。
在配置文件中配置validator校验器
|
|
在处理器适配器中注册Validator
|
|
在JavaBean中可以使用注解制定校验规则。
|
|
Controller中在需要检验的形参前使用@Validated
注解,并在形参中注入一个BindingResult对象接收校验错误信息。@Validated
注解和BindingResult顺序是固定的。(@Validated
在前)
|
|
分组校验
因为校验规则是在JavaBean中定义的,所以当同一个JavaBean需要被多个Controller使用时,可能根据需求需要不同的校验。
在这种情况下,可以使用一个标识作用的接口进行分组。
定义一个空接口作为分组的标识:
|
|
在JavaBean中使用分组:
|
|
在Controller中使用分组校验:
|
|
主要的验证注解如下:
注解 | 适用的数据类型 | 说明 |
---|---|---|
@AssertFalse | Boolean, boolean | 验证注解的元素值是false |
@AssertTrue | Boolean, boolean | 验证注解的元素值是true |
@DecimalMax(value=x) | BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence. | 验证注解的元素值小于等于@ DecimalMax指定的value值 |
@DecimalMin(value=x) | BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence. | 验证注解的元素值小于等于@ DecimalMin指定的value值 |
@Digits(integer=整数位数, fraction=小数位数) | BigDecimal, BigInteger, String, byte,short, int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of Number andCharSequence. | 验证注解的元素值的整数位数和小数位数上限 |
@Future | java.util.Date, java.util.Calendar; Additionally supported by HV, if theJoda Time date/time API is on the class path: any implementations ofReadablePartial andReadableInstant. | 验证注解的元素值(日期类型)比当前时间晚 |
@Max(value=x) | BigDecimal, BigInteger, byte, short,int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type ofCharSequence (the numeric value represented by the character sequence is evaluated), any sub-type of Number. | 验证注解的元素值小于等于@Max指定的value值 |
@Min(value=x) | BigDecimal, BigInteger, byte, short,int, long and the respective wrappers of the primitive types. Additionally supported by HV: any sub-type of CharSequence (the numeric value represented by the char sequence is evaluated), any sub-type of Number. | 验证注解的元素值大于等于@Min指定的value值 |
@NotNull | Any type | 验证注解的元素值不是null |
@Null | Any type | 验证注解的元素值是null |
@Past | java.util.Date, java.util.Calendar; Additionally supported by HV, if theJoda Time date/time API is on the class path: any implementations ofReadablePartial andReadableInstant. | 验证注解的元素值(日期类型)比当前时间早 |
@Pattern(regex=正则表达式, flag=) | String. Additionally supported by HV: any sub-type of CharSequence. | 验证注解的元素值与指定的正则表达式匹配 |
@Size(min=最小值, max=最大值) | String, Collection, Map and arrays. Additionally supported by HV: any sub-type of CharSequence. | 验证注解的元素值的在min和max(包含)指定区间之内,如字符长度、集合大小 |
@Valid | Any non-primitive type(引用类型) | 验证关联的对象,如账户对象里有一个订单对象,指定验证订单对象 |
@NotEmpty | CharSequence,Collection, Map and Arrays | 验证注解的元素值不为null且不为空(字符串长度不为0、集合大小不为0) |
@Range(min=最小值, max=最大值) | CharSequence, Collection, Map and Arrays,BigDecimal, BigInteger, CharSequence, byte, short, int, long and the respective wrappers of the primitive types | 验证注解的元素值在最小值和最大值之间 |
@NotBlank | CharSequence | 验证注解的元素值不为空(不为null、去除首位空格后长度为0),不同于@NotEmpty,@NotBlank只应用于字符串且在比较时会去除字符串的空格 |
@Length(min=下限, max=上限) | CharSequence | 验证注解的元素值长度在min和max区间内 |
CharSequence | 验证注解的元素值是Email,也可以通过正则表达式和flag指定自定义的email格式 |
数据回显
Spring MVC默认支持数据回显。
Spring MVC会在Controller返回之前,自动将形参中的JavaBean放入Request域中,默认名称为类名首字母小写。
只要前端页面动态获取数据的key与JavaBean名称一致,即可完成数据回显。
如果名称不一致,也可以用@ModelAttribute
注解指定形参放入Request域中的key名。
文件上传
Spring MVC使用Multipart解析器完成文件上传,而Multipart解析器需要依赖以下2个jar包:
- commons-fileupload
- commons-io
配置Multipart解析器
|
|
需要在Controller形参中注入一个MultipartFile对象接收文件,该对象名字要与传入的文件名相同。
文件上传示例
|
|
Interceptor
Spring MVC的拦截器是针对处理器进行拦截的,当HandlerMapping查找处理器时,会被拦截器拦截。
可以通过实现HandlerIntercepter接口,自定义一个拦截器。
|
|
配置拦截器
|
|
拦截器的执行顺序
- preHandle()为正向顺序执行,postHandle()和afterCompletion()为逆向顺序执行。
- 如果第一个拦截器返回值为false,那它之后所有的拦截器都不会执行。
- 如果一个拦截器返回值为false,那么它的postHandle()和afterCompletion()都不会执行。
- 只要有一个拦截器的返回值为false,则所有拦截器的postHandle()都不会执行。
RESTful
一种软件架构风格,设计风格而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。
实现REST风格需要在DispatcherServlet中将url映射模式改为 /
|
|
但是当映射模式为/时会把静态资源一起拦截,需要配置才能访问静态资源。
|
|
Springmvc会把mapping映射到ResourceHttpRequestHandler,这样静态资源在经过DispatcherServlet转发时就可以找到对应的Handler了。
在Controller中实现RESTful
|
|
@PathVariable
:将URL中的模板变量映射到形参上,如果形参与模板变量名称不一致,可以使用value=” “设置为模板变量的名称完成映射。- {id}:模板变量。例如URL为 xxxx/update/1,模板变量update/{id}就可以将1封装到{id}中。
JSON
Spring MVC默认使用MappingJacksonHttpMessageConverter对json数据进行转换,所以需要导入Jackson的jar包。
Spring MVC可以使用2个注解完成JSON数据的交互操作。
@RequestBody
:如果请求参数传入的是json数据,使用RequestBody
可以将json转换为java对象。@ResponseBody
:将返回值的java对象转换为json输出。