1

我在过滤器中使用 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)

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

4

1 回答 1

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>

请参阅:请求、会话和全局会话范围

春天应该照顾所有的细节......

于 2012-11-12T21:21:51.450 回答