• 【SpringMVC】处理器拦截器


    拦截器

    拦截器是Aop思想的体现。

    使用拦截器

    1.导包

    <dependencies>
            <dependency>
                <groupId>junitgroupId>
                <artifactId>junitartifactId>
                <version>4.13.2version>
                <scope>testscope>
            dependency>
            <dependency>
                <groupId>org.springframeworkgroupId>
                <artifactId>spring-webmvcartifactId>
                <version>5.3.1version>
            dependency>
            <dependency>
                <groupId>javax.servletgroupId>
                <artifactId>servlet-apiartifactId>
                <version>2.5version>
            dependency>
            <dependency>
                <groupId>javax.servlet.jspgroupId>
                <artifactId>jsp-apiartifactId>
                <version>2.2version>
            dependency>
            <dependency>
                <groupId>javax.servlet.jsp.jstlgroupId>
                <artifactId>jstl-apiartifactId>
                <version>1.2version>
            dependency>
            <dependency>
                <groupId>com.alibabagroupId>
                <artifactId>fastjsonartifactId>
                <version>2.0.7version>
            dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.coregroupId>
                <artifactId>jackson-databindartifactId>
                <version>2.11.3version>
            dependency>
        dependencies>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.处理器层

    @RestController
    public class TestController {
        @GetMapping("/t1")
        public String test(){
            System.out.println("TestController执行成功!");
            return "ok";
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在没有配置拦截器的情况下,ok正常显示:
    在这里插入图片描述

    3.配置拦截器

    自定义一个拦截器非常简单,只需要实现 HandlerInterceptor 这个接口即可,该接口有三个可以实现的方法,如下:

    preHandle() 方法:该方法会在controller层的方法前执行。当其返回值为true时,表示继续向下执行;当其返回值为 false 时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行
    等 )

    postHandle()方法: 该方法会在controller层的方法调用之后,且解析视图之前执行。

    作用:可以通过此方法对请求域(request)中的模型和视图(modelAndView)作出进一步的修改。

    afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。

    作用:可以通过此方法实现一些资源清理、记录日志信息等工作。

    public class MyInterceptor implements HandlerInterceptor {
        /*
        false:不放行,拦截
        true:放行,不拦截
        * */
        //方法执行前拦截!
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("执行前拦截");
            return false;
        }
        //处理modelAndView
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        }
        //资源清理
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:cotext="http://www.springframework.org/schema/context"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context
            https://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/mvc
            https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    
        <cotext:component-scan base-package="com.kxy"/>
    
        <mvc:default-servlet-handler/>
    
        
        <mvc:interceptors>
            <mvc:interceptor>
                
                <mvc:mapping path="/**"/>
                
                <bean class="com.kxy.config.MyInterceptor"/>
            mvc:interceptor>
        mvc:interceptors>
    
    beans>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    4.测试:拦截成功

    在这里插入图片描述
    此时将不会走处理器下的test方法。因此控制台没有打印执行成功的信息。表明拦截成功。

    总结

    1. 一个拦截器,只有 preHandle 方法返回 true , postHandle 、 afterCompletion 才有可能被执行;
    2. 如果 preHandle 方法返回 false ,则该拦截器的 postHandle 、 afterCompletion 必然不会被执行。
    3. 拦截器不是Filter,却实现了Filter的功能,其原理在于:

    所有的拦截器 (Interceptor) 和处理器 (Handler) 都注册在 HandlerMapping 中。
    Spring MVC 中所有的请求都是由 DispatcherServlet 分发的。
    当请求进入 DispatcherServlet.doDispatch() 时候,首先会得到处理该请求的 Handler (即 Controller 中对应的方法)以及所有拦截该请求的拦截器。拦截器就是在这里被调用开始工作的。
    拦截器的工作流程

    正常流程

    在这里插入图片描述

    中断流程

    如果在preHandle中报错或返回false ,那么接下来的流程就会被中断,但注意被执行过的拦截器的afterCompletion仍然会执行。

    应用场景

    拦截器本质上是面向切面编程(AOP),符合横切关注点的功能都可以放在拦截器中来实现,主要的应用场景包括:

    登录验证,判断用户是否登录。
    权限验证,判断用户是否有权限访问资源,如校验token
    日志记录,记录请求操作日志(用户ip,访问时间等),以便统计请求访问量。
    处理cookie、本地化、国际化、主题等。
    性能监控,监控请求处理时长等。

    拿登录验证作为例子:
    需求分析

    1. 当我们注销了的用户,或是从未登录的用户,是不允许进入首页的。
    2. 当我们登录的用户,可以进入首页。

    思路:当我们的用户发出进入首页的请求时,拦截器中提供判断session域中的属性是否有值来进行拦截,如果有,则放行。如果没有,则拦截。

    @Controller
    public class LoginController {
        @GetMapping("/index")
        public String index(){
            return "index";
        }
        @GetMapping("/login")
        public String login(){
            return "login";
        }
        //验证登录
        @GetMapping("/checkedLogin")
        public String checkedLogin(Model model,User user, HttpServletRequest request, HttpServletResponse response){
            //登录成功,放入session域里
            String username = user.getUsername();
            request.getSession().setAttribute("loginUserInfo",username);
            model.addAttribute("username",username);
            System.out.println("username==>"+username);
            return "index";
        }
        //注销
        @GetMapping("/logout")
        public String logout(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException {
            request.getSession().removeAttribute("loginUserInfo");
            return "login";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    拦截器:

    public class LoginInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
           //session没有值的情况下,拦截进入首页的请求
            HttpSession session = request.getSession();
            if (session.getAttribute("loginUserInfo")==null){
                System.out.println("拦截成功!");
                request.getRequestDispatcher("/index.jsp").forward(request,response);
                return false;
            }
            //否则放行
            return true;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    配置拦截器专门拦截进入首页的请求:

        
        <mvc:interceptors>
            <mvc:interceptor>
                
                <mvc:mapping path="/index"/>
                <bean class="com.kxy.config.LoginInterceptor"/>
            mvc:interceptor>
        mvc:interceptors>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    这样使用拦截器,实现登录验证的功能。

  • 相关阅读:
    循序渐进Docker Compose
    PyTorch深度学习(29)Pytorch code importance content
    【python基础】字典详解:如何定义、修改、遍历字典、字典中嵌套字典、列表等
    2022杭电多校第八场
    00-02VSCode常用插件
    游戏“羊了个羊”火爆天际背后的秘密
    高速电路设计笔记----第一章
    联想y7000p怎么开启高性能模式?
    Spring 源码笔记(二),核心概念的理解
    CC2540和CC2541的区别简单解析
  • 原文地址:https://blog.csdn.net/qq_53635765/article/details/126799434