我在过滤器中使用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)
我确实想知道是否在过滤器中设置了“设置数据”,并且通过请求的实际工作“获取数据”可以在这里发挥作用,但不确定如何最好地适应它,如果它甚至是相关的?
答案 0 :(得分:1)
错误可能是由于您正在使Spring维护一个不再有效的请求对象的线程本地句柄。由于采用了不同的方法,细节可能并不重要。
以下其中一项将负责正确设置和清除线程本地状态:DispatcherServlet
,RequestContextListener
或RequestContextFilter
。你需要弄清楚哪一个对你的应用程序如何使用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 应该处理所有细节......