簡體   English   中英

訪問servlet外部的會話變量

[英]Accessing session variables outside servlet

我正在開發一個java webapp,我需要根據用戶登錄ID訪問數據庫中的記錄。我在成功登錄后在會話變量中設置登錄詳細信息。

我想做的就是這樣

從proj_recs中選擇*,其中user_id = user_id(來自會話)

現在我將用戶名作為參數傳遞,但我認為這不是一個好習慣。 有沒有更好的方法來訪問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;

}

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

您正在尋找的解決方案是Thread Local(google it)。 它允許您使用靜態方法訪問特定於線程的數據。

您可以開始閱讀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中,執行以下操作:

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();
    }
}

在您的數據層中,您可以通過執行以下操作來檢索用戶:

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

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

線程本地起初有點令人困惑,但是一旦你閱讀了這篇文章,你就會很快熟悉。

我想你可以輕松使用

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;

}

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

通過嚴格分離關注點,數據層應該與會話或請求無關。 但是您需要服務或數據層中的用戶名(來自您示例的user_id )。 最簡單的是有效地在控制器中收集它(控制器可以訪問請求和會話),將其傳遞給服務層,並將其轉發到數據層。

另一種方法(由Spring Security或Apache Shiro等安全框架使用)是在請求處理開始時將其存儲在線程存儲中,並在結束時(在過濾器中)仔細清理它。 然后,實用程序類的靜態方法可以將其提供給應用程序的任何部分。 但是每次使用實用程序類時,都會獲得對框架的依賴。 為了減少不必要的依賴,你可以擁有自己的Holder類,使用一個靜態方法來調用框架之一:依賴性僅限於holder類。

如果你使用Spring,還有第三種解決方案。 您可以使用具有aop代理的會話范圍bean,您可以在任何需要訪問您的變量的bean中注入。 感謝aop代理,您可以訪問當前會話中的數據,甚至可以訪問單個bean。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM