开发者

SpringBoot项目Web拦截器使用的多种方式

目录
  • 一、实现 HandlerInterceptor 接口
    • 1、创建HandlerInterceptor实现类 MyInterceptor
    • 2、注册拦截器
    • 3、运行测试
  • 二、使用过滤器(Filter)
    • 1、创建过滤器实现类
    • 2、使用@Componenandroidt 注解配置过滤器
    • 3、通过配置类注册过滤器(FilterRegistrationBean)
  • 三、使用OncePerRequestFilter
    • 1. 主要方法
    • 2. 使用 OncePerRequestFilter
      • 2.1 创建自定义过滤器
      • 2.2 注册自定义过滤器
  • 四、其他类似过滤器
    • 1、CharacterEncodingFilter
      • 2、HiddenHttpMethodFilter
        • 3、CorsFilter

        在Spring Boot应用中,Web拦截器(Interceptor)是一种用于在请求处理的不同阶段执行自定义逻辑的机制。拦截器广泛应用于各种场景,以增强应用的功能性、安全性和可维护性。

        在Spring Boot项目中实现Wen拦截器主要有以下几种方式

        • 实现 HandlerInterceptor 接口
        • 使用过滤器(Filter
        • 使用 @ASPect 注解实现AOP拦截

        这里主要介绍 HandlerInterceptor 接口 和 Filter

        一、实现 HandlerInterceptor 接口

        这是最常见和直接的方式。需要创建一个类实现 org.springframework.web.servlet.HandlerInterceptor 接口,并重写其中的方法:

        1、创建HandlerInterceptor实现类 MyInterceptor

        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.stereotype.Component;
        import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
        @Slf4j
        @Component
        public class MyInterceptor implements HandlerInterceptor {
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
                log.info("preHandle");
                return HandlerInterceptor.super.preHandle(request, response, handler);
            }
            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
                log.info("postHandle");
                HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
            }
            @Override
            public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
                log.info("afterCompletion");
                HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
            }
        }

        2、注册拦截器

        实现完拦截器后,需要将其注册到Spring MVC的配置中。可以通过继承 WebMvcConfigurer 接口并重写 addInterceptors 方法来完成:

        import jakarta.annotation.Resource;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
        @Configuration
        public class WebConfig implements WebMvcConfigurer {
            @Resource
            private MyInterceptor myInterceptor;
            @Override
            public void addInterceptors(InterceptorRegistry registry) {
                registry.addInterceptor(myInterceptor)
                        .addPathPatterns("/**")//拦截所有请求
                        .excludePathPatterns("/login");// 放行登录请求
            }
        }

        这里的myInterceptor 也可以直接new MyInterceptor()

        3、运行测试

        MyInterceptor         : preHandle
        MyInterceptor         : postHandle
        MyInterceptor         : afterCompletion

        二、使用过滤器(Filter)

        虽然过滤器不属于拦截器的范畴,但在Spring Boot中,过滤器也是常用的请求处理组件。可以通过实现 Javax.servlet.Filter 接口来创建自定义过滤器:

        1、创建过滤器实现类

        这里我创建了3个测试过滤器,分别是 MyFilterMyFilter2MyFilter2,代码都是相同的,只是打印内容不一样

        @Slf4j
        public class MyFilter implements Filter {
            @Override
            public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
                // 请求前处理
                log.info("MyFilter doFilter pre");
                filterChain.doFilter(servletRequest, servletResponse);
                // 响应后处理
                log.info("MyFilter doFilter after");
            }
        }

        2、使用@Component 注解配置过滤器

        通过将过滤器类声明为Spring组件,Spring Boot会自动检测并注册它。

        import org.springframework.stereotype.Component;
        @Component
        public class MyFilter implements Filter {
            // 实现方法同上
        }

        注意:默认情况下,js使用@Component注册的过滤器会被添加到过滤链中,但顺序可能不确定。如果需要指定顺序,建议使用其他注册方式。

        3、通过配置类注册过滤器(FilterRegistrationBean)

        通过FilterRegistrationBean可以更灵活地注册过滤器,包括设置过滤器的顺序、URL模式等。

        • 可以精确控制过滤器的顺序。
        • 可以指定过滤器应IFoGHaCpu用的URL模式。
        import org.springframework.boot.web.servlet.FilterRegistrationBean;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        @Configuration
        public class FilterConfig {
            @Bean
            public FilterRegistrationBean<MyFilter> myFilter() {
                FilterRegistrationBean<MyFilter> bean = new FilterRegistrationBean<>();
                bean.setFilter(new MyFilter());
                bean.addUrlPatterns("/*"); // 拦截所有请求
                bean.setOrder(1); // 设置过滤器顺序,数值越小优先级越高
                return bean;
            }
            @Bean
            public FilterRegistrationBean<MyFilter2> myFilter2() {
                FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>();
                bean.setFilter(new MyFilter2());
                bean.addUrlPatterns("/*");
                bean.setOrder(2);
                return bean;
            }
            @Bean
            public FilterRegistrationBean<MyFilter3> MyFilter3() {
                FilterRegistrationBean<MyFilter3> bean = new FilterRegistrationBean<>();
                bean.setFilter(new MyFilter3());
                bean.addUrlPatterns("/*");
                bean.setOrder(3);
                return bean;
            }
        }

        运行测试

        通过日志可以看见,order值越小优先级越高,过滤器的执行遵循先进后出的原则

        c.hj.springboot3.filter.demo2.MyFilter   : MyFilter doFilter pre

        c.hj.springboot3.filter.demo2.MyFilter2  : MyFilter2 doFilter pre

        c.hj.springboot3.filter.demo2.MyFilter3  : MyFilter3 doFilter pre

        c.h.s.filter.service.UserServiceImpl     : 执行业务代码

        c.hj.springboot3.filter.demo2.MyFilter3  : MyFilter3 doFilter after

        c.hj.springboot3.filter.demo2.MyFilter2  : MyFilter2 doFilter after

        c.hj.springboot3.filter.demo2.MyFilter   : MyFilter doFilter after

        三、使用OncePerRequestFilter

        OncePerRequestFilter 是 Spring 框架提供的一个非常有用的过滤器基类,旨在确保某个过滤器在每个 HTTP 请求中只执行一次。这在需要确保某些处理逻辑(如身份验证、日志记录、请求修改等)在整个请求生命周期中不被重复执行时特别有用。

        它的主要功能是确保其 doFilterInternal 方法在每个请求中仅被调用一次。这是通过检查请求属性来实现的,防止在某些情况下(如转发请求)过滤器被多次执行。

        1. 主要方法

        • doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain):这是需要子类实现的方法,在其中编写自定义的过滤逻辑。该方法保证在每个请求中只被调用一次。
        • shouldNotFilter(HttpServletRequest request):可以重写此方法来指定某些请求不需要被过滤。
        • doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain):这是 Filter 接口的方法,OncePerRequestFilter 已经实现了该方法,确保 doFilterInternal 只执行一次。

        2. 使用 OncePerRequestFilter

        2.1 创建自定义过滤器

        要使用 OncePerRequestFilter,通常需要创建一个继承自它的子类,并实现 doFilterInternal 方法。

        示例代码:

        import javax.servlet.FilterChain;
        import javax.servlet.ServletException;
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        import org.springframework.web.filter.OncePerRequestFilter;
        import java.io.IOException;
        public class CustomOncePerRequestFilter extends OncePerRequestFilter {
            @Override
            protected void doFilterInternal(HttpServletRequest request, 
                                            HttpServletResponse response, 
                                            FilterChain filterChain)
                    throws ServletException, IOException {
                // 请求预处理逻辑
                System.out.println("CustomOncePerRequestFilter: 请求前处理");
                // 继续过滤器链
                filterChain.doFilter(request, response);
                // 响应后处理逻辑
                System.out.println("CustomOncePerRequestFilter: 响应后处理");
            }
        }

        2.2 注册自定义过滤器

        创建完自定义过滤器后,需要将其注册到 Spring Boot 应用中。可以使用 FilterRegistrationBean 进行注册。

        示例代码:

        import org.springframework.boot.web.servlet.FilterRegistrationBean;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        @Configuration
        public class FilterConfig {
            @Bean
            public FilterRegistrationBean<CustomOncePerRequestFilter> customFilterRegistration() {
                FilterRegistrationBean<CustomOncePerRequestFilter> registration = new FilterRegistrationBean<>();
                registration.setFilter(new CustomOncePerRequestFilter());
                registration.addUrlPatterns("/*"); // 拦截所有请求
                registration.setName("customOncePerRequestFilter");
                registration.setOrder(1); // 设置过滤器顺序
                return registration;
            }
        }

        四、其他类似过滤器

        1、CharacterEncodingFilter

        简介CharacterEncodingFilter 用于设置请求和响应的字符编码,确保请求参数和响应内容的编码一致,防止乱码问题。

        使用场景:在处理国际化应用或需要特定字符编码的场景下非常有用。

        示例配置

        import org.springframework.boot.web.servlet.FilterRegistrationBean;
        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.web.filter.CharacterEncodingFilter;
        @Configuration
        public class EncodingFilterConfig {
            @Bean
            public FilterRegistrationBean<CharacterEncodingFilter> characterEncodingFilter() {
                CharacterEncodingFilter filter = new CharacterEncodingFilter();
                filter.setEncoding("UTF-8");
                filter.setForceEncoding(true);
                FilterRegistrationBean<CharacterEncodingFilter> registration = new FilterRegistrationBean<>(filter);
                registration.addUrlPatterns("/*");
                registration.setName("characterEncodingFilter");
                registration.setOrder(1);
                return registration;
            }
        }

        2、HiddenHttpMethodFilter

        简介HiddenHttpMethodFilter 用于将带有特殊参数(如 _method)的 POST 请求转换为对应的 HTTP 方法(如 PUT、DELETE)。这在 html 表单不支持某些 HTTP 方法时非常有用。

        使用场景:在使用 RESTful API 且前端仅支持 POST 请求时,通过隐藏字段指定实际的 HTTP 方法。

        启用方式

        在 Spring Boot 中,默认情况下,HiddenHttpMethodFilter 是启用的。如果需要自定义,可以手动注册:

        @Bean
        public HiddenHttpMethodFilter hiddenHttpMethodFilter() {
            return new HiddenHttpMethodFilter();
        }

        3、CorsFilter

        简介CorsFilter 用于处理跨域资源共享(CORS)配置,允许或限制来自不同源的请求。

        使用场景:在构建需要与前端分离的应用,且前端和后端部署在不同域时。

        示例配置

        import org.springframework.context.annotation.Bean;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.web.cors.CorsConfigura编程客栈tion;
        import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
        import org.springframework.web.filter.CorsFilter;
        @Configuration
        public class CorsConfig {
            @Bean
            public CorsFilter corsFilter() {
                UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
                CorsConfiguration config = new CorsConfiguration();
                config.setAllowCredentials(true);
                config.addAllowedOrigin("http://example.com");
                config.addAllowedHeader("*");
                config.addAllowedMethod("*");
                source.registerCorsConfiguration("/**", config);
                return new CorsFilter(source);
            }
        }

        到此这篇关于SpringBoot项目Web拦截器使用的文章就介绍到这了,更多相关SpringBoot Web拦截器内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文www.devze.com章希望大家以后多多支持编程客栈(www.devze.com)!

        0

        上一篇:

        下一篇:

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        最新开发

        开发排行榜