2012-02-19 47 views
2

我真的厭倦了這個問題,找不到最好的做法。讓我清楚的問題用一個例子:在自定義類文件中訪問Java Web的HttpServletRequest/Response對象

我有這樣一個靜態方法:

public class AppError { 
    public static void systemError(string errorMsg) { //Like "Can't connect to DB" 
     HttpServletRequest request = ?????????? "HOW TO ACCESS?"; 
     request.setAttribute("Error", errorMsg); 
     request.getRequestDispatcher("/error.jsp").forward(request, response(????????)); 
    } 
} 

正如你可以看到我需要訪問請求和響應對象,我不希望傳遞的HttpServletRequest /響應通過參數,因爲這意味着通過它AppError.systemError調用的地方,這是很多地方:讀/寫文件,cookie和用戶操作,數據庫操作等...

我以爲我找到了解決方案,ThreadLocal,我在過濾器中使用它,並保存請求和響應對象,但接着Filter.Destroy()方法釋放ThreadLocal變量通過ThreadLocal.remove()方法在調試模式下測試時不會被調用。這意味着該線程可能永遠不會被處理。

ServletContextListerner不是一個解決方案,因爲我找不到方法來訪問ServletContext對象中的請求和響應對象。我期望像ServletContext.getRequest()這樣的方法,但沒有。

我也在使用JSF,但JSF的問題是FacesContext在自定義分類中也無法訪問。另外,JSF的加載時間比偵聽器晚,所以如果我使用FacesContext來獲取請求和響應對象,則不能在偵聽器中使用我的錯誤系統。

那麼這裏的最佳做法是什麼?我的意思是這是一個明顯的問題,我不能解決這個問題。

順便說一句,錯誤的方法是一個例子,還有其他地方,我需要訪問請求和響應對象。

回答

4

原則上,沒有任何理由說明爲什麼正確設置的Filter不能與線程本地存儲(TLS)結合使用。

關鍵見解是要清除TLS在Filter#Destroy()的方法,但在主濾波鏈之後的最後子句:

@WebFilter(filterName="requestTLSFilter") 
public class RequestTLSFilter extends Filter { 

    private static final ThreadLocal<ServletRequest> THREAD_LOCAL = new ThreadLocal<ServletRequest>(); 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { 
     try { 
      THREAD_LOCAL.put(request); 
      chain.doFilter(request, response); 
     } finally { 
      THREAD_LOCAL.remove(); 
     } 
    } 

    // Other methods  
} 

對於JSF,FacesContext.getCurrentInstance()是隨處可得。 JSF並不知道誰在調用它,但它只能在調用Facelets servlet之後在調用鏈中進行編碼。

還有另外一種選擇。如果您的容器具有的Java容器授權合同(JACC)的支持,那麼下面讓你的當前請求,以及:

HttpServletRequest request = (HttpServletRequest) PolicyContext.getContext("javax.servlet.http.HttpServletRequest"); 
+0

我不知道我可以使用嘗試,最後像與FilterChain,感謝那想法Arjan Tijms它完全解決了問題! – Seregwethrin 2012-02-19 15:29:25

相關問題