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

时间:2013-11-03 17:46:23

标签: java struts2

似乎如果我对同一个动作发出两个并发请求,例如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或其他数据集。这可能导致不同的用户被访问彼此的数据。

我在所有这些方面都是正确的吗?如果是这样,是否有解决此问题的方法?因为这似乎完全打败了拦截器的目的。

1 个答案:

答案 0 :(得分:1)

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

但是,如果发出并发请求,则操作引用会有所不同。

如果确实如此,则可能是由于自定义。

默认情况下,在DefaultActionInvocation is in createAction的情况下初始化'action'引用的唯一位置,而prepare() of DefaultActionProxy仅在同一个类中的init(ActionProxy)中调用,而且应该仅调用它一次,从createActionProxy() of DefaultActionProxyFactory完成,而Regarding the example s2 project仅从here调用。

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

更新2 here):

虽然我实际上没有运行代码,但我确实经历过。

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

根据拦截器文档{{3}}:

  

拦截器是跟随拦截器的无状态类   模式,可以在javax.servlet.Filter和AOP语言中找到   ...

     

拦截器必须是无状态的,不要假设新实例会   为每个请求或操作创建。

据我所知:

第一个请求在拦截器中分配本地Action实例并进入休眠状态。

第二个请求重新分配Action实例(拦截器是单例)并且也进入休眠状态。

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

'servletConfig'拦截器也已包含在'defaultStack'中,还包含其他一些拦截器。您可以找到详细信息{{3}}