首先在配置shiro框架時,由spring託管shiro。由spring框架中的DelegatingFilterProxy類來代理shiro框架中的ShiroFilterFactoryBean類,這樣spring和shiro就有創建了關係。web
web.xml文件中配置:spring
sprio-shiro.xml文件中配置:瀏覽器
當瀏覽器發起請求時(前面已經講到spring託管了shiro),那麼就調用OncePerRequestFilter的doFilter方法。爲何調用這個類方法,首先咱們來看一下的shiro的各過濾器的一個關係:服務器
並且spring在建立ShiroFilterFactoryBean單例對象的時候,會調用ShiroFilterFactoryBean的getObject()方法,getObject()方法裏在調用createInstance()方法來建立SpringShiroFilter單例對象:session
而SpringShiroFilter類繼承AbstractShiroFilter,而AbstractShiroFilter又繼承OncePerRequestFilter(由上面的過濾器關係能夠知道)。因此當瀏覽器發起請求時,會首先就調用OncePerRequestFilter的doFilter()方法。OncePerRequestFilter.doFilter()方法內部所作的操做以下圖,會調用doFilterInternal()方法:框架
有哪些子類重寫這個方法呢只有兩個(一:AbstractShiroFilter;二:AdviceFilter)。看圖:spa
由於SpringShiroFilter只繼承了AbstractShiroFilter,因此只調用AbstractShiroFilter的doFilterInternal方法:代理
經過上面的圖能夠看到subject就是在這個時候建立的。固然後續還會作一些初始化的操做。能夠知道有一個excuteChain方法,該方法須要一個chain屬性,這個就是原生的過濾器鏈,是catalina的。看圖:xml
接回excuteChain方法,該方法會生成一個代理的過濾器鏈,並執行裏面過濾器的doFilter()方法操做。在生成這個代理的過濾器鏈,會作一些請求的路徑和本身在配置spring-shiro文件中配置的路徑是否有匹配的。如發現有匹配的,就會生成過濾器鏈。看下圖:對象
這個代理過濾器鏈的名稱就是,以下圖:
到如今,一些基本的操做已經完成(好比subject建立等)。接下來就是真正執行過濾器鏈的時候了。
有一個假設:瀏覽器第一次訪問該系統,sessionid已經失效的狀況下。會獲得以下圖:
根據路徑解析會獲得UserFilter(shiro自帶的)和SysUserFilter(這個是本身定義的過濾,並交給shiroFilterFactoryBean進行了管理)。接下來就開始執行ProxiedFilterChain的doFilter()方法。看圖:
像UserFilter和SysUserFilter就在這裏執行開始之路。由於按照順序首先執行UserFilter過濾器。執行doFilter()方法(OncePerRequestFilter的doFilter(),由於子類沒有重寫這個方法),接着在OncePerRequestFilter的doFilter()裏執行doFilterInternal()方法。注意:此時不在執行AbstractShiroFilter的doFilterInternal()方法,而是執行AdviceFilter類的doFilterInternal()方法。由上面的過濾器的關係能夠知道UserFilter只繼承了AdviceFilter抽象類。因此此時執行AdviceFilter類的doFilterInternal()方法。看圖:
接着就是一路執行,瀏覽器第一次請求服務器的時候,會須要生成sessionid給瀏覽器。看圖: