【项目实战】十分钟学习完 Spring Boot 拦截器

👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO TOP红人

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

✊✊ 感觉对你有帮助的朋友,可以给博主一个三连,非常感谢 🙏🙏🙏

在这里插入图片描述

写在前面

🍒🍒🍒 实际项目中我们常有拦截器的需求,例如:项目中说要针对 /upload 上传的接口,做文件类型校验,看是否符合我们的规范。对于这个要求,我们不能每个上传接口的业务逻辑那里判断吧,这样是不是代码太冗余了。所以拦截器就显得很重要。

1、什么是拦截器

拦截器是一种在请求处理过程中进行拦截和处理的组件。它可以在请求到达目标处理器之前或之后执行一些额外的逻辑。拦截器可以用于实现各种功能,例如身份验证、权限验证、日志记录等。在Spring框架中,拦截器通常用于拦截和处理Web请求。当一个请求到达时,拦截器可以在请求被处理之前或之后进行一些操作,例如验证请求参数、记录请求日志等。通过使用拦截器,我们可以在不修改目标处理器代码的情况下,对请求进行统一的处理和控制。

2、Spring Boot 拦截器有多少种写法呢?

在Spring Boot中,可以使用多种拦截器来拦截和处理请求。以下是一些常用的拦截器:

  1. 🍒 HandlerInterceptor:这是Spring MVC框架中最常用的拦截器。它可以在请求处理之前和之后进行拦截,并提供了多个方法来处理拦截逻辑。

  2. 🍒 Filter:这是Servlet规范中定义的过滤器。它可以在请求进入Servlet容器之前进行拦截,并提供了一系列方法来处理拦截逻辑。

  3. 🍒 WebMvcConfigurer:这是Spring Boot提供的一个接口,可以用于配置Spring MVC的行为。通过实现该接口,可以自定义拦截器并将其添加到Spring MVC的拦截器链中。

  4. 🍒 HandlerMethodArgumentResolver:这是Spring MVC框架中的一个接口,用于解析请求中的方法参数。通过实现该接口,可以自定义参数解析逻辑,并在请求处理之前进行拦截。

  5. 🍒 HandlerExceptionResolver:这是Spring MVC框架中的一个接口,用于处理异常情况。通过实现该接口,可以自定义异常处理逻辑,并在发生异常时进行拦截。

2.1、HandlerInterceptor

下面是一个HandlerInterceptor的使用示例:

首先,创建一个自定义的拦截器类,实现HandlerInterceptor接口,并重写其中的方法。例如:

package com.pany.camp.filter;

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

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

/**
 * @description: HandlerInterceptor
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:30
 */
public class CustomInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        // 在请求处理之前执行的逻辑
        System.out.println("Pre-handle logic");
        return true; // 返回true表示继续执行请求,返回false表示中断请求
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 请求处理之后,渲染视图之前执行的逻辑
        System.out.println("Post-handle logic");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        // 请求处理完成后执行的逻辑,包括视图渲染完成后
        System.out.println("After-completion logic");
    }
}
package com.pany.camp.filter;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 *
 * @description:  WebMvcConfig
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-07-07 17:32
 */
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomInterceptor()).addPathPatterns("/**"); // 拦截所有请求
    }
}

CustomInterceptor拦截器会在每个请求的不同阶段执行相应的逻辑。preHandle方法在请求处理之前执行,可以用于身份验证、权限验证等操作;postHandle方法在请求处理之后、视图渲染之前执行,可以用于添加一些公共数据到视图中;afterCompletion方法在请求处理完成后执行,可以用于清理资源等操作。

2.2、Filter

下面是一个Spring Boot Filter的使用示例:

首先,创建一个自定义的过滤器类,实现javax.servlet.Filter接口,并重写其中的方法。例如:

package com.pany.camp.filter;

import javax.servlet.*;
import javax.servlet.FilterConfig;
import java.io.IOException;

/**
 * @description:
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:34
 */
public class CustomFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        // 过滤逻辑
        System.out.println("Before request");
        filterChain.doFilter(servletRequest, servletResponse);
        System.out.println("After response");
    }

    @Override
    public void destroy() {
        // 销毁操作
    }
}
package com.pany.camp.filter;

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 *
 * @description:  FilterConfig
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:35
 */
@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<CustomFilter> customFilterRegistrationBean() {
        FilterRegistrationBean<CustomFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new CustomFilter());
        registrationBean.addUrlPatterns("/*"); // 拦截所有请求
        registrationBean.setOrder(1); // 设置过滤器的执行顺序
        return registrationBean;
    }
}

2.3、WebMvcConfigurer

下面是一个使用WebMvcConfigurer的示例:

首先,创建一个实现WebMvcConfigurer接口的配置类,例如:

package com.pany.camp.filter;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 *
 * @description:  MvcConfig
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:38
 */
@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.addViewController("/home").setViewName("home");
    }
}

我们重写了WebMvcConfigurer接口的addViewControllers方法,通过ViewControllerRegistry来注册一个简单的视图控制器。在这个示例中,我们将"/login"映射到名为"login"的视图,将"/home"映射到名为"home"的视图。

然后,在Spring Boot的主类中,使用@EnableWebMvc注解来启用WebMvc配置:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

/**
 *
 * @description:  Application 
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:38
 */
@SpringBootApplication
@EnableWebMvc
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

我们使用@SpringBootApplication注解来标识主类,并使用@EnableWebMvc注解来启用WebMvc配置。

通过上述配置,当访问"/login"时,会显示名为"login"的视图;当访问"/home"时,会显示名为"home"的视图。这样可以简化URL与视图之间的映射配置。

2.4、HandlerMethodArgumentResolver

下面是一个使用HandlerMethodArgumentResolver的示例:

首先,创建一个实现HandlerMethodArgumentResolver接口的参数解析器类,例如:

package com.pany.camp.filter;

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

import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

/**
 *
 * @description:  CustomResolver
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-07-07 17:41
 */
@Component
public class CustomResolver implements HandlerMethodArgumentResolver {
    
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.getParameterType().equals(CustomObject.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
        HttpServletResponse response = (HttpServletResponse) webRequest.getNativeResponse();

        // 在这里进行自定义参数解析的逻辑处理
        // 例如,从request中获取参数值,然后构造一个CustomObject对象返回
        return new Object();
    }
}

我们自定义了一个参数解析器CustomResolver,实现了HandlerMethodArgumentResolver接口。在supportsParameter方法中,我们判断参数类型是否为CustomObject,如果是,则返回true表示支持解析该参数类型。在resolveArgument方法中,我们可以根据自己的业务逻辑,从HttpServletRequest中获取参数值,并构造一个CustomObject对象返回。

然后,在Spring Boot的配置类中,注册自定义的参数解析器:

package com.pany.camp.filter;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;

/**
 *
 * @description:
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:44
 */
@Configuration
public class MvcConfig1 implements WebMvcConfigurer {

    private final CustomResolver customResolver;

    public MvcConfig1(CustomResolver customResolver) {
        this.customResolver = customResolver;
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(customResolver);
    }
}

我们通过实现WebMvcConfigurer接口,并重写addArgumentResolvers方法,将自定义的参数解析器CustomResolver添加到参数解析器列表中。

2.5、HandlerExceptionResolver

HandlerExceptionResolver是Spring MVC中的一个接口,用于处理请求处理过程中出现的异常。下面是一个使用HandlerExceptionResolver的示例:

首先,创建一个实现HandlerExceptionResolver接口的异常处理器类,例如:

package com.pany.camp.filter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @description:  CustomExceptionHandler
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:49
 */
@Component
public class CustomExceptionHandler implements HandlerExceptionResolver {

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
                                         Exception ex) {
        // 在这里进行自定义的异常处理逻辑
        // 例如,根据不同的异常类型,返回不同的错误页面或错误信息
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.addObject("errorMessage", ex.getMessage());
        modelAndView.setViewName("error");
        return modelAndView;
    }
}

我们自定义了一个异常处理器CustomExceptionHandler,实现了HandlerExceptionResolver接口。在resolveException方法中,我们可以根据自己的业务逻辑,对不同的异常进行不同的处理。例如,可以根据异常类型返回不同的错误页面或错误信息。

然后,在Spring Boot的配置类中,注册自定义的异常处理器:

package com.pany.camp.filter;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;

/**
 *
 * @description:
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-07-07 17:44
 */
@Configuration
public class MvcConfig1 implements WebMvcConfigurer {

    private final CustomResolver customResolver;

    public MvcConfig1(CustomResolver customResolver) {
        this.customResolver = customResolver;
    }

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(customResolver);
    }
}

我们通过实现WebMvcConfigurer接口,并重写configureHandlerExceptionResolvers方法,将自定义的异常处理器CustomExceptionHandler添加到异常处理器列表中。

3、总结

拦截器(Interceptor)是一种在软件系统中常用的组件,用于拦截和处理请求和响应。它可以在请求到达目标之前进行预处理,也可以在响应返回客户端之前进行后处理。拦截器的使用可以带来一些优点和劣势,下面是一些常见的利弊:

利益:

  1. 🍒 代码重用性:拦截器可以被多个请求共享,可以在多个请求中复用相同的处理逻辑,减少代码冗余。
  2. 🍒 业务解耦:拦截器可以将与业务逻辑无关的功能(如日志记录、权限验证等)与业务逻辑分离,提高代码的可维护性和可测试性。
  3. 🍒 统一处理:拦截器可以集中处理一些通用的功能,如请求参数校验、异常处理等,提高代码的一致性和可靠性。
  4. 🍒 灵活性:拦截器可以根据需要进行配置和调整,可以根据具体的业务场景进行灵活的处理。

劣势:

  1. 🍒 性能影响:拦截器会增加请求处理的时间和资源消耗,特别是当拦截器链较长或者拦截器中包含复杂的逻辑时,可能会对系统的性能产生一定的影响。
  2. 🍒 可能引入错误:拦截器的逻辑可能存在错误或者不完善的地方,如果不正确地使用或者处理,可能会引入潜在的问题和错误。
  3. 🍒 可能导致复杂性增加:如果拦截器的使用不当,可能会导致系统的复杂性增加,增加代码的理解和维护难度。

总之拦截器在软件系统中具有一些优点和劣势,使用时需要根据具体的业务需求和性能要求进行权衡和选择。正确地使用和配置拦截器可以提高代码的可维护性和可扩展性,但如果使用不当或者过度使用拦截器,可能会导致性能问题和系统复杂性的增加。

💕💕 本文由激流原创,原创不易,感谢支持
💕💕喜欢的话记得点赞收藏啊
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

激流丶

感觉小弟写的不错,给点鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值