当前位置: 首页 > news >正文

SpringMVC03之拦截器和JSR303

目录

1.什么是拦截器

  2.拦截器与过滤器

        2.1 什么是过滤器(Filter)

        2.2 拦截器与过滤器的区别

3.应用场景

4.拦截器快速入门

        4.1 入门案例

        4.2 拦截器方法说明---详见《自定义拦截器执行流程.png》

preHandle方法

postHandle方法

afterCompletion方法

5.拦截器链(多拦截器)

1. JSR303数据校验

2. JSR303中含有的注解

Hibernate Validator 附加的注解

3. SpringMVC中使用JSR303进行服务器端验证

        3.1 添加相关依赖

        3.2 给校验对象的指定属性添加校验规则

        3.3 在请求处理方法中,使用@Validated或@Valid注解要验证的对象,并根据BindingResult判断校验是否通过。另外,验证参数后必须紧跟BindingResult参数,否则spring会在校验不通过时直接抛出异常

        3.4 在JSP页面上通过form标签显示消息

        3.5 通过BindingResult和form:errors标签在JSP页面显示非验证消息


1.什么是拦截器

  SpringMVC的处理器拦截器,类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。

  依赖于web框架,在实现上基于Java的反射机制,属于面向切面编程(AOP)的一种运用。由于拦截器是基于
  web框架的调用,因此可以使用Spring的依赖注入(DI)进行一些业务操作,同时一个拦截器实例在一个 
  controller生命周期之内可以多次调用。

  2.拦截器与过滤器

        2.1 什么是过滤器(Filter)

     依赖于servlet容器。在实现上基于函数回调,可以对几乎所有请求进行过滤,但是缺点是一个过滤器实例
    只能在容器初始化时调用一次。使用过滤器的目的是用来做一些过滤操作,比如:在过滤器中修改字符编码;
    在过滤器中修改HttpServletRequest的一些参数,包括:过滤低俗文字、危险字符等。

        2.2 拦截器与过滤器的区别

过滤器(filter):

    1) filter属于Servlet技术,只要是web工程都可以使用
    2) filter主要对所有请求过滤
    3) filter的执行时机早于Interceptor

    拦截器(interceptor)

    1) interceptor属于SpringMVC技术,必须要有SpringMVC环境才可以使用
    2) interceptor通常对处理器Controller进行拦截
    3) interceptor只能拦截dispatcherServlet处理的请求

3.应用场景

1)日志记录:记录请求信息的日志,以便进行信息监控、信息统计、计算PV(Page View)等。

 2)权限检查:如登录检测,进入处理器检测是否登录,如果没有直接返回到登录页面;

3)性能监控:有时候系统在某段时间莫名其妙的慢,可以通过拦截器在进入处理器之前记录开始时间,在处理完后记录结束时间,从而得到该请求的处理时间(如果有反向代理,如apache可以自动记录);

4)通用行为:读取cookie得到用户信息并将用户对象放入请求,从而方便后续流程使用,还有如提取Locale、Theme信息等,只要是多个Controller中的处理方法都需要的,我们就可以使用拦截器实现。

4.拦截器快速入门

        4.1 入门案例

创建HelloController
创建自定义拦截器并实现HandlerInterceptor接口。

<mvc:interceptors>
    <bean class="com.zking.springmvc07.interceptor.CustomInterceptor"/>
</mvc:interceptors>

        4.2 拦截器方法说明---详见《自定义拦截器执行流程.png》

preHandle方法

作用:用于对拦截到的请求进行预处理,方法接收布尔(true,false)类型的返回值,返回true:放行,false:不放行。
执行时机:在处理器方法执行前执行 

方法参数:
    1)request请求对象
    2)response响应对象
    3)handler拦截到的方法处理

postHandle方法

作用:用于对拦截到的请求进行后处理,可以在方法中对模型数据和视图进行修改
执行时机:在处理器的方法执行后,视图渲染之前

方法参数:
    1)request请求对象
    2)response响应对象
    3)handler拦截到的处理器方法
    4)ModelAndView处理器方法返回的模型和视图对象,可以在方法中修改模型和视图

afterCompletion方法

作用:用于在整个流程完成之后进行最后的处理,如果请求流程中有异常,可以在方法中获取对象
执行时机:视图渲染完成后(整个流程结束之后)

方法参数:
    1)request请求参数
    2)response响应对象
    3)handler拦截到的处理器方法
    4)ex异常对象

5.拦截器链(多拦截器)

拦截器链的概念:如果多个拦截器能够对相同的请求进行拦截,则多个拦截器会形成一个拦截器链,主要理解拦截器链中各个拦截器的执行顺序。拦截器链中多个拦截器的执行顺序,根拦截器的配置顺序有关,先配置的先执行。

<mvc:interceptors>
      <mvc:interceptor>
          <mvc:mapping path="/**"/>
          <bean class="com.zking.springmvc07.interceptor.CustomInterceptor"/>
      </mvc:interceptor>
      <mvc:interceptor>
          <mvc:mapping path="/user/**"/>
          <bean class="com.zking.springmvc07.interceptor.Custom2Interceptor"/>
      </mvc:interceptor>
</mvc:interceptors>



1. JSR303数据校验

JSR303是Java为Bean数据合法性校验提供给的标准框架,已经包含在 JavaEE6.0中、JSR303通过在Bean 属性中标注类似 @NotNull @Max 等标准的注解指定校验规则,并通过标准的验证接口对 Bean进行验证

   JSR303属于后端验证
   JS属于前端的脚本验证(只作用于客户端的浏览器中,可以被屏蔽)
   技术点:正则表达式

   直接浏览器地址栏回车、借助于第三方的工具(PostMan)

2. JSR303中含有的注解

   @Null   被注释的元素必须为 null  
   @NotNull    被注释的元素必须不为 null  
   @AssertTrue     被注释的元素必须为 true  
   @AssertFalse    被注释的元素必须为 false  
   @Min(value)     被注释的元素必须是一个数字,其值必须大于等于指定的最小值  
   @Max(value)     被注释的元素必须是一个数字,其值必须小于等于指定的最大值  
   @DecimalMin(value)  被注释的元素必须是一个数字,其值必须大于等于指定的最小值  
   @DecimalMax(value)  被注释的元素必须是一个数字,其值必须小于等于指定的最大值  
   @Size(max=, min=)   被注释的元素的大小必须在指定的范围内  
   @Digits (integer, fraction)     被注释的元素必须是一个数字,其值必须在可接受的范围内  
   @Past   被注释的元素必须是一个过去的日期  
   @Future     被注释的元素必须是一个将来的日期  
   @Pattern(regex=,flag=)  被注释的元素必须符合指定的正则表达式  

Hibernate Validator 附加的注解

   @NotBlank(message =)   验证字符串非null,且长度必须大于0  
   @Email  被注释的元素必须是电子邮箱地址  
   @Length(min=,max=)  被注释的字符串的大小必须在指定的范围内  
   @NotEmpty   被注释的字符串的必须非空  
   @Range(min=,max=,message=)  被注释的元素必须在合适的范围内

注:Hibernate Validator是JSR303的一个参考实现,除了支持所有标准的校验注解外,另外Hibernate Validator还有JSR-380的实现  

3. SpringMVC中使用JSR303进行服务器端验证

        3.1 添加相关依赖

<dependency>
     <groupId>org.hibernate</groupId>
     <artifactId>hibernate-validator</artifactId>
     <version>6.0.7.Final</version>
</dependency>

        3.2 给校验对象的指定属性添加校验规则

public class User {
	private Long userId;

	@NotBlank(message = "用户名不能为空")
	private String userName;

	@NotBlank(message = "密码不能为空")
	private String userPwd;

        ............
 
       }

        3.3 在请求处理方法中,使用@Validated或@Valid注解要验证的对象,并根据BindingResult判断校验是否通过。另外,验证参数后必须紧跟BindingResult参数,否则spring会在校验不通过时直接抛出异常

public String login(@Validated @ModelAttribute User user,
			BindingResult bindingResult){
        // 服务器端校验不通过
	if (bindingResult.hasErrors()) {
		return "login";
	}            
        ....
}

注1:@Valid和Validated的区别,随便使用哪个都行
     @Valid是使用hibernate validation的时候使用
     @Validated 是只用spring  Validator校验机制使用

        3.4 在JSP页面上通过form标签显示消息

<form:errors path="*" /> 显示表单所有错误
<form:errors path="user* /> 显示所有以user为前缀的属性对应的错误
<form:errors path="username"/> 显示特定表单对象属性的错误
delimiter:如果一个属性有多个错误,错误信息的分隔符。默认是换行
   

注1:errors标签要放到form标签中才能显示错误消息
注2:如果使用form:errors标签不显示错误消息,请检查Model中是否已经添加了命令对象,没有是不会显示错误消息的
注3:注意命名规范,Book-->book

@ModelAttribute
     public void init(Model model) {
        System.out.println("init...");
        model.addAttribute("user", new User());
     }

        3.5 通过BindingResult和form:errors标签在JSP页面显示非验证消息

public String login(@Valid @ModelAttribute Yh yh, BindingResult bindingResult, Model model){
        bindingResult.rejectValue("yhzh", null, "帐号错误");
        ...
}
bindingResult.rejectValue("email", "validate.email.empty", "邮箱不能为空");//这个函数有好几个重载的变体
它们是可以支持国际化的。 比如,上面这个例子表示, 错误的字段(filed)是“email”, errorCode是“validate.email.empty”, 与资源文件对应, 第三个是defaultMessage
     

感谢观赏!!!

相关文章:

  • 索引失效案例
  • 机器学习笔记 - Albumentations库实现的图像增强功能一览
  • 软考-存储系统
  • 大学生网页设计制作作业实例代码 (全网最全,建议收藏) HTML+CSS+JS
  • GAN Step By Step -- Step4 CGAN
  • HackerRank 算法刷题笔记(一),基于Go语言
  • 【Linux篇】第十三篇——信号(概念+信号的产生+阻塞信号+捕捉信号)
  • Android Jetpack系列之MVI架构
  • 十分钟之内实现stack和queue?容器适配器是什么?priority_queue不是队列?
  • 基于Keras实战项目-猫狗熊猫分类大战
  • 基于 Echarts + Python Flask 动态实时大屏( 附代码)
  • 并查集原理及模拟实现
  • 【Redis】大key的处理
  • T-3.2-把Redis当作消息队列合不合适
  • 简单个人静态HTML网页设计作品 DIV布局个人介绍网页模板代码 DW个人网站制作成品 web网页制作与实现
  • 分享一款快速APP功能测试工具
  • 78. Subsets
  • canvas绘制圆角头像
  • Docker容器管理
  • JavaScript DOM 10 - 滚动
  • Java基本数据类型之Number
  • Java小白进阶笔记(3)-初级面向对象
  • mockjs让前端开发独立于后端
  • SQLServer之创建数据库快照
  • V4L2视频输入框架概述
  • Webpack 4x 之路 ( 四 )
  • 从地狱到天堂,Node 回调向 async/await 转变
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 机器学习中为什么要做归一化normalization
  • 前端存储 - localStorage
  • 思否第一天
  • 微信开放平台全网发布【失败】的几点排查方法
  • PostgreSQL之连接数修改
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • ​VRRP 虚拟路由冗余协议(华为)
  • ###STL(标准模板库)
  • (1)(1.13) SiK无线电高级配置(六)
  • (2020)Java后端开发----(面试题和笔试题)
  • (a /b)*c的值
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (pojstep1.3.1)1017(构造法模拟)
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (分布式缓存)Redis哨兵
  • (附源码)ssm教材管理系统 毕业设计 011229
  • (机器学习-深度学习快速入门)第一章第一节:Python环境和数据分析
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (十)T检验-第一部分
  • (四)linux文件内容查看
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转)Linux下编译安装log4cxx
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation