2014-06-20 156 views
5

我正在處理一個java webapp,我需要根據用戶登錄id從數據庫訪問記錄。成功登錄後,在會話變量中設置登錄詳細信息。在servlet外部訪問會話變量

我想要做的就是從proj_recs這樣的

選擇*其中USER_ID = USER_ID(從Session)

現在,我通過用戶名作爲參數,但我相信這不是一個好實踐。有沒有更好的方式訪問servlet之外的會話變量?

的Servlet

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
     // TODO Auto-generated method stub 

     User user = (User) request.getSession().getAttribute("userInfo"); 

     System.out.println(user); 

     if(user != null){ 
      Gson gson = new Gson(); 
      returnJsonResponse(response,gson.toJson(user)); 
      return; 
     } 
} 

在數據層包

public Accrual getAccruals(String accrualID,String userid) throws AccrualNotFoundException{ 

    String sql = Select * from db_acc where acc_id= accrualID and user_id=userid; 

} 

的問題是我要修改我的用戶id的所有方法。有沒有一種方法可以將用戶的詳細信息設置爲某個靜態類,並在不修改方法簽名的情況下訪問應用程序中所需的詳細信息?但我相信靜態類是不同用戶請求之間的共享。

+0

你想在哪裏訪問會話變量?在客戶端? JSP? – fajarkoe

+0

你能詳細說明一下使用代碼示例嗎? –

+0

在應用程序的數據層 – SRK

回答

2

您正在尋找的解決方案是線程本地(谷歌它)。它允許您使用靜態方法訪問線程特定的數據。

您可以開始閱讀http://veerasundar.com/blog/2010/11/java-thread-local-how-to-use-and-code-sample/。使用實例從那裏,你需要創建:

public class MyThreadLocal { 

    public static final ThreadLocal userThreadLocal = new ThreadLocal(); 

    public static void set(User user) { 
     userThreadLocal.set(user); 
    } 

    public static void unset() { 
     userThreadLocal.remove(); 
    } 

    public static User get() { 
     return userThreadLocal.get(); 
    } 
} 
在servlet

,這樣做:

public void dataLayerMethod(ExistingParameters parameters) { 
    User user = MyThreadLocal.get(); 
} 

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    User user = (User) request.getSession().getAttribute("userInfo"); 
    MyThreadLocal.set(user); 
    try { 
     // call data layer 
    } finally { 
     MyThreadLocal.unset(); 
    } 
} 
在數據層

,您可以通過這個檢索用戶

請注意,您不需要更改數據層的方法簽名。

線程本地開頭有點令人困惑,但一旦閱讀文章,您會很快熟悉。

0

您可以隨時從servlet中的會話中獲取用戶標識並將其傳遞到數據層,在數據層中直接使用會話沒有意義。你提取你的對象,並將降壓傳遞給下一層。在數據層中使用HTTP特定對象實際上是不好的做法。

0

由於嚴格區分顧慮,數據層應該與會話或請求無關。但是您需要服務或數據層的用戶名(例如user_id)。最簡單的方法是有效地將其收集到控制器中(控制器可以訪問請求和會話),將其傳遞到服務層,並將其轉發到數據層。

一個替代方案(用於像Spring Security或Apache Shiro這樣的安全框架)是在請求處理開始時將其存儲在線程存儲中,並在結束時(在過濾器中)仔細清除它。然後,實用程序類的靜態方法可以將其提供給應用程序的任何部分。但是,每次使用實用程序類時都會對該框架產生依賴性。 要減少不必要的依賴性,可以使用調用框架的靜態方法來擁有自己的Holder類:依賴性僅限於持有者類。

如果您使用Spring,還有第三種解決方案。您可以擁有一個會話範圍的bean,使用aop代理,您可以在需要訪問變量的任何bean中注入。由於aop代理,您將可以訪問當前會話中的數據,即使是來自單例bean。

在我自己的應用程序中,我使用第一種方法在簡單情況下(少數類)和第三種方法,當我想避免在許多方法中反覆重複相同的參數。

1

我覺得你可以輕鬆地使用

SecurityUtils.getSubject().getSession().getAttribute("userInfo");

所以沒有必要改變簽名。這樣,您可以使用shiros內置的實用程序,而不是依靠自己的邏輯和概率。

public Accrual getAccruals(String accrualID) throws AccrualNotFoundException{ 
    User user = (User) SecurityUtils.getSubject().getSession().getAttribute("userInfo"); 
    String userid= user.getUserId(); 
    String sql = Select * from db_acc where acc_id= accrualID and user_id=userid; 

}