美文网首页
玩转 SpringBoot 2 快速整合拦截器

玩转 SpringBoot 2 快速整合拦截器

作者: 桌前明月 | 来源:发表于2019-10-04 08:54 被阅读0次

    概述

    首先声明一下,这里所说的拦截器是 SpringMVC 的拦截器 HandlerInterceptor。使用SpringMVC 拦截器需要做如下操作:

    1. 创建拦截器类需要实现 HandlerInterceptor
    2. 在 xml 配置文件中配置该拦截器,具体配置代码如下:
    <mvc:interceptors>
        <mvc:interceptor>
        <!-- /test/** 这个是拦截路径以/test开头的所有的URL-->
        <mvc:mapping path="/**"/><!—这个是拦截说有的路径-->
        <!-- 配置拦截器类路径-->
        <bean class="cn.ljk.springmvc.controller.MyInterceptor"></bean>
        <!-- 配置不拦截器URL路径-->
        <mvc:exclude-mapping path="/fore/**"/>
        </mvc:interceptor>
    </mvc:interceptors>
    

    因为在SpringBoot 中没有 xml 文件,所以SpringBoot 为我们提供 Java Config 的方式来配置拦截器。配置方式有2种:

    1. 继承 WebMvcConfigurerAdapter (官方已经不建议使用)
    2. 实现 WebMvcConfigurer

    接下来开始 SpringBoot 整合拦截器操作详细介绍!

    整合拦截器实战操作

    第一步:声明拦截器类

    通过实现 HandlerInterceptor 来完成。具体代码如下:

    public class LoginInterceptor implements HandlerInterceptor{}
    

    第二步:实现 HandlerInterceptor 3 个拦截方法

    • preHandle:Controller逻辑执行之前进行拦截
    • postHandle:Controller逻辑执行完毕但是视图解析器还为进行解析之前进行拦截
    • afterCompletion:Controller逻辑和视图解析器执行完毕进行拦截

    实际开发中 preHandle使用频率比较高,postHandle 和 afterCompletion操作相对比较少。

    在下面的代码中 preHandle 方法中定义拦截所有访问项目 URL并进行日志信息记录。postHandle 中在视图解析前进行拦截,通过 Model 在次添加数据Request域中。

    afterCompletion 暂时没有想到使用场景,如果有使用过的场景可以在下面评论区中进行评论。

    拦截器详细代码如下:

    public class LoginInterceptor implements HandlerInterceptor{
        
        private Logger log = LoggerFactory.getLogger(LoginInterceptor.class);
        
        //ControllerController逻辑执行之前
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            log.info("preHandle....");
            String uri = request.getRequestURI();
            log.info("uri:"+ uri);
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
                log.info("拦截 Controller:"+ handlerMethod.getBean().getClass().getName());
                log.info("拦截方法:"+handlerMethod.getMethod().getName());
            }
            
            return true;
        }
        
        //Controller逻辑执行完毕但是视图解析器还为进行解析之前
        @Override
        public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
            log.info("postHandle....");
            Map<String,Object>map=modelAndView.getModel();
            map.put("msg","postHandle add msg");
        }
        
        //Controller逻辑和视图解析器执行完毕
        @Override
        public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
            log.info("afterCompletion....");
        }
    }
    

    第三步:Java Config 的方式来配置拦截器

    继承 WebMvcConfigurerAdapter 方式

    通过继承 WebMvcConfigurerAdapter并重写 addInterceptors方法,通过其参数 InterceptorRegistry将拦截器注入到 Spring的上下文中。

    另外拦截路径和不拦截的路径通过InterceptorRegistry 的 addPathPatterns和 excludePathPatterns方法进行设置。

    这种方式官方已经不建议使用,因为官方已将 WebMvcConfigurerAdapter 标记为@Deprecated 了。

    @Deprecated
    public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer {
    

    继承 WebMvcConfigurerAdapter 方式具体代码如下:

    @Configuration
        public class InterceptorConfigByExtendsWebMvcConfigurerAdapter extends  WebMvcConfigurerAdapter{
    
        @Bean
            public LoginInterceptor loginInterceptor(){
                    return new LoginInterceptor();
            }
    
            public void addInterceptors(InterceptorRegistry registry) {
                    registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/*.html");
            }
    }
    

    实现 WebMvcConfigurer 方式

    通过实现 WebMvcConfigurer 接口并实现 addInterceptors方法,其他操作和继承 WebMvcConfigurerAdapter方式一样。具体代码如下:

    ```java
    @Configuration
    public class InterceptorConfigByImplWebMvcConfigurer implements WebMvcConfigurer{
        
        @Bean
        public LoginInterceptor loginInterceptor(){
            return new LoginInterceptor();
        }
         @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/*.html");
        }
    }
    ```
    

    测试

    编写普通Controller,具体代码如下:

    @Controller
    public class IndexController {
        
        @GetMapping("/index")
        public String index(ModelAndView modelAndView){
            
            return "index";
        }
    }
    

    在 src/main/resource 下的 templates目录下创建 IndexController访问页面 index.ftl, 代码如下:

    <h1>${msg}</h1>
    

    由于我这里使用的是 Freemarker当页面使用,说以需要引入 Freemarker starter依赖,具体点如下:

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
    

    通过游览器访问 localhost:8080/sbe/index,具体访问效果如下:

    在这里插入图片描述

    如上图所示在视图解析前通过 Model在次添加数据到 Request域中的msg 成功显示出来了!

    日志输出信息如下:拦截地址和拦截Controller 和具体方法进行日志输出

    2019-09-24 15:53:04.144  INFO 7732 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/sbe]    : Initializing Spring DispatcherServlet 'dispatcherServlet'
    2019-09-24 15:53:04.145  INFO 7732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
    2019-09-24 15:53:04.153  INFO 7732 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 8 ms
    2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : preHandle....
    2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : uri:/sbe/index
    2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : 拦截 Controller:cn.lijunkui.controller.IndexController
    2019-09-24 15:53:04.155  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : 拦截方法:index
    2019-09-24 15:53:04.156  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : postHandle....
    2019-09-24 15:53:04.161  INFO 7732 --- [nio-8080-exec-1] c.lijunkui.interceptor.LoginInterceptor  : afterCompletion....
    

    小结

    SpringBoot 2 整合拦截器和整合 Filter的操作很像,都是通过一个注册类将其注入到Spring的上下文中,只不过Filter使用的是 FilterRegistrationBean 而 拦截器使用的是 InterceptorRegistry。

    个人觉得比使用 xml 配置的方式更为简单了,如果你还没有在 SpringBoot 项目中使用过拦截器,赶快来操作一下吧!

    代码示例

    具体代码示例请在我的GitHub 仓库 springbootexamples 中模块名为 spring-boot-2.x-interceptor 项目中进行查看

    GitHub:https://github.com/zhuoqianmingyue/springbootexamples

    相关文章

      网友评论

          本文标题:玩转 SpringBoot 2 快速整合拦截器

          本文链接:https://www.haomeiwen.com/subject/ozbjpctx.html