shiro学习17-shiro提供的filter-AbstractShiroFilter

这个类是上面的OncePerRequestFilter的子类,实现了其doInternalFilter方法,所有的业务逻辑在里面实现。这个类也是一个抽象类,但是没有任何的抽象方法,所以只要集成他就可以直接使用了。

这是一个及其重要的类,shiro集成spring的ShiroFilterFactoryBean返回给spring context中的bean就是他,在ShiroFilterFactoryBean类中,getObject方法就是返回给spring context的bean,里面返回的就是AbstractShiroFilter类,具体的实现是org.apache.shiro.spring.web.ShiroFilterFactoryBean.SpringShiroFilter这个类,在构造方法中将SecurityManager和FilterChainResolver类传入到AbstractShiroFilter中。

private static final class SpringShiroFilter extends AbstractShiroFilter {
 
        protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
            super();
            if (webSecurityManager == null) {
                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
            }
            setSecurityManager(webSecurityManager);
            if (resolver != null) {
                setFilterChainResolver(resolver);
            }
        }
}

 

在这个类中将filterChainResolver传入进去,filterChainResolver里面有一个属性FilterChainManager,这里面有一个属性filterChains就表示我们在shiroFilterFactoryBean中配置的所有的路径(也可以说是filter的名字)+filter,在filterChainResolver还有一个属性pathMatcher,用来将访问的url和我们匹配的filter的名字像匹配,决定都是调用哪些filter,也就是一个filterChain

 

我们再来看一下AbstractShiroFilter中的 doFilterInternal方法

protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, final FilterChain chain)
            throws ServletException, IOException {
        Throwable t = null;
        try {
            final ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
            final ServletResponse response = prepareServletResponse(request, servletResponse, chain);
            final Subject subject = createSubject(request, response);
            //noinspection unchecked
            subject.execute(new Callable() {
                public Object call() throws Exception {
                    updateSessionLastAccessTime(request, response);
                    executeChain(request, response, chain);//最后调用的是这个方法,
                    return null;
                }
            });
        } catch (ExecutionException ex) {
            t = ex.getCause();
        } catch (Throwable throwable) {
            t = throwable;
        }
        if (t != null) {
            if (t instanceof ServletException) {
                throw (ServletException) t;
            }
            if (t instanceof IOException) {
                throw (IOException) t;
            }
            //otherwise it's not one of the two exceptions expected by the filter method signature - wrap it in one:
            String msg = "Filtered request failed.";
            throw new ServletException(msg, t);
        }
    }

 

executeChain方法如下:

 

 

protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain)
            throws IOException, ServletException {
        FilterChain chain = getExecutionChain(request, response, origChain);//调用这个方法获得此次访问应该调用的filter链。
        chain.doFilter(request, response);
}

 

getExecutionChain的代码如下:

 

protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
        FilterChain chain = origChain;
        FilterChainResolver resolver = getFilterChainResolver();//他是根据配置的filterChainResolver来获得匹配的filterChain。这里的origChain就是我们在web.xml里面配置的那个DelegatingFilter,就是用来调用shiro的所有请求的代理filter,所有访问shiro的filter都是由它获得。
        if (resolver == null) {
            log.debug("No FilterChainResolver configured.  Returning original FilterChain.");
            return origChain;
        }
        FilterChain resolved = resolver.getChain(request, response, origChain);
        if (resolved != null) {
            log.trace("Resolved a configured FilterChain for the current request.");
            chain = resolved;
        } else {
            log.trace("No FilterChain configured for the current request.  Using the default.");
        }
        return chain;
    }

 

通过这个方法我们基本就知道了shiro的处理请求的流程,当某个请求来了之后,他是通过调用配置的ChainResolver调用匹配的路径,如果找到了对应的路径就执行配置的路径后面的所有的filter。另外ShiroFilterFactoryBean向spring context中传入的bean不是传入的自身,而是传入的org.apache.shiro.spring.web.ShiroFilterFactoryBean.SpringShiroFilter这个类,传入的类(也就是spring中的ObjectType)是SpringShiroFilter.class;也不是他自身。

相关推荐