Shiro自定义过滤器会执行两次?看我怎么给你解决

 关注“Java架构栈”微信公众号,回复暗号【Java面试题】即可获取大厂面试题。

最近九哥的一个学生在使用自定义ShiroFilter处理JWT校验时,发现自己写的Filter在处理一次请求时会被执行两次。这个问题困扰了他一个下午都没有解决,最后不得不求助我来帮忙,那我们就来复现一下这个问题,并给出对应的解决方案吧。

 问题复现

为了复现这个bug,我们先来自定义一个过滤器TokenFilter,代码如下:

/**
 * 自定义shiro过滤器
 */
@Component("jwt")
@Slf4j
public class TokenFilter extends AccessControlFilter {
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        // 演示问题,省略调具体业务代码....
        log.debug("=============TokenFilter===============");
        // 演示问题,省略调具体业务代码....
        return true;
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        // 演示问题,省略调具体业务代码....
        return false;
    }
}

接着还需要有个Shiro配置类,代码如下:

@Configuration
public class ShiroConfig {
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition(){
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
        // 白名单
        chainDefinition.addPathDefinition("/user/login","anon");
        chainDefinition.addPathDefinition("/user/regist","anon");
        chainDefinition.addPathDefinition("/error","anon");
        // 让自定义shiro过滤器 jwt(jwt是自定的过滤器的IOC容器中的名字)处理指定的url
        chainDefinition.addPathDefinition("/index/category-recommends","jwt");
        return chainDefinition;
    }
    // 省略其他无关代码
}

最后我们可以执行一次Post请求,观察上面这个自定义过滤器的执行情况。

Shiro自定义过滤器会执行两次?看我怎么给你解决_第1张图片

从控制台的信息中我们可以看出,日志被打印了两次,那么这个问题到底是怎么产生的呢?

 原因分析

为了定位上述问题,我们可以在自定义过滤器中打上断点。

Shiro自定义过滤器会执行两次?看我怎么给你解决_第2张图片

通过断点我们可以清晰的看到,自定义的filter确实被执行了两次。其中第一次是作为shiroFilterChain中的过滤器被shiroFilter调用的,另外又在全局过滤器中注册了我们自定义的过滤器,这就导致了在shirofilter之后,该过滤器又被被执行了一次!

 解决方案

基于上述分析,要想解决这个问题,我们只需要让自定义过滤器不出现在全局过滤器中即可。我们可以编写一个FilterConfig配置类来解决这个问题,代码如下。

@Configuration
public class MyFilterConfig {

    @Bean
    public FilterRegistrationBean tokenFilterFilterRegistrationBean(TokenFilter tokenFilter){
        FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(tokenFilter);
        // 不让该filter出现在全局过滤器链中
        registrationBean.setEnabled(false);
        return registrationBean;
    }
}

添加了该配置类后,我们再次启动应用,并再次观察断点情况。

Shiro自定义过滤器会执行两次?看我怎么给你解决_第3张图片

现在你会发现,Filter处理一次请求会被执行两次的情况就没有了,现在你知道如何解决这个bug了吗?关注Java架构栈,干货天天多不断哦!

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