👉博主介绍: 博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家,WEB架构师,阿里云专家博主,华为云云享专家,51CTO TOP红人
Java知识图谱点击链接:体系化学习Java(Java面试专题)
💕💕 感兴趣的同学可以收藏关注下 ,不然下次找不到哟💕💕
✊✊ 感觉对你有帮助的朋友,可以给博主一个三连,非常感谢 🙏🙏🙏
文章目录
写在前面
🍒🍒🍒 实际项目中我们常有拦截器的需求,例如:项目中说要针对 /upload 上传的接口,做文件类型校验,看是否符合我们的规范。对于这个要求,我们不能每个上传接口的业务逻辑那里判断吧,这样是不是代码太冗余了。所以拦截器就显得很重要。
1、什么是拦截器
拦截器是一种在请求处理过程中进行拦截和处理的组件。它可以在请求到达目标处理器之前或之后执行一些额外的逻辑。拦截器可以用于实现各种功能,例如身份验证、权限验证、日志记录等。在Spring框架中,拦截器通常用于拦截和处理Web请求。当一个请求到达时,拦截器可以在请求被处理之前或之后进行一些操作,例如验证请求参数、记录请求日志等。通过使用拦截器,我们可以在不修改目标处理器代码的情况下,对请求进行统一的处理和控制。
2、Spring Boot 拦截器有多少种写法呢?
在Spring Boot中,可以使用多种拦截器来拦截和处理请求。以下是一些常用的拦截器:
-
🍒 HandlerInterceptor:这是Spring MVC框架中最常用的拦截器。它可以在请求处理之前和之后进行拦截,并提供了多个方法来处理拦截逻辑。
-
🍒 Filter:这是Servlet规范中定义的过滤器。它可以在请求进入Servlet容器之前进行拦截,并提供了一系列方法来处理拦截逻辑。
-
🍒 WebMvcConfigurer:这是Spring Boot提供的一个接口,可以用于配置Spring MVC的行为。通过实现该接口,可以自定义拦截器并将其添加到Spring MVC的拦截器链中。
-
🍒 HandlerMethodArgumentResolver:这是Spring MVC框架中的一个接口,用于解析请求中的方法参数。通过实现该接口,可以自定义参数解析逻辑,并在请求处理之前进行拦截。
-
🍒 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)是一种在软件系统中常用的组件,用于拦截和处理请求和响应。它可以在请求到达目标之前进行预处理,也可以在响应返回客户端之前进行后处理。拦截器的使用可以带来一些优点和劣势,下面是一些常见的利弊:
利益:
- 🍒 代码重用性:拦截器可以被多个请求共享,可以在多个请求中复用相同的处理逻辑,减少代码冗余。
- 🍒 业务解耦:拦截器可以将与业务逻辑无关的功能(如日志记录、权限验证等)与业务逻辑分离,提高代码的可维护性和可测试性。
- 🍒 统一处理:拦截器可以集中处理一些通用的功能,如请求参数校验、异常处理等,提高代码的一致性和可靠性。
- 🍒 灵活性:拦截器可以根据需要进行配置和调整,可以根据具体的业务场景进行灵活的处理。
劣势:
- 🍒 性能影响:拦截器会增加请求处理的时间和资源消耗,特别是当拦截器链较长或者拦截器中包含复杂的逻辑时,可能会对系统的性能产生一定的影响。
- 🍒 可能引入错误:拦截器的逻辑可能存在错误或者不完善的地方,如果不正确地使用或者处理,可能会引入潜在的问题和错误。
- 🍒 可能导致复杂性增加:如果拦截器的使用不当,可能会导致系统的复杂性增加,增加代码的理解和维护难度。
总之拦截器在软件系统中具有一些优点和劣势,使用时需要根据具体的业务需求和性能要求进行权衡和选择。正确地使用和配置拦截器可以提高代码的可维护性和可扩展性,但如果使用不当或者过度使用拦截器,可能会导致性能问题和系统复杂性的增加。
💕💕 本文由激流原创,原创不易,感谢支持
💕💕喜欢的话记得点赞收藏啊