添加拦截器

本文详细介绍了Spring MVC的拦截器功能,包括如何实现HandlerInterceptor接口,注册拦截器,过滤拦截请求,以及拦截器方法的执行流程。在拦截器中,可以进行预处理、后续处理和异常处理。通过重写`preHandle`、`postHandle`和`afterCompletion`方法,可以实现请求的鉴权、请求过滤和异常处理。文章还探讨了多拦截器的执行顺序,并给出了实际应用场景的例子。

添加拦截器

当我们需要在所有的请求处理之前,先做一些预处理,或者在请求处理之后做一些后续处理,或者在处理执行流程中如果有异常则执行一段出错逻辑,这时候我们可以使用Spring MVC的拦截器功能

事实上这个功能很常用,他的逻辑类似Spring的AOP,在所有的请求处理逻辑之上增加一些增强逻辑

HandlerInterceptor接口

首先创建一个拦截器类,并实现HandlerInterceptor接口

public class MyInterceptor implements HandlerInterceptor {
}

实现了这个接口之后,我们可以看到可以重写三个方法

在这里插入图片描述

这三个方法都有默认实现,我们想要实现什么拦截效果,就重写对应的方法即可,首先介绍preHandle方法

preHandle方法是在请求处理方法之前执行的,他有一个布尔类型的返回参数,返回true则表示放行该请求,返回false则拦截该请求,我们常使用这个功能来做简单的鉴权功能

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行前置处理方法");
        System.out.println(request.getRequestURI());
        return true;
    }
}

参数列表中的HttpServletRequest 类可以帮助获取到被拦截的请求的请求信息,用于定制拦截逻辑

当我们返回false值时,拦截器拦截该请求,这个时候浏览器会得到一个空白页面,这个时候可以用参数列表中的HttpServletResponse类来设置页面转发或重定向到登录页面或者初始页面

注册拦截器

创建完拦截器之后,我们需要在Spring MVC配置类中添加这个拦截器,这样拦截器才能生效

重写WebMvcConfigurer接口中的addInterceptors方法来注册拦截器,然后用addPathPatterns方法来绑定需要拦截的请求,如果需要拦截所有的请求,可以使用/**来表示

@Configuration
public class MyWebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**");
    }
}

编写一个请求方法来测试拦截结果

@RestController
public class MyController {

    @RequestMapping("/test")
    public String test() {
        System.out.println("执行请求处理方法");
        return "SUCCESS";
    }
}

测试结果如下,执行了拦截器中的preHandle方法,也获取到了拦截到的uri

在这里插入图片描述

过滤拦截请求

在绑定拦截的请求时,使用/**来拦截所有请求,但是其中有某些请求我们又不想拦截时,可以使用excludePathPatterns方法来过滤拦截请求,这种情况最常见的场景就是过滤静态资源请求,或者过滤登录页的请求

假如我有一张静态资源图片,而静态资源请求,一般是不需要拦截的

在这里插入图片描述

这时候可以先给静态资源的访问路径先加上一个请求前缀

spring:
  mvc:
    static-path-pattern: /static/**

这时候访问静态资源需要加上/static这个前缀

然后在配置拦截器的时候过滤/static/**请求就行了

@Configuration
public class MyWebConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/**").excludePathPatterns("/static/**");
    }
}

拦截器方法的执行流程

除了preHandle方法,HandlerInterceptor接口还有另外两个方法

postHandle方法用于在请求方法执行结束后执行一段逻辑,afterCompletion方法用于在视图渲染完成后执行一段逻辑

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("执行preHandle方法");
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("执行postHandle方法");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("执行afterCompletion方法");
    }
}

发送一个测试请求

在这里插入图片描述

可以发现他们的执行先后顺序是

  1. 执行preHandle方法
  2. 执行请求处理方法
  3. 执行postHandle方法
  4. 执行afterCompletion方法

执行出现异常时

当执行过程出现异常时,无论是preHandle方法,请求处理方法,还是postHandle方法出现了异常,都会触发afterCompletion方法,并且可以通过afterCompletion方法参数列表中的Exception类来获取异常信息

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("执行afterCompletion方法");
        System.out.println(ex.getMessage());
    }
}

我们在请求处理方法中模拟一个异常,测试结果

@RestController
public class MyController {

    @RequestMapping("/test")
    public String test() {
        System.out.println("执行请求处理方法");
        throw new RuntimeException("模拟异常");
    }
}

在这里插入图片描述

可以看到在发生异常时,会触发afterCompletion方法,并且可以获取到异常的信息

多拦截器执行流程

当有多个拦截器时,执行顺序如下图

在这里插入图片描述

  1. 顺序执行所有拦截器的preHandle方法
    • 如果preHandle方法返回true,执行下一个preHandle方法
    • 如果preHandle方法返回false,倒序执行所有已经执行过的拦截器的afterCompletion方法
  2. 如果所有preHandle方法返回true,执行请求处理方法,否则不执行
  3. 如果执行了请求处理方法,倒序执行所有拦截器的postHandle方法
    • 前面的所有步骤,如果有发生异常,则倒序执行所有已经执行过的拦截器的afterCompletion方法
    • 如果无异常,则倒序执行所有拦截器的afterCompletion方法
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值