程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> shiro realm 注解失敗問題解決過程,shirorealm

shiro realm 注解失敗問題解決過程,shirorealm

編輯:JAVA綜合教程

shiro realm 注解失敗問題解決過程,shirorealm


  做為一名在.net混了八九年的老兵油子,轉戰java時間並不長,剛開始做項目完全是憑借對C#的認識來做,雖然遇到一些問題,但實際結果顯示C#在語言上和java還是有很大相似度,而且微軟的MVC與Spring MVC也是那麼的神似,這也是為什麼我在做項目前並未對java進行系統的學習也能做項目的原因。最近稍微有些空閒時間,所以決定從基礎開始系統的學習java,這裡並沒有太多高深技術可分享的,本篇給大家分享我解決問題的一個經驗:觸類旁通或者叫舉一反三,對了還有一點,對於存在可優化點的部分要不輕言放棄。
 
  困擾以久的問題:

  項目中應用shiro進行登錄權限認證,在Realm實現類中注解服務不成功,得到的實例是null。網上遇到同類問題的還不少,可能每個人的項目情況不同,我並未從中得到正確的解決方案。
 

@Autowired
 private ISecurityService securityService;

  有兩種方法可以解決:

  •   通過ApplicationContext動態獲取實例
private ISecurityService securityService;

    private void initSecurityService() {
        if (null == this.securityService) {
            ApplicationContext appCtx = ApplicationContextUtils.getApplicationContext();
            this.securityService = appCtx.getBean(ISecurityService.class);

        }
    }

 

  •   通過靜態屬性注解,這個方法可以用來調試spring是否有對這個屬性進行過注解。為什麼下面代碼中的變量是靜態的呢?當不是靜態類型時,調試過程中的確有進行過注解,而且是注解成功的,但當程序執行後,shiro獲取到的實例為null,並不是之前注解過的實例,將這個變量修改為靜態的之後運行成功。
private static ISecurityService securityService;
    @Autowired
    public void setSecurityService(ISecurityService securityService) {
        securityService = securityService;
    }


  以上兩種寫法都比較惡心,但當時對於spring類掃描的不了解,也只能做罷。在知識不夠的情況下,如果一味的去鑽也許不一定會有完美的結果,所以我選擇暫時放棄。


  項目中遇到過使用數據庫事務不生效的情況,當時同事的解釋是spring掃描的問題,在加載事務配置時,不能掃描Controller。後來有時間研究了下,由於我們使用了spring mvc,而且在web.xml中采用了非常經典的Application Context +DispatcherServlet Context結構。而有意思的是我們並沒有給Application Context配置有關資源掃描以及Bean加載的信息,只有一個shiro配置文件的加載,結果就是項目所有的bean加載都集中在DispatherServlet這個MVC的配置文件中。

  也有說如果只存在一個Servlet,那麼可以選擇只使用一個Context,這樣也可以避免誤使用雙親上下文所帶來的問題,這個做法我還沒有嘗試,有時間研究下。


  Application Context是什麼?
  它是應用程度級別的一個上下文,這個上下文其中一個重要功能就是負責提供對訪問數據庫事務,數據層以及其它一些你想通過應用程序訪問的需求(這裡也許描述的不夠准確,有興趣的可上官方網站上去看文檔)。比如上面的方法一,獲取bean就是通過這個上下文對象動態獲取得到。

  DispatcherServlet Context是什麼?
  一個應用程序可以定義多個Servlet,每個Servlet都有一個屬於自己的上下文,我們項目中只有一個Servlet。

  Application Context與DispatcherServlet Context的關系?
  DispatcherServlet Context的父級是Application Context,會繼承所有Application Context所定義的內容。這裡推薦兩個貼子,說的挺清楚的。



  為什麼在加載數據庫事務配置前,不能掃描Controller?這個我目前並不知道明細的原因,只大概知道是Spring設計規則問題,DispatherServlet中如果在數據庫事務配置加載前掃描了包含Controller在類的命名空間,結果就是事務並不具備事務能力。所以我們在DispatherServlet配置文件中會出現兩段掃描代碼:

  •    先只掃描Controller
<context:component-scan base-package="cn.wanmei.party" use-default-filters="false">
        <context:include-filter expression="org.springframework.web.bind.annotation.Controller" type="annotation"/>
    </context:component-scan>
  •     。。。。。掃描加載其它配置
  • 加載數據庫配置,由於事務的存在,這裡在掃描時需要去掉對於Service的掃描,避免二次重復掃描產生不可預期的結果。
<context:component-scan base-package="cn.wanmei.party">
        <context:exclude-filter expression="org.springframework.web.bind.annotation.RestController" type="annotation"/>
    </context:component-scan>
    <import resource="mybatis.xml"/>

   上面這種將幾乎所有配置全部寫在DispatherServlet配置文件中的做法有缺點:

  •    架空了原本為Application Context配置的root-context配置文件(只有一個shiro配置文件,不包含任何bean加載相關的內容)
  •    將原本屬於Application Context做的事情轉交給DispatherServlet,會造成掃描問題
  •    配置會顯得復雜,我個人的意見是DispatherServlet盡量只配置與Servlet自身相關的,而像數據庫配置最好放在root-context這個Application級別的配置中


   以上大部分都是在描述事務不生效的問題,那與我文前提到的Realm實現類中通過Autowired注解服務失敗有什麼關聯呢?之前提到了Application Context主要功能之一就是提供應用程序對於事務,數據層以及其它類實例的訪問,那麼在Realm實現類中提供類的注解實例當然是在職責范圍內,為此我們需要對配置文件做變更:

  •    root-context,增加包掃描,將數據庫配置轉移到進來
 <context:component-scan base-package="cn.wanmei.party">
    </context:component-scan>
     <import resource="mybatis.xml"/>
     <import resource="redis-context.xml"/>
    <import resource="spring-shiro-web.xml" /> 
  •     DispatherServlet:只加載與Servlet相關的配置,在掃描類配置上需要刪除對Service的掃描,避免二次掃描問題。
 <context:component-scan base-package="cn.wanmei.party">
         <context:exclude-filter expression="org.springframework.stereotype.Service" type="annotation"/>
    </context:component-scan>


  解決後:
  1:root-context飽滿了
  2:Application Conext 有活干了,事務呀什麼的應有的它都有了
  3:DispatherServlet的配置清爽了

  經過測試,事務正常,Realm中的注解正常,從此再也不需要使用文前提到的那兩種惡心的方式了。本文通過項目中事務不生效的問題,聯想到Realm實現類注解失敗與之存在關聯,最後通過實踐進一步證實推測,也進一步了解了Spring的上下文知識。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved