• SpringBoot之拦截器



    前言

    SpringBoot拦截器讲解。


    一、编写拦截器

    1. 编写一个拦截器实现HandlerInterceptor接口

    2. 拦截器注册到容器中(实现WebMvcConfigureraddInterceptors()

    3. 指定拦截规则(注意,如果是拦截所有,静态资源也会被拦截】

    编写一个实现HandlerInterceptor接口的拦截器:

    /**
     * 登录检查
     * 1、配置好拦截器要拦截哪些请求
     * 2、把这些配置放在容器中
     */
    @Slf4j
    public class LoginInterceptor implements HandlerInterceptor {
    
        /**
         * 目标方法执行之前
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
            String requestURI = request.getRequestURI();
            log.info("preHandle拦截的请求路径是{}",requestURI);
    
            //登录检查逻辑
            HttpSession session = request.getSession();
    
            Object loginUser = session.getAttribute("loginUser");
    
            if(loginUser != null){
                //放行
                return true;
            }
    
            //拦截住。未登录。跳转到登录页
            request.setAttribute("msg","请先登录");
    //        re.sendRedirect("/");
            request.getRequestDispatcher("/").forward(request,response);
            return false;
        }
    
        /**
         * 目标方法执行完成以后
         * @param request
         * @param response
         * @param handler
         * @param modelAndView
         * @throws Exception
         */
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
            log.info("postHandle执行{}",modelAndView);
        }
    
        /**
         * 页面渲染以后
         * @param request
         * @param response
         * @param handler
         * @param ex
         * @throws Exception
         */
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
            log.info("afterCompletion执行异常{}",ex);
        }
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    拦截器注册到容器中 ,指定拦截规则:

    /**
     * 1、编写一个拦截器实现HandlerInterceptor接口
     * 2、拦截器注册到容器中(实现WebMvcConfigurer的addInterceptors)
     * 3、指定拦截规则【如果是拦截所有,静态资源也会被拦截】
     */
    @Configuration
    public class AdminWebConfig implements WebMvcConfigurer{
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor())//拦截器注册到容器中
                    .addPathPatterns("/**")  //所有请求都被拦截包括静态资源
                    .excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**",
                            "/js/**","/aa/**"); //放行的请求
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    二、拦截器的执行时机和原理

    1. 根据当前请求,找到HandlerExecutionChain(可以处理请求的handler以及handler的所有 拦截器)
    2. 先来顺序执行 所有拦截器的 preHandle()方法。
      • 如果当前拦截器preHandle()返回为true。则执行下一个拦截器的preHandle()
      • 如果当前拦截器返回为false。直接倒序执行所有已经执行了的拦截器的 afterCompletion();
    3. 如果任何一个拦截器返回false,直接跳出不执行目标方法。
    4. 所有拦截器都返回true,才执行目标方法。
    5. 倒序执行所有拦截器的postHandle()方法。
    6. 前面的步骤有任何异常都会直接倒序触发 afterCompletion()
    7. 页面成功渲染完成以后,也会倒序触发 afterCompletion()

    拦截器我在SpringMVC中讲解过一些:SpringMVC之拦截器
    在这里插入图片描述
    DispatcherServlet中涉及到HandlerInterceptor的地方:

    public class DispatcherServlet extends FrameworkServlet {
        
        ...
        
    	protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		HttpServletRequest processedRequest = request;
    		HandlerExecutionChain mappedHandler = null;
    		boolean multipartRequestParsed = false;
    
    		WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);
    
    		try {
    			ModelAndView mv = null;
    			Exception dispatchException = null;
    
                	...
                
                    //该方法内调用HandlerInterceptor的preHandle()
    				if (!mappedHandler.applyPreHandle(processedRequest, response)) {
    					return;
    				}
    
    				// Actually invoke the handler.
    				mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
    
                	...
                    //该方法内调用HandlerInterceptor的postHandle()
    				mappedHandler.applyPostHandle(processedRequest, response, mv);
    			}			
            	processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
    		}
    		catch (Exception ex) {
                //该方法内调用HandlerInterceptor接口的afterCompletion方法
    			triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
    		}
    		catch (Throwable err) {
                //该方法内调用HandlerInterceptor接口的afterCompletion方法
    			triggerAfterCompletion(processedRequest, response, mappedHandler,
    					new NestedServletException("Handler processing failed", err));
    		}
    		finally {
    			...
    		}
    	}
    
    	private void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response,
    			@Nullable HandlerExecutionChain mappedHandler, Exception ex) throws Exception {
    
    		if (mappedHandler != null) {
                //该方法内调用HandlerInterceptor接口的afterCompletion方法
    			mappedHandler.triggerAfterCompletion(request, response, ex);
    		}
    		throw ex;
    	}
    
    	private void processDispatchResult(HttpServletRequest request, HttpServletResponse response,
    			@Nullable HandlerExecutionChain mappedHandler, @Nullable ModelAndView mv,
    			@Nullable Exception exception) throws Exception {
    
            ...
    
    		if (mappedHandler != null) {
                //该方法内调用HandlerInterceptor接口的afterCompletion方法
    			// Exception (if any) is already handled..
    			mappedHandler.triggerAfterCompletion(request, response, null);
    		}
    	}
    
    
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    public class HandlerExecutionChain {
        
        ...
        
    	boolean applyPreHandle(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		for (int i = 0; i < this.interceptorList.size(); i++) {
    			HandlerInterceptor interceptor = this.interceptorList.get(i);
                //HandlerInterceptor的preHandle方法
    			if (!interceptor.preHandle(request, response, this.handler)) {
                    
    				triggerAfterCompletion(request, response, null);
    				return false;
    			}
    			this.interceptorIndex = i;
    		}
    		return true;
    	}
        
       	void applyPostHandle(HttpServletRequest request, HttpServletResponse response, @Nullable ModelAndView mv)
    			throws Exception {
    
    		for (int i = this.interceptorList.size() - 1; i >= 0; i--) {
    			HandlerInterceptor interceptor = this.interceptorList.get(i);
                
                //HandlerInterceptor接口的postHandle方法
    			interceptor.postHandle(request, response, this.handler, mv);
    		}
    	}
        
        void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
    		for (int i = this.interceptorIndex; i >= 0; i--) {
    			HandlerInterceptor interceptor = this.interceptorList.get(i);
    			try {
                    //HandlerInterceptor接口的afterCompletion方法
    				interceptor.afterCompletion(request, response, this.handler, ex);
    			}
    			catch (Throwable ex2) {
    				logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
    			}
    		}
    	}
        
        
    } 
        
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45

    总结

    以上就是拦截器的讲解。

  • 相关阅读:
    神经网络和深度学习-反向传播back propagation代码
    大数据安全 测试
    工程管理系统简介 工程管理系统源码 java工程管理系统 工程管理系统功能设计
    拙见--springMVC的controller接受的请求参数
    Python 序列
    【Unity】U3D ARPG游戏制作实例(一)EasyTouch5完整示例
    重庆自考2022报名注意事项
    python动态规划算法实例详解
    软件设计与体系结构简答题汇总
    unity使用vs进行c#代码提示,查看F12unity元代码
  • 原文地址:https://blog.csdn.net/weixin_62951900/article/details/133324140