过滤器和拦截器

过滤器

实现方法:
  1. 定义一个类,实现Filter接口
  2. 重写doFilter()方法
@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
       // filter对传给servlet的request进行过滤:预处理
       filterChain.doFilter(servletRequest,servletResponse);
       // filter对servlet返还给客户端的response进行后处理
       }
  1. 配置拦截路径: 注解方式@WebFilter或web.xml
过滤器链(配置多个过滤器)

web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。
所以当我们只实现了一个filter时,调用filter.dofilter(),它去寻找filter链的下一个filter,但它下面已经没有了,因此就直接转发给对应的servlet中了。

    * 执行顺序:如果有两个过滤器:过滤器1和过滤器2
        1. 过滤器1
        2. 过滤器2
        3. 资源执行
        4. 过滤器2
        5. 过滤器1

    * 过滤器先后顺序问题:
        1. 注解配置:按照类名的字符串比较规则比较,值小的先执行
            * 如: AFilter 和 BFilter,AFilter就先执行了。
        2. web.xml配置: <filter-mapping>谁定义在上边,谁先执行
Springboot中编写filter的配置类代替@WebFilter注解配置
  1. 编写实现了Filter接口的类,无需添加注解
  2. 配置类中使用FilterRegistrationBean来添加filter并设置过滤路径和优先级等:
@Configuration
public class FilterConfig {

    @Bean // 将自定义filter对象注入到spring容器中
    public MyFilter myFilter(){
        return new MyFilter();
    }

    @Bean
    public FilterRegistrationBean getFilterRegistrationBean(MyFilter myFilter){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(myFilter);
        filterRegistrationBean.addUrlPatterns("/filter/*");
        filterRegistrationBean.setName("myFilter");
        filterRegistrationBean.setOrder(1);
        return filterRegistrationBean;
    }
}
过滤器 用户登录

我们在FilterConfig中通过addUrlPatterns()设置了过滤路径, 之后客户端请求中包含该过滤路径的请求都转到doFilter()中来,这些请求中带有/**/open/**模式的会放行,其他的如果没有设置token header都不放行,认为用户未登录,转到未登录中。

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // HttpServletRequest extends ServletRequest, 因为传过来的引用为Http的请求因此可以通过强转转为子接口,这是为了使用子接口特有的功能
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String uri = request.getRequestURI();
        System.out.println(uri);

        /*String method = request.getMethod();
        System.out.println(uri+" "+method+"哈哈我进入了 MyFilter 过滤器了");
        filterChain.doFilter(servletRequest, servletResponse);*/

        // 路径匹配器 https://blog.csdn.net/andy_zhang2007/article/details/88884286
        AntPathMatcher matcher = new AntPathMatcher();
        if (matcher.match(openUrl, uri)){ // 如果是开放路径open 直接放行
            System.out.println("匹配成功!直接放行!");
            filterChain.doFilter(servletRequest, servletResponse);
        }else{
            String token = request.getHeader("token");
            if (token == null || "".equals(token)){ // 加上open才能通过拦截器
                servletRequest.getRequestDispatcher("/filter/open/unLogin").forward(servletRequest, servletResponse);
            }else{// 有token代表用户登录,放行
                filterChain.doFilter(servletRequest, servletResponse);
            }
        }
    }

拦截器

类似于filter,但拦截器interceptor是springmvc的一部分:
在这里插入图片描述

实现
  1. 实现HandlerInterceptor接口
  • preHandler():目标方法执行前执行,返回值为布尔类型,返回为true时会执行目标资源
  • postHandler():目标方法执行后,视图对象返回前执行
  • afterCompletion():所有流程执行完之后执行
    在这里插入图片描述
  1. 配置springmvc的配置文件
<!--配置拦截器-->
<mvc:interceptors>
    <mvc:interceptor>
        <!--对哪些资源执行拦截操作-->
        <mvc:mapping path="/**"/>
        <bean class="com.itheima.interceptor.MyInterceptor1"/>
    </mvc:interceptor>
</mvc:interceptors>
springboot整合SpringMVC拦截器

在编写拦截器后,配置方法从编写spring-mvc.xml到编写配置类实现WebMvcConfigurer:

@Configuration
public class MvcConfig implements WebMvcConfigurer {
//注册拦截器
@Bean
public MyInterceptor myInterceptor(){
    return new MyInterceptor();
}
//添加拦截器到spring mvc拦截器链,快捷键ctrl + 0/o, 配置拦截器和拦截器路径
@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(myInterceptor()).addPathPatterns("/*").excludePathPatterns("/*/open/*"); // 这里的路径不能写成/**/open/** 不然会报错!
}
}
用户登录

这里和filter的区别就是匹配放行路径通过excludePathPatterns()给设置好了,代码中只需要判断是否登录即可:

@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("MyInterceptor....在请求处理之前进行调用(Controller方法调用之前)");
        String requestUrl=request.getRequestURI();
        System.out.println("过滤器MyFilter拦截了请求为" + requestUrl);

        // 拦截验证用户是否登录,判断是否携带token即可
        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token)){
            request.getRequestDispatcher("/filter/open/unLogin").forward(request, response);
            return false; // 未登录,进行拦截
        }
        return true;
    }

过滤器和拦截器是可以同时配置的,都可以实现我们想要的功能。

postman安装使用

https://zhuanlan.zhihu.com/p/41212281
复制url到postman中,可以设置请求头token等信息,比swagger要灵活

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值