拦截器、验证器的使用
SpringMVC 框架
拦截器[Interceptor]
主要是针对SpringMVC框架中的控制器进行拦截
使用Interceptor的步骤
- ###### 编写一个 拦截器类,需要实现
HandlerInterceptor
, 或者 继承HandlerInterceptorAdapter
类
这个接口有三个方法
- preHandle 方法, 在执行目标Handler【小C控制器中的某个方法】之前 被调用
- postHandle 方法, 在执行目标Handler【小C控制器中的某个方法】之后,但是在View被渲染之前
- afterCompletion 方法,也就是请求完成【VIEW被渲染】后执行
注:我们可以根据需要来决定重写哪个方法,不是所有方法都要重写的。
另外,preHandle 方法的返回值是布尔类型,为true时,则执行目标控制器中方法,如果为false,则应该直接响应客户端。
注:SpringMVC中提供了HandlerInterceptorAdapter
类,我们只需要继承这个类即可,并重写你需要重写的方法即可。
- 在xxxx-servlet.xml中,来配置 拦截器。【注:SpringMVC中暂没有提供 拦截器的注解配置】
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path=""/>
<mvc:exclude-mapping path=""/>
<bean class="注解的类路径"/>
</mvc:interceptor>
<!-- 可以配置多个 -->
</mvc:interceptors>
如果我们配置了多个拦截器,则这些拦截器的执行顺序就是我们配置的顺序.
配置了多个拦截器后,此处假设我们有 Interceptor1, 和 Interceptor2, 它们的执行顺序:
- Interceptor1.preHandle()
- Interceptor2.preHandle()
- 执行目标的Handler【也就是控制器的目标方法】
- Interceptor2.postHandle()
- Interceptor1.postHandle()
- 渲染视图后
- Interceptor2.afterCompletion()
- Interceptor1.afterCompletion()
注:
如果拦截器链中的某个拦截器的preHandle方法返回false, 则这个拦截器后面的拦截器以及目标Controller的方法都不再执行,当然,postHandle方法也不会执行,但是,preHandle方法返回true的那个拦截器中的afterCompletion方法会执行。
数据验证Bean Validation
前端页面我们可以通过JS来进行验证,但是,前端的验证是很容易被“跳过”的,所以,在后端我们还是需要做数据的验证,它是为了保证数据的合法性和可用性。
所以,在严谨的系统中,前后端的数据验证都是需要做的。
在SpringMVC框架中,后端如何来做数据的验证呢?
步骤
在
WebMvcConfig
类中,重写父类的 getValidator() 方法, 指定ValidationMessageSource,如果不指定,会去classpath下面查找一个名为ValidationMessages
的默认属性文件, 建议是我们自己指定写一个方法,返回 ValidationSource, 具体参考代码
编写属性文件,可以以 国际化的格式来写,如:validationMessages_zh.properties, 它有三部份:
- baseName, 如 ValidationMessages
- 语言代码, 如: zh, en
- 国家代码, 如: cn, us
利用 JSR-303的验证规范,导入 Hibernate-Validator 依赖【它是JSR303的实现者】
在你需要做数据验证的实体类[entity]或数据传输对象[dto]或 值对象[Value Object] 的上面添加如下的注解:
JSR303规范中定义的注解,所在包: javax.validation.constraints:
| 注解类 | 说明 | | ————————— | ——————————————– | | @Null | 必须为 null | | @NotNull | 必须不为 null | | @AssertTrue | 必须为 true | | @AssertFalse | 必须为 false | | @Min(value) | 必须是一个数字,其值必须大于等于指定的最小值 | | @Max(value) | 必须是一个数字,其值必须小于等于指定的最大值 | | @DecimalMin(value) | 必须是一个数字,其值必须大于等于指定的最小值 | | @DecimalMax(value) | 必须是一个数字,其值必须小于等于指定的最大值 | | @Size(min, max) | 大小必须在指定的范围内 | | @Digits (integer, fraction) | 必须是一个数字,其值必须在可接受的范围内 | | @Past | 必须是一个过去的日期 | | @Future | 必须是一个将来的日期 | | @Pattern(value) | 必须符合指定的正则表达式 |
Hibernate-Validator提供的注解:
| 注解类 | 说明 | | ——— | ——————————— | | @Email | 必须是电子邮箱地址 | | @Length | 字符串的长度必须在指定的范围内 | | @NotEmpty | 必须非空(有空格就不算Empty) | | @NotBlank | 字符串的必须非空(单纯空格算Blank) | | @Range | 必须在指定范围内 |
编写控制器
- 在控制器中的方法中,要使用 @Validated 注解,同时,要保证验证的对象与BindingResult 连在一起
@Controller public class ValidatorController { @RequestMapping("/register2") public String testRegisterValidation(Model model, @Validated UserDto userDto, BindingResult bindingResult) { //验证失败的信息会绑定到 bindingResult对象中,所以,我们要判断bindingResult if(bindingResult.hasErrors()) { // List<FieldError> errors = bindingResult.getFieldErrors(); for(FieldError fe : errors) { System.out.println(fe.getField()+" => "+fe.getDefaultMessage()); } //返回到当前页面 return "forward:/register2.jsp"; } return "forward:/index.jsp"; } }
当然,我们也可以把这个错误信息包装好后绑定到model中,并在JSP页面中通过 EL表达式取出来。