拦截器详解

一、概述

什么是拦截器?

是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制方法的执行。

到底是干啥用的?

拦截请求用的,在指定的方法调用前后,执行在拦截器中编写的程序

比如:我们做了一个页面,我们希望在用户登录之后才能访问后面的页面,但是他们可以直接在地址栏中输入 /接口 去访问后面的页面。

所以我们要使用拦截器,在用户直接访问了接口之后,在程序的方法执行前拦截住,检查一下有没有好好的登陆再决定方法是否要执行。

拦截器详解_第1张图片

操作步骤

1、定义拦截器

实现HandlerInterceptor接口,并重写其中的所有方法

拦截器详解_第2张图片

其中有三个方法需要重写

  • preHandle:在目标方法(接口)执行前拦截住,先执行其中的逻辑后决定是否放行目标方法。返回值 true放行,false不放行
  • postHandle:在目标方法(接口)执行后拦截住,执行其中的逻辑
  • afterCompletion:在试图渲染完毕后拦截住,执行其中的逻辑

你可能会疑问,里面什么数据都没有,我们之前是通过参数声明的方式直接拿到,但是在重写的这个方法中并没有。那怎么在里面验证前后端的数据呢?没错,这是因为数据直接被包含在了这方法里的参数中

  • HttpServletRequest:代表请求,所有的请求数据都在request对象中
  • HttpServletRequest:代表响应,所有的响应数据都在response数据中

而且还在拦截器上加上@Component注解,那么就代表就要交给了IOC容器管理了,此时就变成了一个bean对象。

2、注册拦截器

拦截器详解_第3张图片

只有在这里面引入刚才写完的拦截器后,拦截器才会生效。重写其中的addIntercepter方法。顾名思义,就是添加那些拦截器。

注:既然是拦截器,那么它就能拦截所有的接口。一定要注意不能让它拦截登录接口和注册接口,不然要访问数据接口就要登录生成的token,要登陆的token就要访问登录接口,由于登录接口也被拦截了,那么访问登录接口就要登录生成的token,要登录的token就要访问登录接口......开启了无限套娃。因此要使用excludePathPatterns方法排除不需要拦截的接口。


二、拦截详解

拦截路径

拦截器详解_第4张图片

执行流程

当我们打开浏览器来访问部署在web服务器上的web应用时,此时过滤器Filter就会拦截到这次请求,然后依次执行 放行前操作,放行,放行后操作。之后就会进入springboot程序 。

        Tomcat服务器是一个servlet容器,只识别servlet程序,不识别controller程序。因此Spring的web环境提供了一个前端控制器DispatcherServlet,请求会先到这里面,DispatcherServlet又会转给Controller,这个过程中会遇到拦截器Interceptor,以此执行preHandle、postHandle、afterCompletion。反过来响应也是如此

拦截器详解_第5张图片

过滤器与拦截器的区别

  • 接口规范不同:过滤器需要实现Filter接口,而拦截器需要实现HandlerIntercetor接口
  • 拦截范围不同:过滤器Filter会拦截所有的资源,而拦截器Interceptor会拦只会拦截spring中的资源 

过滤器与拦截器我们只使用其中一个就行了,推荐使用拦截器


三、使用案例

登录校验

@Component
public class LoginInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //获取令牌
        String token = request.getHeader("Authorization");
        //验证token
        try {
            Map claims = JwtUtil.parseToken(token);

            //将解析的token信息放入ThreadLocal
            ThreadLocalUtil.set(claims);

            //没有异常就放行
            return true;
        } catch (Exception e) {
            //未登录,不放行
            response.setStatus(401);
            return false;
        }

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

        //清空ThreadLocal的数据
        ThreadLocalUtil.remove();
    }
}

在这里补充一个

全局异常处理器

我们在写bug程序的时候,难免会遇到很多bug,通常我们会直接try - catch包裹住方法,然后处理掉。但是这样会让程序显得很臃肿,不方便别人观看。因此我们还是选择直接throw抛出异常让调用者处理。就这样一直抛一直抛,扔到最后,让一个专门的类来做统一处理,这就是全局异常处理。

拦截器详解_第6张图片

代码实现

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    public Result handleException(Exception e){
        e.printStackTrace();
        //有的异常可能没有message,所以要先用三元运算符判断一下
        return Result.error(StringUtils
                .hasLength(e.getMessage()) ? e.getMessage() : "操作失败");
    }

}

简单解释一下,

  • @RestControllerAdvice代表这是一个全局异常处理器。
  • @ExceptionHandler()代表你要捕获什么异常,Exception.class代表你要捕获所有的异常,因为Exception是所有异常的父类 

你可能会疑问,我们最后return出去的不是result类吗,前端是怎么接受到json文件呢?

这是因为@RestControllerAdvice = @ControllerAdvice + @ResponesBody

@ResponesBody会将方法的返回值转化为Json

你可能感兴趣的:(java,前端,开发语言)