日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Shiro切入Spring的方式

發布時間:2024/4/17 javascript 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Shiro切入Spring的方式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在springMVC中要使用shiro,一般都遵循下面的配置:

applicationContext-shiro.xml

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> .....</bean>

web.xml

<listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener><!-- Spring MVC Servlet --> <servlet><servlet-name>springServlet</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath*:/spring/springmvc-common.xml</param-value></init-param><load-on-startup>1</load-on-startup> </servlet> <servlet-mapping><servlet-name>springServlet</servlet-name><url-pattern>/</url-pattern> </servlet-mapping><filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><init-param><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param> </filter> <filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern> </filter-mapping>

看到這樣的配置,難免有些疑問:
1. 這三者是怎樣融合到一起的
2. 為什么那個bean的id和filter的name保持一樣
3. 為什么配置的bean是一個factoryBean而不是普通的bean

帶著這樣的疑問,跟蹤下啟動過程。正向跟蹤,即在refresh方法中開展,鎖定getBean方法,通過name來追蹤shiroFilter,發現關系比較亂,而且費時。于是鎖定ShiroFilterFactoryBean的getObject方法,反向追蹤,獲得了下面的序列圖:

重點就是:

配置的監聽器啟動容器的初始化,完成上面ShiroFilterFactoryBean的創建和維護

servlet觸發過濾器Filter的init方法,在initDelegate方法中會getBean(),這個getBean最終會轉移到ShiroFilterFactoryBean的getObject方法

上面的問題第二個看源碼很容易解決。

在調用DelegatingFilterProxy初始化方法時:

@Override protected void initFilterBean() throws ServletException {synchronized (this.delegateMonitor) {if (this.delegate == null) {// If no target bean name specified, use filter name.if (this.targetBeanName == null) {this.targetBeanName = getFilterName();}// Fetch Spring root application context and initialize the delegate early,// if possible. If the root application context will be started after this// filter proxy, we'll have to resort to lazy initialization.WebApplicationContext wac = findWebApplicationContext();if (wac != null) {this.delegate = initDelegate(wac);}}} }protected final String getFilterName() {return (this.filterConfig != null ? this.filterConfig.getFilterName() : this.beanName); }protected Filter initDelegate(WebApplicationContext wac) throws ServletException {Filter delegate = wac.getBean(getTargetBeanName(), Filter.class);if (isTargetFilterLifecycle()) {delegate.init(getFilterConfig());}return delegate; }

獲取的這個名字將用來追尋之前spring維護的那個bean,并且還要通過它來拿到一個Filter實例。

那么為什么配置的那個bean是一個factoryBean而不是一個普通的bean?

首先shiro是基于過濾器來實現的,配置一個filter是必要的。

但是和spring在一起使用,就要讓spirng來管理一些filter依賴的bean,例如安全管理器,還有自己實現的認證和鑒權服務之類。如果shiro直接寫一個過濾器,那spring的容器早就啟動完了,你這些東西怎么注入。

所以只有提前初始化那些過濾器需要的東西,讓他們依附于某個特定類,通過約定來在過濾器的初始化中獲取(這個就是前面提到的相同的name)。

那么這個bean可以是普通的bean嗎?答案是不可以,畢竟shiro要的這個bean得是一個filter。普通的bean只能獲取到它本身的實例,要獲取filter那么它必須實現Filter接口。但是創建filter的方法你掌控不了了,spring會通過反射來創建對象,怎么創建是它說了算,自定義的創建是不可能了。

這時候你就只能使用FactoyBean了。

這個FactoryBean當然得交給shiro實現。不過filter的創建方式自由了,我們可以通過getBean來獲取這個filter,另一邊的filter配置還有必要嗎?

當然必要。因為這個filter怎么創建不重要,切入web的生命周期才重要,這個配置是一個規范。所以spring引入了這么一個類: DelegatingFilterProxy。就是一個代理類,自定義的實現轉移到factoryBean了,這里就是公共類,主要操作是在容器中追蹤并獲取之前的factoryBean,并在初始化方法中獲取需要的filter。

Spring容器的啟動依靠監聽器,而filter是在監聽器之后,依靠servlet規范,在listener,filter和servlet三者之間尋找契機,并形成一個共榮圈,Spring把這種關系處理得非常妙!

轉載于:https://www.cnblogs.com/lucare/p/8679131.html

與50位技術專家面對面20年技術見證,附贈技術全景圖

總結

以上是生活随笔為你收集整理的Shiro切入Spring的方式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。