使用Spring RequestContextHolder时出现IllegalStateException

时间:2012-11-12 15:25:10

标签: java spring tomcat

我在过滤器中使用RequestContextHolder来记录一段数据,并希望稍后在POJO(通过Spring连接)中​​访问它。我得到一个例外,这表明我在这里做错了什么,会对这是什么的指导表示感谢。

过滤代码(在 doFilter()方法中,其日志记录确认它正在被调用):

RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
if (attrs == null)
{
    logger.info("Creating new ServletRequestAttributes");
    attrs = new ServletRequestAttributes(servletRequest);
}

attrs.setAttribute("my_attr", "hello there!", RequestAttributes.SCOPE_REQUEST);

RequestContextHolder.setRequestAttributes(attrs);

POJO代码:

RequestAttributes attrs = RequestContextHolder.getRequestAttributes();
if (attrs != null && attrs.getAttribute("my_attr", RequestAttributes.SCOPE_REQUEST) != null)
{
    String myAttr = (String) attrs.getAttribute("my_attr", RequestAttributes.SCOPE_REQUEST);
    logger.debug("Got it: ", myAttr);
}

我看到这个异常来自Tomcat:

java.lang.IllegalStateException: The request object has been recycled and is no longer associated with this facade
    at org.apache.catalina.connector.RequestFacade.getAttribute(RequestFacade.java:259)
    at org.springframework.web.context.request.ServletRequestAttributes.getAttribute(ServletRequestAttributes.java:98)
    at com.mycompany.MyClass(MyClass.java:50)

我确实想知道是否在过滤器中设置了“设置数据”,并且通过请求的实际工作“获取数据”可以在这里发挥作用,但不确定如何最好地适应它,如果它甚至是相关的?

1 个答案:

答案 0 :(得分:1)

错误可能是由于您正在使Spring维护一个不再有效的请求对象的线程本地句柄。由于采用了不同的方法,细节可能并不重要。

以下其中一项将负责正确设置和清除线程本地状态:DispatcherServletRequestContextListenerRequestContextFilter。你需要弄清楚哪一个对你的应用程序如何使用Spring最有意义。您的过滤器和POJO代码不需要直接使用RequestContextHolder之类的类。应该发生的是您为要访问的属性声明一个代理的,请求范围的bean:

<bean id="myAttr" scope="request">
  <aop:scoped-proxy/>
</bean>

然后,为您的POJO声明bean及其对请求范围的bean的依赖:

<bean id="myPojo">
  <property name="myAttr" ref="myAttr"/>
</bean>

请参阅:Request, session, and global session scopes

Spring 应该处理所有细节......