拦截器Interceptor及与过滤器Filter的区别

统一拦截–拦截器Interceptor

1.概述

  • 概念:是一种动态拦截方法调用的机制,类似于过滤器。Spring框架中提供的,用来动态拦截控制器方法的执行。
  • 作用:拦截请求,在指定的方法调用前后,根据业务需要执行预先设定的代码。
  • 与过滤器Filter的使用差不多。

2.快速入门

  1. 定义拦截器,实现HandlerInterceptor接口,并重写其所有方法。
package com.mannor.Interceptor;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class LoinCheckInterceptor implements HandlerInterceptor {

    @Override  //目标资源方法运行前运行,返回true:放行;false:不放行
    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. 注册配置拦截器
package com.mannor.Config;

import com.mannor.Interceptor.LoinCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration   //声明为配置类
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoinCheckInterceptor loinCheckInterceptor;
	
    @Override  //用来注册拦截器
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loinCheckInterceptor).addPathPatterns("/**");
    }
}

3.拦截路径

  • 拦截器可以根据需求,配置不同的拦截路径:
拦截路径含义举例
/*一级路径能匹配/depts,/emps,/login,不能匹配/depts/1
/**任意级路径能匹配/depts,/depts/1 ,/depts/1/2
/depts/*/depts下的一级路径能匹配/depts/1,不能匹配/depts/1/2,/depts
/depts/**/depts下的任意级路径能匹配/depts,/depts/1,/depts/1/2,不能匹配/emps/1
  • addPathPatterns:拦截的路径。
  • excludePathPatterns:不拦截的路径。
@Configuration   //声明为配置类
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private LoinCheckInterceptor loinCheckInterceptor;

    @Override  //用来注册拦截器
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loinCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

4.拦截器-执行流程

  • 过滤器和拦截器的执行先后流程:
    过滤器和拦截器的执行先后流程

5.Filter与Interceptor

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

6.登录校验的实现–Interceptor

  1. 步骤(与Filter一样)
  • 获取请求url。
  • 判断请求url中是否包含login,如果包含,说明是登录操作,放行。
  • 获取请求头中的令牌( token) 。
  • 判断令牌是否存在,如果不存在,返回错误结果(未登录)。
  • 解析token,如果解析失败,返回错误结果(未登录)。
  • 放行。
    Interceptor登录校验的实现的过程
package com.mannor.Interceptor;

import com.alibaba.fastjson.JSONObject;
import com.mannor.pojo.Result;
import com.mannor.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Slf4j
@Component
public class LoinCheckInterceptor implements HandlerInterceptor {

    @Override  //目标资源方法(Controller方法)运行前运行,返回true:放行;false:不放行
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        System.out.println("preHandle...运行了");
        //1. 获取请求url。
        String requestURI = req.getRequestURI();
        log.info("请求的url:{}", requestURI);

        //2.判断请求url中是否包含login,如果包含,说明是登录操作,放行。
        if (requestURI.contains("login")) {
            log.info("登录操作");
            return true;
        }
        //3.获取请求头中的令牌(token)。
        String jwt = req.getHeader("token");

        //4.判断令牌是否存在,如果不存在,返回错误结果(未登录)。
        if (!StringUtils.hasLength(jwt)) {
            log.info("请求头token为空,返回未登录的信息");
            Result error = Result.error("NOT_LOGIN");//前端需要响应一个json格式的数据
            //手动将对象转换为json格式的数据-------》使用阿里巴巴fastJSON的工具包(需要引入依赖)
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);//使用HttpServletResponse对象返回错误的JSON数据
            return false;
        }
        //5.解析token(校验jwt令牌),如果解析失败,返回错误结果(未登录)。如果错误会报错,所以使用try...catch...
        try {
            JwtUtils.parseJWT(jwt);
        } catch (Exception e) {//程序执行到这里说明程序执行失败--jwt令牌错误
            e.printStackTrace();
            log.info("解析令牌失败,返回未登录的错误信息");
            Result error = Result.error("NOT_LOGIN");//前端需要响应一个json格式的数据
            //手动将对象转换为json格式的数据-------》使用阿里巴巴fastJSON的工具包(需要引入依赖)
            String notLogin = JSONObject.toJSONString(error);
            resp.getWriter().write(notLogin);//使用HttpServletResponse对象返回错误的JSON数据
            return false;
        }
        //6.放行。
        log.info("令牌合法,直接放行");
        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...运行了");
    }
}

除此之外,还需要在配置类WebConfig.java中使用excludePathPatterns()方法对cssvuejs等静态资源放行,不然Interceptor会产生拦截

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

曼诺尔雷迪亚兹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值