SpringBoot(08) -- Web开发-- 拦截器

SpringBoot2学习笔记

源码地址

四、Web开发

4.7)拦截器

4.7.1)HandlerInterceptor 接口

HandlerInterceptor.java的源码如下:

public interface HandlerInterceptor {
    // 目标方法执行之前进行拦截
    default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        return true;
    }
​
    // 目标方法执行完成以后进行拦截
    default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }
    // 页面渲染以后进行拦截
    default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }
}

在工程SpringBootDemo4Admin中,新建 LoginInterceptor.java,代码如下:

package com.study.admin.interceptor;
​
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
​
/**
 * 拦截器
 * 登录检查
 * 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", "请先登录");
        // 转发至登录页
        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);
    }
}

4.7.2)配置拦截器

新建 AdminWebConfig.java,代码如下:

/**
 * 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/**");
​
    }
}

测试:浏览器访问:http://localhost:8080/main.html,页面如下:

 控制台输出:

2022-06-07 20:15:41.569  INFO 22852 --- [nio-8080-exec-3] c.s.admin.interceptor.LoginInterceptor   : preHandle拦截的请求路径是/main.html

输入用户和密码,点击登录后,页面重定向至主页,控制台输出:

2022-06-07 20:20:54.747  INFO 22852 --- [nio-8080-exec-7] c.s.admin.interceptor.LoginInterceptor   : preHandle拦截的请求路径是/main.html
2022-06-07 20:20:54.748  INFO 22852 --- [nio-8080-exec-7] c.s.admin.controller.IndexController     : 当前方法是:mainPage
2022-06-07 20:20:54.748  INFO 22852 --- [nio-8080-exec-7] c.s.admin.interceptor.LoginInterceptor   : postHandle执行ModelAndView [view="main"; model={}]
2022-06-07 20:20:54.858  INFO 22852 --- [nio-8080-exec-7] c.s.admin.interceptor.LoginInterceptor   : afterCompletion执行异常{}

4.7.3)拦截器原理

  1. 根据当前请求,找到HandlerExecutionChain【可以处理请求的handler以及handler的所有拦截器】源码如下图:

 先来顺序执行所有拦截器的 preHandle方法:

    • 如果当前拦截器prehandler返回为true。则执行下一个拦截器的preHandle;

    • 如果当前拦截器返回为false,直接 倒序执行所有已经执行了的拦截器的 afterCompletion;

  1. 如果任何一个拦截器返回false,直接跳出不执行目标方法

  2. 所有拦截器都返回True。执行目标方法

  3. 倒序执行所有拦截器的postHandle方法

  4. 前面的步骤有任何异常都会直接倒序触发 afterCompletion

  5. 页面成功渲染完成以后,也会倒序触发 afterCompletion

拦截器的执行流程如下图:

猜你喜欢

转载自blog.csdn.net/jianghao233/article/details/125172802