• 【JavaEE进阶】Spring统一功能处理:拦截器的使用


    目录

    1.什么是拦截器?

    2.拦截器的使用

    2.1定义拦截器

    2.2 注册配置拦截器

    3.拦截器详解

    3.1 拦截路径

    3.2 拦截器的执行流程

    4. 使用拦截器实现登录校验

    4.1 定义拦截器

    4.2 注册配置拦截器


    1.什么是拦截器?

    拦截器是Spring框架提供的核心功能之⼀, 主要用来拦截用户的请求, 在指定⽅法前后, 根据业务需要执行预先设定的代码.

            也就是说, 允许开发人员提前预定义一些逻辑, 在用户的请求响应前后执行. 也可以在用户请求前阻止其执行.
            在拦截器当中,开发人员可以在应用程序中做一些通用性的操作, 比如通过拦截器来拦截前端发来的请求, 判断Session中是否有登录用户的信息. 如果有就可以放行, 如果没有就进行拦截.

    比如我们去银行办理业务,在办理业务前后, 就可以加一些拦截操作
    办理业务之前, 先取号, 如果带身份证了就取号成功
    业务办理结束, 给业务办理人员的服务进行评价.
    这些就是"拦截器"做的工作.

    2.拦截器的使用

    拦截器的使用步骤分为两步:

    1.定义拦截器

    2.注册配置拦截器

    2.1定义拦截器

    定义拦截器: 实现 HandlerInterceptor 接口, 并重写其所有方法

    1. import jakarta.servlet.http.HttpServletRequest;
    2. import jakarta.servlet.http.HttpServletResponse;
    3. import lombok.extern.slf4j.Slf4j;
    4. import org.springframework.web.servlet.HandlerInterceptor;
    5. import org.springframework.web.servlet.ModelAndView;
    6. @Slf4j
    7. public class LoginInterceptorTest implements HandlerInterceptor {
    8. @Override
    9. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    10. log.info("LoginInterceptor ⽬标⽅法执⾏前执⾏..");
    11. return true;
    12. }
    13. @Override
    14. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    15. log.info("LoginInterceptor ⽬标⽅法执⾏后执⾏");
    16. }
    17. @Override
    18. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    19. log.info("LoginInterceptor 视图渲染完毕后执⾏,最后执⾏");
    20. }
    21. }

    preHandle 中返回 true 和返回 false 的区别:

    preHandle方法的返回值会影响目标方法的执行流程: 

    • 返回true:表示继续执行目标方法。如果preHandle方法返回true,则目标方法会继执行,整个请求处理流程会继续进行。

    • 返回false:表示中断目标方法的执行。如果preHandle方法返回false,则目标方法不会被执行,整个请求处理流程会被中断,后续的处理器方法和拦截器方法不会被执行。

    总结

    preHandle() 方法: 目标方法执行前执行. 返回true: 继续执行后续操作; 返回false: 中断后续操作.
    postHandle() 方法: 目标方法执行后执行
    afterCompletion() 方法: 视图渲染完毕后执行,最后执行(后端开发现在几乎不涉及视图,暂不了解)

    2.2 注册配置拦截器

     注册配置拦截器: 实现WebMvcConfigurer接口, 并重写addInterceptors方法

    1. @Configuration
    2. public class WebConfigTest implements WebMvcConfigurer {
    3. //自定义的拦截器对象
    4. @Autowired
    5. private LoginInterceptorTest loginInterceptorTest;
    6. @Override
    7. public void addInterceptors(InterceptorRegistry registry) {
    8. //注册自定义的拦截器对象
    9. registry.addInterceptor(loginInterceptorTest)
    10. .addPathPatterns("/**"); //设置拦截器的请求路径, (/**表示拦截所有请求)
    11. }
    12. }

     在图书管理系统中引入上述拦截器的代码

    在图书管理系统中点击登录按钮: 

    此时拦截器代码的日志记录如下:

    可以看到 preHandle 方法执行之后就放行了, 开始执行目标方法, 目标方法执行完成之后执行
    postHandleafterCompletion 方法.

    我们把拦截器中 preHandle 方法的返回值改为 false, 再观察运行结果

     可以看到, 拦截器拦截了请求, 没有进行响应.

    3.拦截器详解

    拦截器的入门程序完成之后,接下来我们来介绍拦截器的使用细节。拦截器的使用细节我们主要介绍两个部分:

    1.拦截器的拦截路径配置
    2.拦截器实现原理
     

    3.1 拦截路径

    拦截路径是指我们定义的这个拦截器, 对哪些请求生效. 

    我们在注册配置拦截器的时候,通过 addPathPatterns() 方法指定要拦截哪些请求. 也可以通过excludePathPatterns() 指定不拦截哪些请求.

    上述代码中,我们配置的是 / ** ,表示拦截所有的请求.

    比如用户登录校验,我们希望可以对除了登录之外所有的路径生效.

    1. @Configuration
    2. public class WebConfig implements WebMvcConfigurer {
    3. @Autowired
    4. private LoginInterceptor loginInterceptor;
    5. @Override
    6. public void addInterceptors(InterceptorRegistry registry) {
    7. registry.addInterceptor(loginInterceptor)
    8. .addPathPatterns("/**")
    9. .excludePathPatterns("/user/login") //排除掉不需要拦截的路径
    10. .excludePathPatterns("/css/**") //排除掉不需要拦截的路径
    11. .excludePathPatterns("/js/**") //排除掉不需要拦截的路径
    12. .excludePathPatterns("/pic/**") //排除掉不需要拦截的路径
    13. .excludePathPatterns("/**/*.html") //排除掉不需要拦截的路径
    14. ;
    15. }
    16. }

    在拦截器中除了可以设置 / ** 拦截所有资源外,还有一些常见拦截路径设置:

     以上拦截规则可以拦截此项目中的使用URL, 包括静态文件(图片文件, JS和CSS等文件).

    3.2 拦截器的执行流程

    正常的调用顺序:

                           

    有了拦截器之后,会在调用 Controller 之前进行相应的业务处理,执行的流程如下图                                            

    1.添加拦截器后,执行 Controller 的方法之前, 请求会先被拦截器拦截住. 执行 preHandle() 方法,
    这个方法需要返回一个布尔类型的值. 如果返回 true, 就表示放行本次操作, 继续访问 Controller 中的方法. 如果返回 false , 则不会放行 (Controller 中的方法也不会执行).

    2. Controller 当中的方法执行完毕后,再回过来执行 postHandle() 这个方法以及afterCompletion() 方法,执行完毕之后,最终给浏览器响应数据.

    4. 使用拦截器实现登录校验

    学习拦截器的基本操作之后,接下来我们需要完成最后一步操作: 通过拦截器来完成图书管理系统中的登录校验功能

    4.1 定义拦截器

    session 中获取用户信息,如果 session 中不存在, 则返回 false, 并设置 http 状态码为 401, 否则返回 true.

    1. import com.example.com.constant.Constants;
    2. import com.example.com.model.UserInfo;
    3. import jakarta.servlet.http.HttpServletRequest;
    4. import jakarta.servlet.http.HttpServletResponse;
    5. import jakarta.servlet.http.HttpSession;
    6. import lombok.extern.slf4j.Slf4j;
    7. import org.springframework.stereotype.Component;
    8. import org.springframework.web.servlet.HandlerInterceptor;
    9. @Slf4j
    10. @Component
    11. public class LoginInterceptor implements HandlerInterceptor {
    12. /**
    13. * 请求处理前执行的逻辑
    14. * true : 表示放行, 不进行拦截
    15. * false: 表示拦截, 不进行下一步处理
    16. */
    17. @Override
    18. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    19. log.info("LoginInterceptor priHandle.....");
    20. //获取session 并且判断session中存储的userInfo信息是否为空
    21. HttpSession session = request.getSession();
    22. // getSession(true): session存在就返回, 不存在就创建一个新的session返回 默认是true
    23. // getSession(false): session存在就返回, 不存在就返回空
    24. UserInfo userInfo = (UserInfo) session.getAttribute(Constants.USER_SESSION_KEY);
    25. if(userInfo == null || userInfo.getId() <= 0) {
    26. //用户未登录
    27. response.setStatus(401);
    28. return false;
    29. }
    30. return true;
    31. }
    32. }

    4.2 注册配置拦截器

    1. import com.example.com.interceptor.LoginInterceptor;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    6. @Configuration
    7. public class WebConfig implements WebMvcConfigurer {
    8. @Autowired
    9. private LoginInterceptor loginInterceptor;
    10. @Override
    11. public void addInterceptors(InterceptorRegistry registry) {
    12. registry.addInterceptor(loginInterceptor)
    13. .addPathPatterns("/**")
    14. .excludePathPatterns("/user/login") //排除掉不需要拦截的路径
    15. .excludePathPatterns("/css/**") //排除掉不需要拦截的路径
    16. .excludePathPatterns("/js/**") //排除掉不需要拦截的路径
    17. .excludePathPatterns("/pic/**") //排除掉不需要拦截的路径
    18. .excludePathPatterns("/**/*.html") //排除掉不需要拦截的路径
    19. ;
    20. }
    21. }

    也可以改写成:

    1. import com.example.com.interceptor.LoginInterceptor;
    2. import org.springframework.beans.factory.annotation.Autowired;
    3. import org.springframework.context.annotation.Configuration;
    4. import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    5. import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    6. import java.util.Arrays;
    7. import java.util.List;
    8. @Configuration
    9. public class WebConfig implements WebMvcConfigurer {
    10. @Autowired
    11. private LoginInterceptor loginInterceptor;
    12. private List excludePaths = Arrays.asList(
    13. "/user/login",
    14. "/css/**",
    15. "/js/**",
    16. "/pic/**",
    17. "/**/*.html"
    18. );
    19. @Override
    20. public void addInterceptors(InterceptorRegistry registry) {
    21. registry.addInterceptor(loginInterceptor)
    22. .addPathPatterns("/**")
    23. .excludePathPatterns(excludePaths) //排除掉不需要拦截的路径
    24. ;
    25. }
    26. }

    以上代码在项目中的位置:

  • 相关阅读:
    文心一言 VS 讯飞星火 VS chatgpt (92)-- 算法导论8.3 5题
    UE5: UpdateOverlap - 从源码深入探究UE的重叠触发
    Cocos Creator 3.6 新特性详解 3/3:性能篇
    Springboot毕设项目基于HTML5+CSS3的信息化农村综合服务平台690g7(java+VUE+Mybatis+Maven+Mysql)
    CleanMyMac4.11.2清理苹果电脑硬盘、删除垃圾文件软件
    西湖大学利用 Transformer 分析百亿多肽的自组装特性,破解自组装法则
    【李宏毅】深度学习-2021HW3-CNN(图像分类)
    PC_浮点数加减运算
    氮化镓充电器芯片 NV6128、NV6127、NV6125 QFN6x8mm
    springboot集成mybatis-plus及常用功能配置
  • 原文地址:https://blog.csdn.net/m0_73648729/article/details/139756319