拦截器

拦截器配置

过滤器 和 拦截器的 6个区别,别再傻傻分不清了_程序员小富的博客-CSDN博客_过滤器和拦截器

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

SpringMVC中的拦截器用于拦截控制器方法的执行

SpringMVC中的拦截器需要实现HandlerInterceptor

SpringMVC的拦截器必须在SpringMVC的配置文件中进行配置:

1
2
3
4
5
6
7
8
9
10
11
12
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
//这是 在modelandview之前进行的
mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
if (asyncManager.isConcurrentHandlingStarted()) {
return;
}

this.applyDefaultViewName(processedRequest, mv);
mappedHandler.applyPostHandle(processedRequest, response, mv);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.zss.mvc.interceptor;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class FirstInterceptor implements HandlerInterceptor {
//crtl+o执行方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
//返回true进行拦截
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
}
}

xml文件配置

全部拦截1

1
2
3
4
<!--配置拦截器-->
<mvc:interceptors>
<bean class="com.zss.mvc.interceptor.FirstInterceptor"/>
</mvc:interceptors>

全部拦截2

在拦截器进行标记为普通组件

1
2
3
//标记为普通组件
@Component
public class FirstInterceptor implements HandlerInterceptor {

同时也需要xml文件进行扫描

1
2
<!--扫描组件,扫描整个大包-->
<context:component-scan base-package="com.zss.mvc"/>
1
2
3
<mvc:interceptors>
<ref bean="firstInterceptor"/>
</mvc:interceptors>

精准拦截

1
2
3
4
5
6
7
8
9
10
11
<!--配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!--拦截所有-->
<mvc:mapping path="/*"/>
<!--排除-->
<mvc:exclude-mapping path="/target"/>
<ref bean="firstInterceptor"/>
</mvc:interceptor>

</mvc:interceptors>

当然也可以在路径中进行精确定位进行拦截

三个抽象方法

SpringMVC中的拦截器有三个抽象方法:

preHandle:控制器方法执行之前执行preHandle(),其boolean类型的返回值表示是否拦截或放行,返回true为放行,即调用控制器方法;返回false表示拦截,即不调用控制器方法

postHandle:控制器方法执行之后执行postHandle()

afterComplation:处理完视图和模型数据,渲染视图完毕之后执行afterComplation()

多个拦截器的顺序

1
2
3
4
5
<!--配置拦截器-->
<mvc:interceptors>
<ref bean="firstInterceptor"/>
<ref bean="secondInterceptor"/>
</mvc:interceptors>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Component
public class FirstInterceptor implements HandlerInterceptor {
//crtl+o执行方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("1--preHandle");
//返回true进行拦截
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("1--postHandle");
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("1--afterCompletion");
}
}

image-20220428160643972

首先和我们的配置的顺序相关,其次会,是一个逐层紧密闭合的过程

pre

1
2
3
4
5
6
7
8
boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}

post

1
2
3
4
for(int i = this.interceptorList.size() - 1; i >= 0; --i) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
interceptor.postHandle(request, response, this.handler, mv);
}

return false

如果我将第二个拦截器返回false,那么

image-20220428162725939

其实在第二个返回false的时候,第二个的post与after都不会执行了,