SpringMVC-拦截器(基础加执行流程)

概述

在开发一个网站时可能有这样的需求:某些页面只希望几个特定的用户浏览。对于这样的访问权限控制,应该如何实现呢?拦截器就可以实现上述需求。在 Struts 2 框架中,拦截器是其重要的组成部分,Spring MVC 框架也提供了拦截器功能。

Spring MVC 的拦截器(Interceptor)与 Java Servlet 的过滤器(Filter)类似,它主要用于拦截用户的请求并做相应的处理,通常应用在权限验证、记录请求信息的日志、判断用户是否登录等功能上。

  1. SpringMVC框架中的拦截器用于对处理器进行预处理和后处理的技术。
  2. 可以定义拦截器链,连接器链就是将拦截器按着一定的顺序结成一条链,在访问被拦截的方法时,拦截器链 中的拦截器会按着定义的顺序执行。
  3. 拦截器和过滤器的功能比较类似,有区别
  4. 过滤器是Servlet规范的一部分,任何框架都可以使用过滤器技术。
  5. 拦截器是SpringMVC框架独有的。
  6. 过滤器配置了/*,可以拦截任何资源。
  7. 拦截器只会对控制器中的方法进行拦截。
  8. 拦截器也是AOP思想的一种实现方式
  9. 想要自定义拦截器,需要实现HandlerInterceptor接口

自定义拦截器步骤

在 Spring MVC 框架中定义一个拦截器需要对拦截器进行定义和配置,定义一个拦截器可以通过两种方式:

一种是通过实现 HandlerInterceptor 接口或继承 HandlerInterceptor 接口的实现类来定义;

另一种是通过实现 WebRequestInterceptor 接口或继承 WebRequestInterceptor 接口的实现类来定义。

这里以实现 HandlerInterceptor 接口的定义方式为例自定义拦截器的使用方法

第一个拦截器

//实现HandlerInterceptor接口
public class MyInterceptor implements HandlerInterceptor {
	
	/**
	 * Controller方法执行前,进行拦截的方法
	 * return true放行
	 * return false拦截
	 * 可以使用转发或者重定向直接跳转到指定的页面
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {

		System.out.println("MyInterceptor:preHandle方法在controller方法执行前执行");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("MyInterceptor:postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行");
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("MyInterceptor:afterCompletion方法在控制器的处理请求放发执行完成后执行,即视图渲染结束之后执行");
		
	}
}

第二个拦截器

//实现HandlerInterceptor接口
public class MyInterceptor2 implements HandlerInterceptor {
	
	/**
	 * Controller方法执行前,进行拦截的方法
	 * return true放行
	 * return false拦截
	 * 可以使用转发或者重定向直接跳转到指定的页面
	 */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("MyInterceptor2:preHandle方法在controller方法执行前执行");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("MyInterceptor2:postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行");
		
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("MyInterceptor2:afterCompletion方法在控制器的处理请求放发执行完成后执行,即视图渲染结束之后执行");
		
	}
}

在上述拦截器的定义中实现了 HandlerInterceptor 接口,并实现了接口中的 3 个方法。有关这 3 个方法的描述如下。

  • preHandle 方法:该方法在控制器的处理请求方法前执行,其返回值表示是否中断后续操作,返回 true 表示继续向下执行,返回 false 表示中断后续操作。
  • postHandle 方法:该方法在控制器的处理请求方法调用之后、解析视图之前执行,可以通过此方法对请求域中的模型和视图做进一步的修改。
  • afterCompletion 方法:该方法在控制器的处理请求方法执行完成后执行,即视图渲染结束后执行,可以通过此方法实现一些资源清理、记录日志信息等工作。

在springmvc.xml中配置拦截器

<!-- 配置拦截器 -->
		<mvc:interceptors>
			<!-- 全局拦截器,拦截所有请求 -->
			<!-- <bean class="com.woniu.interceptor.MyInterceptor"/> -->
			
			<!-- 指定路径拦截器 -->
			<mvc:interceptor>
				<!-- 配置拦截器作用的路径 -->
				<mvc:mapping path="/**"/>
				<!-- 配置不需要拦截的路径 -->
				<mvc:exclude-mapping path=""/>
				<!-- 注册拦截器对象 -->
				<bean class="com.woniu.interceptor.MyInterceptor" />
			</mvc:interceptor>
            <!-- 配置多个拦截器,在编写一个MyInterceptor2拦截器的类 -->
			<mvc:interceptor>
				<!-- 配置拦截器作用的路径 -->
				<mvc:mapping path="/demo01.do"/>
				<!-- 注册拦截器对象 -->
				<bean class="com.woniu.interceptor.MyInterceptor2" />
			</mvc:interceptor>
		</mvc:interceptors>

在以上示例代码中

<mvc:interceptors> 元素用于配置一组拦截器,其子元素 定义的是全局拦截器,即拦截所有的请求。

<mvc:interceptor> 元素中定义的是指定路径的拦截器,其子元素 <mvc:mapping> 用于配置拦截器作用的路径,该路径在其属性 path 中定义。

如上述示例代码中,path 的属性值“/**”表示拦截所有路径,“/demo01.do”表示拦截所有以“/demo01.do”结尾的路径。如果在请求路径中包含不需要拦截的内容,可以通过 <mvc:exclude-mapping> 子元素进行配置。

需要注意的是,<mvc:interceptor> 元素的子元素必须按照 <mvc:mapping…/>、<mvc:exclude-mapping…/>、<bean…/> 的顺序配置。

单个拦截器执行流程

在这里插入图片描述

都为true运行结果:

MyInterceptor:preHandle方法在controller方法执行前执行
rebody:sid=1&sname=zhangsan
MyInterceptor:postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行
MyInterceptor:afterCompletion方法在控制器的处理请求放发执行完成后执行,即视图渲染结束之后执行

多个拦截器的执行流程

在这里插入图片描述

都为true运行结果:

MyInterceptor:preHandle方法在controller方法执行前执行
MyInterceptor2:preHandle方法在controller方法执行前执行
rebody:sid=1&sname=zhangsan
MyInterceptor2:postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行
MyInterceptor:postHandle方法在控制器的处理请求方法调用之后,解析视图之前执行
MyInterceptor2:afterCompletion方法在控制器的处理请求放发执行完成后执行,即视图渲染结束之后执行
MyInterceptor:afterCompletion方法在控制器的处理请求放发执行完成后执行,即视图渲染结束之后执行

总结:

1、从preHandle到postHandle是一个完整的执行链,preHandle在执行的时候有一个为false,后面的都不会执行

2、afterCompletion:任意一个拦截器的preHandle方法返回true,afterCompletion方法会压栈,对应的afterCompletion方法最后会执行

3、拦截器不会拦截页面,只拦截处理器方法,Servlet的Filter过滤器会拦截页面

©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页