拦截器执行流程——补充
IndexController
@Controller
public class IndexController {@RequestMapping("/index")public String toIndex() {System.out.println("IndexController#toIndex() ---> 处理器方法执行了");return "index";}@RequestMapping("/ok")public String toOk(){System.out.println("IndexController#toOk() ---> 处理器方法执行了");return "ok";}
}
Interceptor1
@Component
public class Interceptor1 implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Interceptor1's preHandle!");return true;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Interceptor1's postHandle!");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("Interceptor1's afterCompletion!");}
}
springmvc.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:mvc="http://www.springframework.org/schema/mvc"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd"><!--组件扫描--><context:component-scan base-package="com.pn.controller, com.pn.interceptors"/><!--视图解析器--><bean id="thymeleafViewResolver" class="org.thymeleaf.spring6.view.ThymeleafViewResolver"><property name="characterEncoding" value="UTF-8"/><property name="order" value="1"/><property name="templateEngine"><bean class="org.thymeleaf.spring6.SpringTemplateEngine"><property name="templateResolver"><bean class="org.thymeleaf.spring6.templateresolver.SpringResourceTemplateResolver"><property name="prefix" value="/WEB-INF/thymeleaf/"/><property name="suffix" value=".html"/><property name="templateMode" value="HTML"/><property name="characterEncoding" value="UTF-8"/></bean></property></bean></property></bean><!--配置拦截器--><mvc:interceptors><!--基本配置:第一种方式--><!--注意:基本配置,默认情况下是拦截所有请求的。-->
<!-- <bean class="com.pn.interceptors.Interceptor1"/>--><!--高级配置,指定一些路径被拦截,一些路径不拦截。--><mvc:interceptor>
<!-- 拦截所有路径--><mvc:mapping path="/**"/>
<!-- /ok 请求路径不拦截--><mvc:exclude-mapping path="/ok"/>
<!-- 设置拦截器--><ref bean="interceptor1"/></mvc:interceptor></mvc:interceptors></beans>
index.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>index</title>
</head>
<body>
<h1>拦截器</h1>
</body>
</html>
ok.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>ok</title>
</head>
<body>
<h1>OK!</h1>
</body>
</html>
当在浏览器中分别访问 localhost:8080/springmvc11/ok
和 localhost:8080/springmvc11/index
时,整个执行流程如下:
一. 访问 localhost:8080/springmvc11/ok
流程步骤:
1.请求进入 DispatcherServlet
浏览器请求到达 Spring MVC 的前端控制器 DispatcherServlet
,URL 路径为 /springmvc11/ok
。
2.路径匹配与拦截器检查
- DispatcherServlet 根据
springmvc.xml
中的配置查找匹配的 Handler(控制器方法)。 - 路径
/ok
被<mvc:exclude-mapping path="/ok"/>
明确排除在拦截器之外,因此 Interceptor1 不会拦截此请求。
3.执行目标控制器方法
DispatcherServlet 找到 IndexController
中的 toOk()
方法并执行:
@RequestMapping("/ok")
public String toOk(){System.out.println("IndexController#toOk() ---> 处理器方法执行了");return "ok";
}
4.视图解析与渲染
- 返回的视图名称
ok
被ThymeleafViewResolver
解析为/WEB-INF/thymeleaf/ok.html
。 - 浏览器显示
ok.html
的内容
<h1>OK!</h1>
控制台输出:
IndexController#toOk() ---> 处理器方法执行了
二、访问 localhost:8080/springmvc11/index
流程步骤:
1.请求进入 DispatcherServlet
浏览器请求到达 DispatcherServlet,URL 路径为 /springmvc11/index
。
2.路径匹配与拦截器触发
- DispatcherServlet 查找匹配的 Handler(控制器方法)。
- 路径
/index
符合<mvc:mapping path="/**"/>
的规则,且未被排除,因此 Interceptor1 会拦截此请求。
3.执行拦截器的 preHandle
方法
Interceptor1 的 preHandle
方法被调用:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("Interceptor1's preHandle!");return true; // 返回 true 表示继续执行后续流程
}
4.执行目标控制器方法
DispatcherServlet 执行 IndexController
中的 toIndex()
方法:
@RequestMapping("/index")
public String toIndex() {System.out.println("IndexController#toIndex() ---> 处理器方法执行了");return "index";
}
5.执行拦截器的 postHandle
方法
在控制器方法返回后,但视图渲染前,Interceptor1 的 postHandle
方法被调用:
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {System.out.println("Interceptor1's postHandle!");
}
6.视图解析与渲染
- 返回的视图名称
index
被解析为/WEB-INF/thymeleaf/index.html
。 - 浏览器显示
index.html
的内容:
<h1>拦截器</h1>
7.执行拦截器的 afterCompletion
方法
视图渲染完成后,Interceptor1 的 afterCompletion
方法被调用:
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {System.out.println("Interceptor1's afterCompletion!");
}
控制台输出:
Interceptor1's preHandle!
IndexController#toIndex() ---> 处理器方法执行了
Interceptor1's postHandle!
Interceptor1's afterCompletion!
总结
/ok
请求:直接访问控制器方法,不触发拦截器。/index
请求:触发拦截器的完整生命周期(preHandle
→ 控制器 →postHandle
→ 视图渲染 →afterCompletion
)。