3 回答

TA貢獻1725條經驗 獲得超8個贊
問題不在于您的Spring注釋,而在于您的設計模式。您將不同的作用域和線程混合在一起:
單身人士
會話(或請求)
作業線程池
單身人士可以在任何地方使用,沒關系。但是,會話/請求范圍在附加到請求的線程之外不可用。
即使請求或會話不再存在,異步作業也可以運行,因此無法使用依賴于請求/會話的bean。同樣也沒有辦法知道,如果您正在另一個線程中運行作業,哪個線程是發起者請求(這意味著aop:proxy在這種情況下沒有幫助)。
我覺得你的代碼看起來像要作合同 ReportController,報表制作,UselessTask和ReportPage之間。有沒有辦法只使用一個簡單的類(POJO)來存儲UselessTask中的數據并在ReportController或ReportPage中讀取它,而不再使用ReportBuilder?

TA貢獻2039條經驗 獲得超8個贊
如果還有其他人堅持同一觀點,以下解決了我的問題。
在web.xml中
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
會話中組件
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
在pom.xml中
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.1</version>
</dependency>

TA貢獻1799條經驗 獲得超6個贊
原因
原因是使用多個線程。如Spring Guide中所述,請求對象在這些線程中不可用:
DispatcherServlet,RequestContextListener并且RequestContextFilter都做同樣的事情,即綁定HTTP請求對象添加到服務該請求的線程。這使得在請求鏈和會話范圍內的bean可以在調用鏈的更下游使用。
解決方案1
可以使請求對象可用于其他線程,但是它對系統有一些限制,這在所有項目中可能都不可行。我從在多線程Web應用程序中訪問請求范圍的Bean獲得了此解決方案:
我設法解決了這個問題。我開始使用SimpleAsyncTaskExecutor而不是WorkManagerTaskExecutor/ ThreadPoolExecutorFactoryBean。好處是SimpleAsyncTaskExecutor永遠不會重復使用線程。那只是解決方案的一半。解決方案的另一半是使用RequestContextFilter而不是RequestContextListener。RequestContextFilter(以及DispatcherServlet)具有一個threadContextInheritable屬性,該屬性基本上允許子線程繼承父上下文。
解決方案2
唯一的其他選擇是在請求線程內使用會話范圍的Bean。就我而言,這是不可能的,因為:
控制器方法用注釋@Async;
控制器方法將啟動批處理作業,該批處理作業將線程用于并行作業步驟。
- 3 回答
- 0 關注
- 908 瀏覽
添加回答
舉報