解锁高级技巧:玩转 Spring MVC 自定义拦截器的神奇世界

简介: 解锁高级技巧:玩转 Spring MVC 自定义拦截器的神奇世界

😀前言

在现代的Web应用开发中,控制请求的流程和管理请求的数据变得至关重要。Spring MVC作为一个强大的框架,为我们提供了许多工具来处理这些挑战。其中,自定义拦截器是一个令人激动的概念,它赋予开发者在请求到达目标方法之前和之后执行自定义逻辑的能力。通过精心设计的拦截器,我们可以轻松地添加身份验证、日志记录、数据处理等功能,从而让我们的应用更加安全、高效和易于维护。

🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的动力😉😉



解锁高级技巧:玩转 Spring MVC 自定义拦截器的神奇世界

🤔什么是拦截器

● 说明

  1. Spring MVC 也可以使用拦截器对请求进行拦截处理,用户可以自定义拦截器来实现特定的功能.
  2. 自定义的拦截器必须实现 HandlerInterceptor 接口

● 自定义拦截器的三个方法

  1. preHandle():这个方法在业务处理器处理请求之前被调用,在该方法中对用户请求request 进行处理。
  2. postHandle():这个方法在目标方法处理完请求后执行
  3. afterCompletion():这个方法在完全处理完请求后被调用,可以在该方法中进行一些资源清理的操作。

😍自定义拦截器执行流程分析图

● 自定义拦截器执行流程说明

  1. 如果 preHandle 方法 返回 false, 则不再执行目标方法, 可以在此指定返回页面
  2. postHandle 在目标方法被执行后执行. 可以在方法中访问到目标方法返回的ModelAndView 对象
  3. 若 preHandle 返回 true, 则 afterCompletion 方法 在渲染视图之后被执行.
  4. 若 preHandle 返回 false, 则 afterCompletion 方法不会被调用
  5. 在配置拦截器时,可以指定该拦截器对哪些请求生效,哪些请求不生效

😁自定义拦截器应用实例

● 应用实例需求

完成一个自定义拦截器,学习一下如何配置拦截器和拦截器的运行流程

创建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中自定义拦截器的核心概念和运作原理。通过详细的代码示例,我们学习了拦截器的三个关键方法:preHandlepostHandleafterCompletion,以及它们在请求流程中的作用。从拦截器的创建、配置到实际应用,我们探讨了多种不同场景下的用法,并通过实例演示了如何拦截请求、进行数据处理、实现条件跳转等功能。

自定义拦截器不仅仅是一种技术手段,更是提升应用质量和开发效率的关键工具。通过合理的拦截器设计,我们可以将横切关注点与核心业务逻辑解耦,使代码更加模块化和可维护。在今天不断演进的Web开发领域,掌握自定义拦截器的知识,将为您的应用带来更多的灵活性和竞争优势。

 

文章到这里就结束了,如果有什么疑问的地方请指出,诸佬们一起来评论区一起讨论😁

希望能和诸佬们一起努力,今后我们一起观看感谢您的阅读🍻

如果帮助到您不妨3连支持一下,创造不易您们的支持是我的动力🤞


目录
相关文章
|
人工智能 Java Serverless
【MCP教程系列】搭建基于 Spring AI 的 SSE 模式 MCP 服务并自定义部署至阿里云百炼
本文详细介绍了如何基于Spring AI搭建支持SSE模式的MCP服务,并成功集成至阿里云百炼大模型平台。通过四个步骤实现从零到Agent的构建,包括项目创建、工具开发、服务测试与部署。文章还提供了具体代码示例和操作截图,帮助读者快速上手。最终,将自定义SSE MCP服务集成到百炼平台,完成智能体应用的创建与测试。适合希望了解SSE实时交互及大模型集成的开发者参考。
11697 60
|
1月前
|
缓存 监控 Java
《深入理解Spring》拦截器(Interceptor)——请求处理的艺术
Spring拦截器是Web开发中实现横切关注点的核心组件,基于AOP思想,可在请求处理前后执行日志记录、身份验证、权限控制等通用逻辑。相比Servlet过滤器,拦截器更贴近Spring容器,能访问Bean和上下文,适用于Controller级精细控制。通过实现`HandlerInterceptor`接口的`preHandle`、`postHandle`和`afterCompletion`方法,可灵活控制请求流程。结合配置类注册并设置路径匹配与执行顺序,实现高效复用与维护。常用于认证鉴权、性能监控、统一异常处理等场景,提升应用安全性与可维护性。
|
1月前
|
前端开发 Java 微服务
《深入理解Spring》:Spring、Spring MVC与Spring Boot的深度解析
Spring Framework是Java生态的基石,提供IoC、AOP等核心功能;Spring MVC基于其构建,实现Web层MVC架构;Spring Boot则通过自动配置和内嵌服务器,极大简化了开发与部署。三者层层演进,Spring Boot并非替代,而是对前者的高效封装与增强,适用于微服务与快速开发,而深入理解Spring Framework有助于更好驾驭整体技术栈。
|
2月前
|
监控 安全 Java
使用 @HealthEndpoint 在 Spring Boot 中实现自定义健康检查
Spring Boot 通过 Actuator 模块提供了强大的健康检查功能,帮助开发者快速了解应用程序的运行状态。默认健康检查可检测数据库连接、依赖服务、资源可用性等,但在实际应用中,业务需求和依赖关系各不相同,因此需要实现自定义健康检查来更精确地监控关键组件。本文介绍了如何使用 @HealthEndpoint 注解及实现 HealthIndicator 接口来扩展 Spring Boot 的健康检查功能,从而提升系统的可观测性与稳定性。
200 0
使用 @HealthEndpoint 在 Spring Boot 中实现自定义健康检查
|
8月前
|
前端开发 Java 测试技术
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
本文介绍了 `@RequestParam` 注解的使用方法及其与 `@PathVariable` 的区别。`@RequestParam` 用于从请求中获取参数值(如 GET 请求的 URL 参数或 POST 请求的表单数据),而 `@PathVariable` 用于从 URL 模板中提取参数。文章通过示例代码详细说明了 `@RequestParam` 的常用属性,如 `required` 和 `defaultValue`,并展示了如何用实体类封装大量表单参数以简化处理流程。最后,结合 Postman 测试工具验证了接口的功能。
460 0
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestParam
|
8月前
|
JSON 前端开发 Java
微服务——SpringBoot使用归纳——Spring Boot中的MVC支持——@RequestBody
`@RequestBody` 是 Spring 框架中的注解,用于将 HTTP 请求体中的 JSON 数据自动映射为 Java 对象。例如,前端通过 POST 请求发送包含 `username` 和 `password` 的 JSON 数据,后端可通过带有 `@RequestBody` 注解的方法参数接收并处理。此注解适用于传递复杂对象的场景,简化了数据解析过程。与表单提交不同,它主要用于接收 JSON 格式的实体数据。
707 0
|
4月前
|
前端开发 Java API
Spring Cloud Gateway Server Web MVC报错“Unsupported transfer encoding: chunked”解决
本文解析了Spring Cloud Gateway中出现“Unsupported transfer encoding: chunked”错误的原因,指出该问题源于Feign依赖的HTTP客户端与服务端的`chunked`传输编码不兼容,并提供了具体的解决方案。通过规范Feign客户端接口的返回类型,可有效避免该异常,提升系统兼容性与稳定性。
316 0
|
4月前
|
SQL Java 数据库连接
Spring、SpringMVC 与 MyBatis 核心知识点解析
我梳理的这些内容,涵盖了 Spring、SpringMVC 和 MyBatis 的核心知识点。 在 Spring 中,我了解到 IOC 是控制反转,把对象控制权交容器;DI 是依赖注入,有三种实现方式。Bean 有五种作用域,单例 bean 的线程安全问题及自动装配方式也清晰了。事务基于数据库和 AOP,有失效场景和七种传播行为。AOP 是面向切面编程,动态代理有 JDK 和 CGLIB 两种。 SpringMVC 的 11 步执行流程我烂熟于心,还有那些常用注解的用法。 MyBatis 里,#{} 和 ${} 的区别很关键,获取主键、处理字段与属性名不匹配的方法也掌握了。多表查询、动态
150 0
|
4月前
|
JSON 前端开发 Java
第05课:Spring Boot中的MVC支持
第05课:Spring Boot中的MVC支持
255 0
|
存储 人工智能 Java
【图文详解】基于Spring AI的旅游大师应用开发、多轮对话、文件持久化、拦截器实现
【图文详解】基于Spring AI的旅游大师应用开发、多轮对话、文件持久化、拦截器实现
764 0