😀前言
在现代的Web应用开发中,控制请求的流程和管理请求的数据变得至关重要。Spring MVC作为一个强大的框架,为我们提供了许多工具来处理这些挑战。其中,自定义拦截器是一个令人激动的概念,它赋予开发者在请求到达目标方法之前和之后执行自定义逻辑的能力。通过精心设计的拦截器,我们可以轻松地添加身份验证、日志记录、数据处理等功能,从而让我们的应用更加安全、高效和易于维护。
🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉
解锁高级技巧:玩转 Spring MVC 自定义拦截器的神奇世界
🤔什么是拦截器
● 说明
- Spring MVC 也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能.
- 自定义的拦截器必须实现 HandlerInterceptor 接口
● 自定义拦截器的三个方法
- preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request 进行处理。
- postHandle():这个方法在目标方法处理完请求后执行
- afterCompletion():这个方法在完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。
😍自定义拦截器执行流程分析图
● 自定义拦截器执行流程说明
- 如果 preHandle 方法 返回 false, 则不再执行目标方法, 可以在此指定返回页面
- postHandle 在目标方法被执行后执行. 可以在方法中访问到目标方法返回的ModelAndView 对象
- 若 preHandle 返回 true, 则 afterCompletion 方法 在渲染视图之后被执行.
- 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用
- 在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效
😁自定义拦截器应用实例
● 应用实例需求
完成一个自定义拦截器,学习一下如何配置拦截器和拦截器的运行流程
创建MyInterceptor01
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
解读
1. preHandle() 在目标方法执行前被执行
2. 如果preHandle() 返回false , 不再执行目标方法
3. 该方法可以获取到request, response, handler
4. 这里根据业务,可以进行拦截,并指定跳转到哪个页面
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
解读
1. 在目标方法执行后,会执行postHandle
2. 该方法可以获取到 目标方法,返回的ModelAndView对象
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception
解读
afterCompletion() 在视图渲染后被执行, 这里可以进行资源清理工作
@Component public class MyInterceptor01 implements HandlerInterceptor { /** * 解读 * 1. preHandle() 在目标方法执行前被执行 * 2. 如果preHandle() 返回false , 不再执行目标方法 * 3. 该方法可以获取到request, response, handler * 4. 这里根据业务,可以进行拦截,并指定跳转到哪个页面 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("--MyInterceptor01--preHandle()---"); } /** * 解读 * 1. 在目标方法执行后,会执行postHandle * 2. 该方法可以获取到 目标方法,返回的ModelAndView对象 * @param request * @param response * @param handler * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("--MyInterceptor01--postHandle()--"); } /** * 解读 * 1. afterCompletion() 在视图渲染后被执行, 这里可以进行资源清理工作 * @param request * @param response * @param handler * @param ex * @throws Exception */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("--MyInterceptor01--afterCompletion()--"); } }
创建FurnHandler类
@Controller public class FurnHandler { @RequestMapping(value = "/hi") public String hi(User user) { System.out.println("---FurnHandler--hi()---"); return "success"; } @RequestMapping(value = "/hello") public String hello() { System.out.println("---FurnHandler--hello()---"); return "success"; } }
在 springDispatcherServlet-servlet.xml 配置拦截器
<!--配置自定义拦截器-spring配置文件--> <mvc:interceptors> <!-- 解读 1. 第一种配置方式 2. 使用ref 引用到对应的myInterceptor01 3. 这种方式,会拦截所有的目标方法 --> <!--<ref bean="myInterceptor01"/>--> <!--解读 1. 第二种配置方式 2. mvc:mapping path="/hi" 指定要拦截的路径 3. ref bean="myInterceptor01" 指定对哪个拦截器进行配置 --> <!--<mvc:interceptor>--> <!-- <mvc:mapping path="/hi"/>--> <!-- <ref bean="myInterceptor01"/>--> <!--</mvc:interceptor>--> <!--解读 1. 第3种配置方式 2. mvc:mapping path="/h*" 通配符方式 表示拦截 /h 打头的路径 3. mvc:exclude-mapping path="/hello" /hello不拦截 4. ref bean="myInterceptor01" 指定对哪个拦截器配置 --> <mvc:interceptor> <mvc:mapping path="/h*"/> <mvc:exclude-mapping path="/hello"/> <ref bean="myInterceptor01"/> </mvc:interceptor> </mvc:interceptors>
第一种配置方式
使用ref 引用到对应的myInterceptor01
这种方式,会拦截所有的目标方法
第二种配置方式
- mvc:mapping path="/hi" 指定要拦截的路径
- ref bean="myInterceptor01" 指定对哪个拦截器进行配置
<mvc:interceptor> <mvc:mapping path="/hi"/> <ref bean="myInterceptor01"/> </mvc:interceptor>
第3种配置方式
- mvc:mapping path="/h*" 通配符方式 表示拦截 /h 打头的路径
- mvc:exclude-mapping path="/hello" /hello不拦截
- ref bean="myInterceptor01" 指定对哪个拦截器配置
<mvc:interceptor> <mvc:mapping path="/h*"/> <mvc:exclude-mapping path="/hello"/> <ref bean="myInterceptor01"/> </mvc:interceptor>
创建interceptor.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>测试自定义拦截器</title> </head> <body> <h1>测试自定义拦截器</h1> <a href="<%=request.getContextPath()%>/hi">测试自定义拦截器-hi</a><br><br> <a href="<%=request.getContextPath()%>/hello">测试自定义拦截器-hello</a><br/><br/> </body> </html>
完成测试(页面方式)
浏览器 http://localhost:8080/springmvc/interceptor.jsp
完成测试(Postman 方式)
注意
拦截器需要配置才生效,不配置是不生效的.
如果 preHandler() 方法返回了 false, 就不会执行目标方法(前提是你的目标方法被拦截了), 程序员可以在这里根据业务需要指定跳转页面.
🥰多个拦截器执行流程示意图
代码实现
创建MyInterceptor02
@Component public class MyInterceptor02 implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("--MyInterceptor02--preHandle--"); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { System.out.println("--MyInterceptor02--postHandle--"); } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { System.out.println("--MyInterceptor02--afterCompletion--"); } }
配置xml
1.配置的第二个拦截器
2.多个拦截器在执行时,是顺序执行
<!--配置自定义拦截器-spring配置文件--> <mvc:interceptors> <!-- 解读 1. 第一种配置方式 2. 使用ref 引用到对应的myInterceptor01 3. 这种方式,会拦截所有的目标方法 --> <!--<ref bean="myInterceptor01"/>--> <!--解读 1. 第二种配置方式 2. mvc:mapping path="/hi" 指定要拦截的路径 3. ref bean="myInterceptor01" 指定对哪个拦截器进行配置 --> <!-- <mvc:interceptor>--> <!-- <mvc:mapping path="/hi"/>--> <!-- <ref bean="myInterceptor01"/>--> <!-- </mvc:interceptor>--> <!--解读 1. 第3种配置方式 2. mvc:mapping path="/h*" 通配符方式 表示拦截 /h 打头的路径 3. mvc:exclude-mapping path="/hello" /hello不拦截 4. ref bean="myInterceptor01" 指定对哪个拦截器配置 --> <mvc:interceptor> <mvc:mapping path="/h*"/> <mvc:exclude-mapping path="/hello"/> <ref bean="myInterceptor01"/> </mvc:interceptor> <!--解读 1.配置的第二个拦截器 2.多个拦截器在执行时,是顺序执行 --> <mvc:interceptor> <mvc:mapping path="/h*"/> <ref bean="myInterceptor02"/> </mvc:interceptor> </mvc:interceptors>
完成测试(页面方式)
浏览器 http://localhost:8080/springmvc/interceptor.jsp
完成测试(Post 方式)
注意事项和细节
1.如果第1个拦截器的preHandle()返回false,后面都不在执行
2.如果第2个拦截器的preHandle()返回false,就直接执行第1个拦截器的afterCompletion()方法,如果拦截器更多,规则类似
3.说明:前面说的规则,都是目标方法被拦截的前提
😀扩展需求
需求: 如果用户提交的数据有禁用词(比如 病毒),则,在第 1 个拦截器就返回,不执行 目标方法, 功能效果示意图
创建warning.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>警告</title> </head> <body> <h1>不要乱讲话~</h1> </body> </html>
修改MyInterceptor01
@Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { System.out.println("--MyInterceptor01--preHandle()---"); //获取到用户提交的关键字 String keyword = request.getParameter("keyword"); if("病毒".equals(keyword)) { //请求转发到warning request.getRequestDispatcher("/WEB-INF/pages/warning.jsp") .forward(request,response); return false; } System.out.println("得到到keyword= "+ keyword); return true; }
完成测试(使用 Postma)
😄总结
本文深入剖析了Spring MVC中自定义拦截器的核心概念和运作原理。通过详细的代码示例,我们学习了拦截器的三个关键方法:preHandle
、postHandle
和afterCompletion
,以及它们在请求流程中的作用。从拦截器的创建、配置到实际应用,我们探讨了多种不同场景下的用法,并通过实例演示了如何拦截请求、进行数据处理、实现条件跳转等功能。
自定义拦截器不仅仅是一种技术手段,更是提升应用质量和开发效率的关键工具。通过合理的拦截器设计,我们可以将横切关注点与核心业务逻辑解耦,使代码更加模块化和可维护。在今天不断演进的Web开发领域,掌握自定义拦截器的知识,将为您的应用带来更多的灵活性和竞争优势。
文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁
希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻
如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞