2012-05-06 3 views
4

스프링 3을 사용 중입니다. 컨트롤러가 요청을 받으면 서비스 빈에 @Async이라는 주석이 붙은 someMethod() 메서드에 컨트롤을 전달한 다음 반환합니다. 내가 someMethod()의 HttpSession 객체에 액세스 할 때 나는이 예외를받을원래 수신 스레드 외부에서 HttpSession에 액세스합니다.

java.lang.IllegalStateException: No thread-bound request found: Are you 
referring to request attributes outside of an actual web request, or 
processing a request outside of the originally receiving thread? If you are 
actually operating within a web request and still receive this message, your 
code is probably running outside of DispatcherServlet/DispatcherPortlet: In 
this case, use RequestContextListener or 
RequestContextFilter to expose the current request. 

나는이 문제를 어떻게 해결할 수 있습니까?

답변

3

HttpSession 개체 자체는 여러 스레드에서 사용할 수 있지만 이 아니라은 스레드로부터 안전하므로 동기화되어야합니다. 그러나 봄은 약간의 특별한 마술을하고있다. session- 범위의 콩이있을 때. 즉, 아래에 ThreadLocal을 사용하여 현재 세션을 스레드와 바인드합니다.

정확한 시나리오는 무엇인지 모르겠지만 분명히 Spring은 다른 스레드에있는 동안 HttpSessionThreadLocal에서 검색하려고합니다. 분명히 실패합니다.

해결책은 간단합니다. @Async 메서드에서 필요한 세션 속성을 추출하고 직접 전달하십시오. 이것은 훨씬 더 좋은 디자인입니다 - HttpSession 객체를 전달하는 것을 피하십시오. 테스트가 더 어려워지고 코드가 미래에 재사용 될 가능성이 훨씬 적기 때문입니다.

+0

당신의 솔루션은 간단하고 훌륭하지만 컨트롤러 레이어뿐만 아니라 비즈니스 및 데이터 레이어에서도 사용자 별 데이터를 저장할 수있는 곳은 어디입니까? 아니면 메서드 인수를 통해 이러한 데이터를 전달해야합니까? 후자가 유일한 해결책입니까? –

+0

@OleksandrBondarenko : 그것에 대해 생각해보십시오 - 서비스 계층의 세션에 액세스하면 숨겨진 커플 링 및 명시 적이지 않은 종속성이 도입됩니다. 인수를 통해이 모든 데이터를 전달하는 것은 (아마도 일부 객체에 배치하여) 실제로 가장 좋은 방법입니다. –

+0

하지만 세션에서 설정하는 것은 어떻습니까? 요청 이외에 HttpSession에 액세스 할 수 있다는 주장을 뒷받침 할 수있는 설명서가 있습니까? – mjaggard