自定义拦截器实现

简介: 自定义拦截器实现

在 Spring MVC 框架中, 拦截器作为一种机制, 用于对请求进行拦截. 拦截器可以在请求进入处理器之前、处理器返回处理之后、视图渲染之前等各个环节进行拦截.

拦截器通常用于实现一下功能 :


  • 鉴权和身份认证
  • 日志记录和统计
  • 请求参数和校验和过滤
  • 缓存和性能优化
  • 路径重定向和错误处理


也就是说, 当需要对多个请求进行相同或者类似处理时, 可以使用拦截器来统一处理, 从而避免冗余的代码和低效的维护.


一. 自定义拦截器实现



1. 创建一个 Spring Boot 项目, 添加 Spring Web、 Lombok 起步依赖.


正常创建一个 Spring Boot 的 Maven 项目即可.


2. 创建一个公共包 common 实现登录拦截器类


在 Spring MVC 中, 拦截器是通过实现 HandlerInterceptor 接口实现的.

在实现 HandlerInterceptor 接口时, 重写里面的拦截器方法.


3ba764edad47ceb91fa7adc97a3f782b.png


a. preHandle


该方法用于在请求处理之前进行拦截和处理. 该方法在 DispatcherServlet ( 调度器 ) 将请求对象封装为 HandlerExecutionChain 对象后、但在调用处理器( Controller ) 之前被调用在 preHandle 方法中, 我们可以对请求进行检查、验证、修改等操作, 例如 :

  • 身份认证和权限控制
  • 请求参数校验和过滤
  • 缓存和性能优化


b. postHandle


该方法用于在请求处理完成之后, 试图渲染之前进行拦截和处理. 该方法在 HandlerAdapter 将处理器执行并将其结果返回给 DispatcherServlet 之后调用.在 postHandle 方法中, 我们可以做一些与请求处理有关的操作, 例如 :

  • 修改 Model 数据
  • 添加一些公共的 Model 属性
  • 对视图进行渲染前的处理


c. afterCompletion


该方法用于请求处理完毕后进行回收和清理工作, 该方法在视图渲染完毕之后被调用, 用于释放资源和进行日志记录等操作在 afterCompletion 方法中, 我们可以进行一些与请求处理过程相关的清理工作, 例如 :

  • 清理 ThreadLocal 变量
  • 关闭打开的文件或数据库连接
  • 记录请求处理时间和结果


3. 重写方法


由于我们是一个登陆拦截器, 可以想象在各个功能使用之前就需要进行权限的鉴定和登陆的检验. 因此应该重写 preHandle 方法, 在请求处理之前进行拦截和处理

@Component
    public class LoginInterceptor implements HandlerInterceptor {
        /**
* 拦截器为调用方法执行之前执行的方法
*
* @param request  请求
* @param response 响应
* @param handler  表示要执行的处理器, 即处理请求的 Controller 对象或者是拦截器的对象
* @return true 拦截器验证成功, 继续执行后续操作
* false 拦截器验证失败, 验证未通过后续流程不执行
* @throws Exception 异常
*/
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 用户登录判断
            HttpSession session = request.getSession(false);
            if (session != null && session.getAttribute("session_userinfo") != null) {
                // 该用户已经登陆
                return true;
            }
            // 请求无权限, 返回状态码提示
            response.setStatus(401);
            return false;
        }
    }


4. 添加拦截器配置


有了拦截器, 但还没有实现拦截规则, 并且这个拦截的规则是要随着 Web 项目的启动而启动的, 否则在进行页面访问时, 就无法提前拦截了. 因此还需要将自定义的拦截器添加到我们的系统配置当中.而在 Spring MVC 中提供了一个 WebMvcConfigurer 接口, 因为我们配置的是拦截器, 因此重写里面的 addInterceptors 方法即可.

image.png


在重写的方法中, 将我们实现的登陆拦截器添加进去, 然后配置拦截的规则即可

@Configuration
    public class MyInterceptorConfig implements WebMvcConfigurer {
        // 将自定义的拦截器注入
        @Autowired
        private LoginInterceptor interceptor;
        /**
* @param registry 注册对象
*/
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // 注册对象将拦截器添加进框架中
            registry.addInterceptor(interceptor)
                // 配置拦截规则
                .addPathPatterns("/**") // 拦截所有的 url
                .excludePathPatterns("/user/reg") // 排除用户注册 url
                .excludePathPatterns("/user/login") // 排除用户登陆 url
                .excludePathPatterns("/image/**"); // 排除 image 文件夹底下的所有文件
        }
    }


一般对于拦截规则的设置, 我们都是先拦截所有, 然后放行部分. 并且里面的路径写法和我们之前学习的相同.


5. 验证拦截器


当写好拦截器后, 我们创建一个用户操作类

@RestController
    @RequestMapping("/user")
    public class UserController {
        @RequestMapping("/reg")
        public String register() {
            return "注册成功";
        }
        @RequestMapping("/login")
        public String login() {
            return "登陆成功";
        }
        @RequestMapping("article")
        public String writer() {
            return "写文章鉴权";
        }
    }


根据我们的拦截规则, 我们排除了 url 为 /user/reg 和 user/login 以及 image 文件底下的所有文件. 因此这三个都是可以访问的, 其他的 ulr 都是不可以访问的, 也就是我们上面写的 /user/article 是无法访问的, 会被拦截并返回 401


可以看到, 我们放行的方法都能够正确经过拦截器的处理

9206dc285059eb2c037e5b546e642515.png

064a7f3ebdcf2be0042a50382bfce96a.png

而我们的 /user/article 被拦截器拦截在外无法执行

e567fb21e305d12cad15e3d96cf2eefd.png


6. 调整返回错误信息


对于我们刚刚的做法中, 当被拦截以后, 说明这个方法是不符合要求的请求, 直接返回了 401 拒绝访问, 但在开发中, 无论是否被拦截, 都应该将信息返回给前端, 而并非返回页面而是要一个数据, 前端根据我们返回的数据进行判断后再执行下一步操作.


因此, 我们可以封装一个统一的返回对象 ResultAjax

即使后端拦截了这个方法, 它没有进行登录, 我们也不能帮前端进行重定向让给用户去登录, 这是要越权行为. 我们只需要返回约定的错误代码 code 告诉前端, 并把错误信息返回给前端即可.

@Data
    public class ResultAjax {
        private int code;
        private String msg;
        private String date;
    }


当被拦截时, 说明为经过登陆鉴权, 返回约定的对象即可

@Component
    public class LoginInterceptor implements HandlerInterceptor {
        /**
* 拦截器为调用方法执行之前执行的方法
*
* @param request  请求
* @param response 响应
* @param handler  表示要执行的处理器对象, 即处理请求的 Controller 对象或者是拦截器的对象
* @return true 拦截器验证成功, 继续执行后续操作
* false 拦截器验证失败, 验证未通过后续流程不执行
* @throws Exception 异常
*/
        @Autowired
        private ResultAjax resultAjax;
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            // 用户登录判断
            HttpSession session = request.getSession(false);
            if (session != null && session.getAttribute("session_userinfo") != null) {
                // 该用户已经登陆
                return true;
            }
            ObjectMapper objectMapper = new ObjectMapper();
            // 设置数据返回格式, 防止乱码解析
            response.setContentType("application/json; charset = utf8");
            // 当前方法未通过登陆鉴权, 返回约定的结果
            resultAjax.setCode(-1); // 约定错误都为 -1 状态码, 成功都为 200
            resultAjax.setMsg("用户未登录, 请登录后再操作 !");
            resultAjax.setDate(""); // 为登陆没有数据返回
            // 将返回的数据对象转为 JSON 格式字符串
            String respJson = objectMapper.writeValueAsString(resultAjax);
            // 返回统一的处理对象给前端
            response.getWriter().write(respJson);
            return false;
        }
    }


1aa52b2316220a1655d3d722cb52589c.png


这是一般我们的处理情况, 最好的还是进行一个统一的格式的错误信息返回. 关于统一的数据处理和错误处理, 在后续文章中会讲解到.

相关文章
|
3月前
SpringMVC之拦截器和异常处理器
【1月更文挑战第20天】SpringMVC之拦截器和异常处理器
58 0
QGS
|
存储 调度 数据安全/隐私保护
入门SpringMVC之Interceptor拦截器
SpringMVC中的Interceptor拦截器,它的主要作用是拦截指定的用户需求,并进行相应的预处理与后处理。
QGS
77 0
|
前端开发 Java Spring
SpringMVC拦截器interceptor
Spring MVC 的拦截器类似于 Servlet 开发中的过滤器 Filter,用于对处理器进行预处理和后处理。
109 0
SpringMVC拦截器interceptor
|
XML Java 数据格式
自定义拦截器|学习笔记
快速学习自定义拦截器
147 0
自定义拦截器|学习笔记
|
Java Spring 容器
SpringBoot中添加拦截器,在拦截器中注入其他类的时候出现空指针异常解决办法
SpringBoot中添加拦截器,在拦截器中注入其他类的时候出现空指针异常解决办法
339 0
SpringMVC 如何使用注解完成登录拦截
SpringMVC 如何使用注解完成登录拦截
SpringMVC 如何使用注解完成登录拦截
|
Java 开发者
使用Java动态代理实现的拦截器
在软件开发领域,有一条很重要的规则:Don’t Repeat Yourself,即DRY规则,意思是不要书写重复的代码
376 0
使用Java动态代理实现的拦截器
springmvc 在方法上使用 @ModelAttribute 注解
在方法上使用 @ModelAttribute 注解
167 0
|
前端开发 Java Spring
详解SpringMVC中使用Interceptor拦截器
SpringMVC 中的Interceptor 拦截器也是相当重要和相当有用的,它的主要作用是拦截用户的请求并进行相应的处理。
1055 0