범위 '세션'이 현재 스레드에 대해 활성화되지 않았습니다. 불법 상태 예외:스레드 바인딩된 요청을 찾을 수 없습니다.
세션별로 고유한 컨트롤러가 있습니다.스프링 문서에 따르면 구현에는 두 가지 세부 사항이 있습니다.
초기 웹 구성
요청, 세션 및 글로벌 세션 수준(웹 범위 콩)에서 콩 범위를 지정하려면 콩을 정의하기 전에 몇 가지 사소한 초기 구성이 필요합니다.
저는 제 내추다습니가에 web.xml
설명서에 표시된 대로:
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
종속성으로서의 스코프 원두
HTTP 요청 범위 빈을 다른 빈에 주입하려면(예를 들어) 범위 빈 대신 AOP 프록시를 주입해야 합니다.
나는 콩에 주석을 달았습니다.@Scope
공는하를 proxyMode
아래와 같이:
@Controller
@Scope(value="session", proxyMode=ScopedProxyMode.TARGET_CLASS)
public class ReportBuilder implements Serializable {
...
...
}
문제
위의 구성에도 불구하고 다음과 같은 예외가 발생합니다.
기관.스프링 골조콩 공장콩 창조예외:이름이 'scopeTarget.reportBuilder'인 빈을 만드는 동안 오류가 발생했습니다. 현재 스레드에 대해 스코프 '세션'이 활성화되지 않았습니다. 싱글톤에서 이 빈을 참조하려면 이 빈에 대한 범위가 지정된 프록시를 정의하십시오. 중첩된 예외는 java.lang입니다.잘못된 상태 예외:스레드 바인딩된 요청을 찾을 수 없습니다.실제 웹 요청 외부의 요청 속성을 말하는 것입니까, 아니면 원래 수신 스레드 외부의 요청을 처리하는 것입니까?실제로 웹 요청 내에서 작업 중이고 여전히 이 메시지가 표시되는 경우 코드가 DispatcherServlet/DispatcherPortlet 외부에서 실행되고 있을 수 있습니다.이 경우 RequestContextListener 또는 RequestContextFilter를 사용하여 현재 요청을 표시합니다.
업데이트 1
아래는 나의 구성요소 스캔입니다.는 항있다이니습목에 과 같은 것이 .web.xml
:
<context-param>
<param-name>contextClass</param-name>
<param-value>
org.springframework.web.context.support.AnnotationConfigWebApplicationContext
</param-value>
</context-param>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>org.example.AppConfig</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
그리고 그고다은에 .AppConfig.java
:
@Configuration
@EnableAsync
@EnableCaching
@ComponentScan("org.example")
@ImportResource("classpath:applicationContext.xml")
public class AppConfig implements AsyncConfigurer {
...
...
}
업데이트 2
재현 가능한 테스트 케이스를 만들었습니다.이것은 훨씬 작은 프로젝트이기 때문에 차이점이 있지만 같은 오류가 발생합니다.파일이 꽤 많아서 제가 파일을 올렸습니다.tar.gz
메가 파일 업로드.
문제는 스프링 주석이 아니라 설계 패턴에 있습니다.다양한 범위와 스레드를 함께 사용할 수 있습니다.
- 싱글톤
- 세션(또는 요청)
- 스레드 풀의 작업
싱글톤은 어디서나 구매 가능합니다, 괜찮습니다.그러나 요청에 연결된 스레드 외부에서는 세션/요청 범위를 사용할 수 없습니다.
요청 또는 세션이 더 이상 존재하지 않는 경우에도 비동기 작업을 실행할 수 있으므로 요청/세션 종속 빈을 사용할 수 없습니다.또한 별도의 스레드에서 작업을 실행 중인 경우 어떤 스레드가 원본 요청인지 알 수 없습니다(이 경우 aop:proxy는 유용하지 않음을 의미함).
당신의 코드는 ReportController, ReportBuilder, DisuseTask, ReportPage 간의 계약을 원하는 것처럼 보입니다.쓸모없는 작업의 데이터를 저장하고 ReportController 또는 ReportPage에서 읽고 ReportBuilder를 더 이상 사용하지 않는 단순 클래스(POJO)를 사용하는 방법이 있습니까?
원인과 가능한 해결책에 대한 더 나은 개요를 제공하기 때문에 저는 제 자신의 질문에 답하고 있습니다.@Martin이 원인을 지목했기 때문에 저는 그에게 보너스를 수여했습니다.
원인
@Martin이 제안한 바와 같이 원인은 여러 스레드의 사용입니다.스프링 가이드에 언급된 바와 같이 요청 개체는 이러한 스레드에서 사용할 수 없습니다.
DispatcherServlet
,RequestContextListener
그리고.RequestContextFilter
모두 동일한 작업을 수행합니다. 즉, HTTP 요청 개체를 해당 요청을 처리하는 스레드에 바인딩합니다.이를 통해 요청 및 세션 범위가 지정된 빈을 콜 체인 아래에서 사용할 수 있습니다.
솔루션 1
요청 개체를 다른 스레드에서 사용할 수 있도록 만들 수 있지만 시스템에 몇 가지 제한이 적용되어 일부 프로젝트에서는 사용할 수 없습니다.멀티 스레드 웹 애플리케이션의 요청 범위 빈 액세스에서 이 솔루션을 얻었습니다.
저는 이 문제를 간신히 모면했습니다.사용하기 시작했습니다.
SimpleAsyncTaskExecutor
에WorkManagerTaskExecutor
/ThreadPoolExecutorFactoryBean
은 점은입니다.SimpleAsyncTaskExecutor
스레드를 다시 사용하지 않습니다.그것은 해결책의 절반에 불과합니다.해결책의 나머지 절반은 다음을 사용하는 것입니다.RequestContextFilter
에RequestContextListener
.RequestContextFilter
및 (뿐만아니라)▁(DispatcherServlet
)가 있습니다.threadContextInheritable
기본적으로 자식 스레드가 부모 컨텍스트를 상속할 수 있도록 허용하는 속성입니다.
솔루션 2
다른 유일한 옵션은 요청 스레드 내에서 세션 범위 빈을 사용하는 것입니다.저의 경우 다음과 같은 이유로 불가능했습니다.
- 컨트롤러 메소드에는 다음과 같은 주석이 달립니다.
@Async
; - 컨트롤러 방법은 병렬 작업 단계에 스레드를 사용하는 배치 작업을 시작합니다.
만약 다른 누군가가 같은 점을 고집한다면, 팔로우는 나의 문제를 해결했습니다.
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>
파일에 다음 코드를 추가하여 이 문제를 해결했습니다.
@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
XML 구성 -
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
위에서 우리는 Java 구성을 사용할 수 있습니다.
@Configuration
@WebListener
public class MyRequestContextListener extends RequestContextListener {
}
no-xml 구성으로 RequestContextListener를 추가하는 방법은 무엇입니까?
봄 버전 5.1.4를 사용하고 있습니다.릴리스 및 폼의 아래 변경 사항을 추가할 필요가 없습니다.
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.10</version>
</dependency>
Spring Web MVC, 즉 Spring Dispatcher Servlet 또는 Dispatcher Portlet에서 처리되는 요청 내에서 스코프 빈에 액세스하는 경우 특별한 설정이 필요하지 않습니다. Dispatcher Servlet 및 Dispatcher Portlet은 이미 모든 관련 상태를 노출합니다.
Spring MVC(Dispatch Servlet에서 처리되지 않음) 외부에서 실행 중인 경우에는RequestContextListener
뿐만 아니라.ContextLoaderListener
.
web.xml에 다음을 추가합니다.
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
그 범위에서 콩을 유지하기 위해 스프링에 세션을 제공할 것입니다.
업데이트 : 다른 답변에 따르면,@Controller
Spring MVC Context 내에 있을 때만 sense가 가능합니다. 따라서 @Controller는 코드에서 실제 목적을 수행하지 않습니다.그래도 세션 범위/요청 범위(특정 범위에서 콩을 주입하는 데 스프링 MVC/컨트롤러가 필요하지 않음)를 통해 어디든 콩을 주입할 수 있습니다.
업데이트 : RequestContextListener는 요청을 현재 스레드에만 표시합니다.
보고서 작성기 자동 배선이 두 곳에 있습니다.
1. ReportPage
Spring이 보고서 작성기를 올바르게 삽입한 것을 볼 수 있습니다. 아직 동일한 웹 스레드에 있기 때문입니다.저는 ReportPage에 ReportBuilder가 이렇게 삽입되었는지 확인하기 위해 당신의 코드 순서를 변경했습니다.
log.info("ReportBuilder name: {}", reportBuilder.getName());
reportController.getReportData();
저는 당신의 논리대로 로그가 뒤따라야 한다는 것을 알았습니다, 단지 디버깅 목적으로 추가했습니다.
2. UselessTasklet
예외가 발생했습니다. 이는 요청이 노출되지 않는 Spring Batch에서 생성된 다른 스레드이기 때문입니다.RequestContextListener
.
생성하고 주입하려면 다른 논리가 있어야 합니다.ReportBuilder
인스턴스(instance to Spring Batch)(May Spring Batch 매개변수 및 사용)Future<ReportBuilder>
나중에 참조할 수 있도록 반환할 수 있습니다.)
제 답변은 OP가 설명하는 일반적인 문제의 특별한 경우를 언급하지만, 누군가에게 도움이 될 경우를 대비해 추가하겠습니다.
을 할 때@EnableOAuth2Sso
봄이 오면 됩니다.OAuth2RestTemplate
응용 프로그램 컨텍스트에서 이 구성 요소는 스레드 바인딩 서블릿 관련 항목을 가정합니다.
내 코드에 자동 배선을 사용하는 예약된 비동기 메서드가 있습니다.RestTemplate
은 실않다지습니 안에서.DispatcherServlet
하지만 스프링은 주사를 놓고 있었습니다.OAuth2RestTemplate
OP가 설명하는 오류를 생성했습니다.
해결책은 이름을 기반으로 한 주입입니다.Java 구성에서 다음을 수행합니다.
@Bean
public RestTemplate pingRestTemplate() {
return new RestTemplate();
}
그리고 그것을 사용하는 클래스에서:
@Autowired
@Qualifier("pingRestTemplate")
private RestTemplate restTemplate;
Spring은 이 없는 Spring을 합니다.RestTemplate
.
https://stackoverflow.com/a/30640097/2569475
이 문제에 대해서는 위의 주어진 URL에서 내 답변을 확인하십시오.
실제 웹 요청 외부에서 요청 범위 빈 사용
내가 가지고 있었을 때 같은 오류가 있었습니다.@Order
필터 클래스의 주석입니다.비록 내가 필터를 통해 추가했지만.HttpSecurity
쇠사슬의
를 했습니다.@Order
그리고 그것은 성공하였다.
프로토타입을 제외한 기본 싱글톤 스코프와 다른 스코프가 필요한 빈에서 정의하기만 하면 됩니다.예:
<bean id="shoppingCart"
class="com.xxxxx.xxxx.ShoppingCartBean" scope="session">
<aop:scoped-proxy/>
</bean>
언급URL : https://stackoverflow.com/questions/21286675/scope-session-is-not-active-for-the-current-thread-illegalstateexception-no
'sourcetip' 카테고리의 다른 글
Google 문서와 유사한 라이브 업데이트를 수행하는 방법은 무엇입니까? (0) | 2023.07.27 |
---|---|
gradle bootRun을 사용하여 명령줄 속성을 추가하는 방법은 무엇입니까? (0) | 2023.07.27 |
추상 기본 클래스에서 @autowired 사용 (0) | 2023.07.22 |
gitam과 git apply의 차이점은 무엇입니까? (0) | 2023.07.22 |
Oracle에서 프로세스가 두 번 이상 실행되지 않도록 하는 가장 좋은 방법이 있습니까? (0) | 2023.07.22 |