2012-04-17 32 views
9

我不確定如何在這裏標題的標題,因爲我不確定如何去尋找答案。Java中是否有請求上下文?

我有一個處理請求的java servlet引擎。假設我們有doGet請求:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    //set up user data 

    //do whatever the user requested 
    SomeClass c = new SomeClass(); 
    c.doSomething(); 
} 

現在,在doSomething中,我希望能夠訪問哪個用戶提出請求。現在,我通過創建一個Java對象並將它傳遞到哪裏,我需要做的是:

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 
    //set up user data 
    MyUserObj userObj = new MyUserObj(); 
    userObj.setId('123'); 

    //do whatever the user requested 
    SomeClass c = new SomeClass(userObj); 
    c.doSomething(); 
} 

通過這樣做,我有機會獲得MyUserObj的實例,它可以沿着如果需要,可以進一步通過。

這感覺馬虎。在asp.net MVC3中(我目前正在學習它,在我開始學習java之後開始學習,但發現這非常方便,所以讓我重新思考我是如何在java中進行的),例如,我可以存儲當前項目像這樣的線程:HttpContext.Current.Items.Add("myId", "123")。然後可以在其他函數中使用HttpContext,而不必傳遞對象。

是否有在Java中的方式來設置每個請求一些變量(或甚至設置MyUserObject稍後訪問)而不經過對象通過作爲參數?

如果這是一種常見的已經回答的問題隨時給我指出正確的方向,因爲我不知道如何句話吧。

+0

我自由地編輯了你的標題。請驗證它是否是一個好的 – Bozho 2012-04-17 18:48:51

+0

我只是明確地傳遞它,隱式狀態和依賴關係對可維護性不利。像Spring這樣的框架應該明確地幫助刪除一些樣板和混亂。 – millimoose 2012-04-17 18:48:54

+0

如果你理解我的問題,那麼我相信你的標題編輯比我原來的標題更好:) – Two13 2012-04-17 18:55:49

回答

19

在servlet API中沒有,但你可以輕鬆製作自己的。 (如彈簧-MVC一些框架,支柱提供這樣的功能)

只需使用一個public static ThreadLocal來存儲和檢索的對象。你甚至可以存儲HttpServletRequest本身在ThreadLocal中,並使用其setAttribute()/getAttribute()方法,或者你可以存儲一個ThreadLocal Map,是不可知的Servlet API。一個重要的提示是你應該在請求之後清理threadlocal(例如使用Filter)。

另請注意,將對象作爲參數傳遞被認爲是一種更好的做法,因爲您通常會將其從Web層傳遞到服務層,而服務層不應依賴於與Web相關的對象,如HttpContext

如果您認爲它是好的將它們存儲在一個線程局部,而不是圍繞它們傳遞:

public class RequestContext { 
    private static ThreadLocal<Map<Object, Object>> attributes = new ThreadLocal<>(); 
    public static void initialize() { 
     attributes.set(new HashMap<Map<Object, Object>>()); 
    } 
    public static void cleanup() { 
     attributes.set(null); 
    } 
    public static <T> T getAttribute(Object key) { 
     return (T) attributes.get().get(key); 
    } 
    public static void setAttribute(Object key, Object value) { 
     attributes.get().put(key, value); 
    } 
} 

並有必要的過濾器:

@WebFilter(urlPatterns="/") 
public class RequestContextFilter implements Filter { 
    public void doFilter(..) { 
     RequestContext.initialize(); 
     try { 
      chain.doFilter(request, response); 
     } finally { 
      RequestContext.cleanup(); 
     } 
    } 
} 
+2

什麼關於'ServletRequest.setAttribute'? – 2012-04-17 18:43:57

+2

然後您必須通過請求。我認爲這不是OP想要的。我添加它作爲選項,這仍然需要threadlocal,雖然 – Bozho 2012-04-17 18:45:13

+0

啊,好點,沒有類似的'HttpContext.Current'。 – 2012-04-17 18:47:22

4

您可以將一個對象到當前請求setAttribute。此API主要用於內部路由,但只要您爲屬性名稱使用適當的名稱空間,也可以用於您自己的目的。

+0

我不會然後必須通過ServletRequest對象作爲參數嗎? – Two13 2012-04-17 18:54:23

+0

你會的。但是,如果您在開始時傳遞請求,則可以避免傳遞其他與請求相關的對象。 – ataylor 2012-04-17 19:02:21

相關問題