Java Struts 2在其仍在拦截器中时重置动作实例

Java Struts 2在其仍在拦截器中时重置动作实例,java,struts2,Java,Struts2,看起来,如果我对同一个操作发出了两个并发请求,例如mysite.com/fooAction,那么struts会重置第一个操作的实例,而该实例可能仍在拦截器中 例如,如果我的拦截器中有以下代码: action = ai.getAction(); String result = ai.invoke(); logger.debug("Orig action : " + action.toString() +" , now : " + ai.getAction().toString() ); 如果

看起来,如果我对同一个操作发出了两个并发请求,例如mysite.com/fooAction,那么struts会重置第一个操作的实例,而该实例可能仍在拦截器中

例如,如果我的拦截器中有以下代码:

action =  ai.getAction();
String result = ai.invoke();
logger.debug("Orig action : " + action.toString()  +" , now : " + ai.getAction().toString() );
如果我对同一个操作同时发出两个请求(例如使用javascript),则行:

logger.debug("Orig action : " + action.toString()  +" , now : " + ai.getAction().toString() );
生成两个不同的
toString()
代码,表明原始操作与上一个操作位于不同的实例中

这是一个大问题,因为现在,如果我在拦截器中有任何代码,它会在我的操作中设置某些内容,例如执行以下操作:

MyAction action =  (MyAction) ai.getAction();
Auth auth = new Auth ( action.getSession() );
action.setAuth(auth);
action.setCookiesMap( Util.getAllCookies() );
String result = ai.invoke();
那么就不能保证我在我的操作中设置的所有东西实际上都会被传递到正确的实例。也就是说,当调用
ai.invoke()
时,它实际上可能调用一个完全不同的操作实例,该实例上有不同的cookie或其他数据集。这可能导致不同的用户可以访问彼此的数据


所有这些我都对吗?如果有,这个问题有解决办法吗?因为这似乎完全违背了拦截器的目的

如果我正确理解了问题-如果提出了单个请求,那么打印操作引用的结果表明它们是相同的

但是,如果同时发出请求,则操作引用不同

如果确实如此,那么很可能是因为定制

默认情况下,初始化“action”引用的唯一位置,在这种情况下,只能在同一类中的init(ActionProxy)中调用“action”引用,并且只能调用“action”引用一次,并且只能从中调用“action”引用

因此,对于ActionInvocation的给定实例,操作将(应该)始终相同

更新2():

虽然我并没有实际运行代码,但我确实进行了检查

Json拦截器是有状态的。但是,它必须是无状态的。这解释了为什么并发请求导致操作实例不同

根据拦截器文件:

拦截器是拦截器后面的无状态类 模式,如javax.servlet.Filter和AOP语言中所示。

拦截器必须是无状态的,并且不能假定新实例将 为每个请求或操作创建

据我了解:

第一个请求在拦截器中分配本地操作实例并进入睡眠状态

第二个请求重新分配操作实例(拦截器是单实例)并进入睡眠状态

第一个请求被唤醒并继续执行。再次返回并比较操作实例后,将在拦截器中从第二个请求中看到该操作实例,并再次从ActionInvocation中获取当前请求的操作实例。他们确实会有所不同。这解释了观察到的行为。此外,即使未调用ai.invoke()或ai.invokeActionOnly(),它也应该是可见的


另外,“servletConfig”拦截器已经与其他拦截器一起包含在“defaultStack”中。如果我正确理解了问题,您可以找到详细信息

——如果提出了单个请求,那么打印操作引用的结果表明它们是相同的

但是,如果同时发出请求,则操作引用不同

如果确实如此,那么很可能是因为定制

默认情况下,初始化“action”引用的唯一位置,在这种情况下,只能在同一类中的init(ActionProxy)中调用“action”引用,并且只能调用“action”引用一次,并且只能从中调用“action”引用

因此,对于ActionInvocation的给定实例,操作将(应该)始终相同

更新2():

虽然我并没有实际运行代码,但我确实进行了检查

Json拦截器是有状态的。但是,它必须是无状态的。这解释了为什么并发请求导致操作实例不同

根据拦截器文件:

拦截器是拦截器后面的无状态类 模式,如javax.servlet.Filter和AOP语言中所示。

拦截器必须是无状态的,并且不能假定新实例将 为每个请求或操作创建

据我了解:

第一个请求在拦截器中分配本地操作实例并进入睡眠状态

第二个请求重新分配操作实例(拦截器是单实例)并进入睡眠状态

第一个请求被唤醒并继续执行。再次返回并比较操作实例后,将在拦截器中从第二个请求中看到该操作实例,并再次从ActionInvocation中获取当前请求的操作实例。他们确实会有所不同。这解释了观察到的行为。此外,即使未调用ai.invoke()或ai.invokeActionOnly(),它也应该是可见的


另外,“servletConfig”拦截器已经与其他拦截器一起包含在“defaultStack”中。您可以找到详细信息

请参见我的编辑,其中我提供了一个示例项目来测试此行为,它显示通过
ai.getAction()
获得的操作引用与通过
ai.invokeActionOnly()获得的引用不同
如果同时多次请求同一个操作类。@ClickUpvote我已经更新了答案。简单地说,拦截器应该是无状态的。你是对的。为了清楚起见,我将第一个
操作
存储为类字段,而不是
intercept()
方法的局部变量。所以,是b