1

似乎如果我对同一个操作(例如 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 或其他数据集。这可能导致不同的用户被授予访问彼此数据的权限。

我在这一切中都是正确的吗?如果是这样,是否有解决此问题的方法?因为这似乎完全违背了拦截器的目的。

4

1 回答 1

1

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

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

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

默认情况下,在DefaultActionInvocation 的情况下初始化“动作”引用的唯一位置是在 createAction中,而 createAction 又仅在同一类中的 init(ActionProxy) 中调用,而后者又应该只被调用一次并完成来自 DefaultActionProxy 的prepare() ,而后者又只能从DefaultActionProxyFactory 的 createActionProxy()调用。

因此,对于给定的 ActionInvocation 实例,动作将(应该)总是相同的。

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

虽然我没有真正运行代码,但我确实完成了它。

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

根据此处的拦截器文档:

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

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

据我了解:

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

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

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

此外,“servletConfig”拦截器和其他一些拦截器已经包含在“defaultStack”中。你可以在这里找到详细信息

于 2013-11-03T22:38:21.190 回答