Struts 2重置动作实例,而它仍处于拦截器中 [英] Struts 2 resetting action instance while its still in interceptor

查看:81
本文介绍了Struts 2重置动作实例,而它仍处于拦截器中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

It seems that if I have two concurrent requests being made to the same action, e.g mysite.com/fooAction, then struts resets the first action's instance while that instance may still be in the interceptor.

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

E.g, if I have the following code in my interceptor:

action =  ai.getAction();
String result = ai.invoke();
logger.debug("Orig action : " + action.toString()  +" , now : " + ai.getAction().toString() );

如果我对同一个动作发出两个并发请求(例如使用javascript),那么行:

And if I make two concurrent requests to the same action (e.g using javascript), then the line:

logger.debug("Orig action : " + action.toString()  +" , now : " + ai.getAction().toString() );

生成两个不同的 toString()代码,显示原始操作与上一个操作的实例不同。

produces two different toString() codes, showing that the original action was in a different instance than the last action.

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

This is a big problem, because now, if I had any code in the interceptor, which was setting certain things on my action, e.g doing the following:

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或其他数据集。这可能会导致不同的用户被访问彼此的数据。

then there is no guarantee that all those things which I've set on my action are in fact going to be passed to the correct instance. I.e, when ai.invoke() is called, it may in fact call a completely different instance of the action, which has different cookies or other data set on it. This could result in different users being given access to each other's data.

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

Am I correct in all of this? If so, is there a solution to this problem? Because this seems to completely defeat the purpose of interceptors.

推荐答案

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

If I understand the question correctly - If a single request is made, then the result of printing the action references indicate that they are same.

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

However if concurrent requests are made, then the action references differ.

如果确实如此,那么它可能是由于自定义。

If this is indeed so, then its likely due to customizations.

默认情况下,只有在 DefaultActionInvocation位于createAction中,而后者仅在同一个类中的init(ActionProxy)中调用,而后者应该只调用一次,并且从 DefaultActionProxy的prepare(),它仅从 DefaultActionProxyFactory的createActionProxy()

By default, the only place where the 'action' reference is initialized in case of DefaultActionInvocation is in createAction which in turn is invoked only in init(ActionProxy) in the same class and which in turn is supposed to be invoked only once and is done from prepare() of DefaultActionProxy which in turn is only invoked from createActionProxy() of DefaultActionProxyFactory.

同样如此在ActionInvocation的给定实例中,操作将(应该)始终相同。

As such for a given instance of ActionInvocation the action would (should) always be the same.

更新2 关于示例s2项目):

虽然我实际上没有运行代码,但我确实去了通过它。

While I did not actually run the code, I did go through it.

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

The Json interceptor is stateful. However it is required to be stateless. This explains why concurrent requests result in the action instances being different.

根据拦截器文档这里


拦截器是一个无状态类,它遵循拦截器
模式,如javax.servlet.Filter和AOP语言中所见。

...

An interceptor is a stateless class that follows the interceptor pattern, as found in javax.servlet.Filter and in AOP languages.
...

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

Interceptors must be stateless and not assume that a new instance will be created for each request or Action.

根据我的理解:

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

The first request assigns the local Action instance in the interceptor and goes to sleep.

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

The second request re-assigns the Action instance (interceptor being singleton) and also goes to sleep.

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

The first request wakes up and continues with the execution. Upon returning and comparing the action instances again, sees the Action instance in the interceptor from the second request and fetches the action instance for the current request from the ActionInvocation again. They will indeed be different. This explains the observed behaviour. Also, it should be visible even if ai.invoke() or ai.invokeActionOnly() is not called.

此外,'servletConfig'拦截器已包含在'' defaultStack'以及其他一些人。您可以在此处找到详细信息

Also the 'servletConfig' interceptor is already included in the 'defaultStack' along with a bunch of others. You can find the details here

这篇关于Struts 2重置动作实例,而它仍处于拦截器中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆