Struts 2中的ActionContext对当前请求是唯一的吗?

时间:2013-10-17 20:55:24

标签: java servlets struts2 thread-local actioncontext

我正在使用自定义拦截器创建新的数据库连接,并在执行操作之前将此连接设置为当前操作。之后,拦截器关闭连接。

我正在寻找一种方便的方法来与操作使用的其他类/静态方法(例如模型)共享此数据库连接。例如,我可以调用静态方法,如User.get( id )User.getEmail( id ),而不必分别将db连接传递给每个方法。

我可以通过执行以下操作将数据库连接设置为来自拦截器的ActionContext

ServletActionContext.getActionContext().put("db", db );

然后我可以从静态方法访问此数据库连接,例如:

public class User implements Model
{ 
   public static String getEmail(int id)
   {
      Connection db = 
         (Connection) ServletActionContext.getActionContext().get("db");
      //...
   }
}

我的问题是,是否会为每个给定的请求生成一个新的ActionContext,所以我可以确定每次都会使用一个新的数据库连接?例如,如果我有500人访问mysite.com/fooAction,我是否可以确定这500个请求中的每一个都生成一个唯一的ActionContext,并且每次调用User.getEmail()都只能访问给定的db连接请求?

感谢。

2 个答案:

答案 0 :(得分:3)

回答这个问题:

  

我的问题是,是否会为每个给定的人生成一个新的ActionContext   请求,所以我可以确保每个都使用一个新的数据库连接   时间?

是的。是的。参考是java-doc。它与Alfredo Osorio提供的类似,仅指2.3.x版本。

你能说出正在使用的struts2版本吗?

我无法找到任何使用

的版本
ServletActionContext.getActionContext()

但是签名是

ServletActionContext.getActionContext(javax.servlet.http.HttpServletRequest)

回答有关线程本地静态的comment,并且每个请求的ActionContext实例仍然是唯一的,因为执行

ActionContext.getContext()

在内部调用线程本地实例的get。

 actionContext.get()

您可能会发现以下post在这方面很有帮助。

然而,深入研究方法

ServletActionContext.getActionContext(javax.servlet.http.HttpServletRequest)

采用与使用线程本地不同的路由。

public static ActionContext getActionContext(HttpServletRequest req) {
    ValueStack vs = getValueStack(req);
    if (vs != null) {
        return new ActionContext(vs.getContext());
    } else {
        return null;
    }
}

public static ValueStack getValueStack(HttpServletRequest req) {
    return (ValueStack) req.getAttribute(STRUTS_VALUESTACK_KEY);
}

getActionContext

getValueStack

以下是一些其他参考资料(源代码)。

ValueStack

OgnlValueStack

ActionContext

以下帖子也可能有所帮助。

  1. will-a-new-actioncontext-and-valuestack-be-created-for-every-new-action-object

  2. struts2-actioncontext-and-valuestack

  3. 更新2:

    想要添加如上所述here(上面的链接1),如果涉及ActionChaining,则使用自己的拦截器堆栈和结果调用该操作。

    执行它的线程是相同的。

    复制值堆栈和参数。请参阅 - ActionChainResult #execute(ActionInvocation)。

    链调用完成后,将重置action-context的状态。 (参见DefaultActionProxy#execute())。

    部分信息:虽然在DefaultActionInvocation#init(ActionProxy)中设置了动作调用,但我无法确定它是否或在何处重置。

    来源:

    DefaultActionInvocation

    DefaultActionProxy

    DefaultActionProxyFactory

    ActionChainResult

    FilterDispatcher(Deprecated)

答案 1 :(得分:2)

  

我的问题是,是否会为每个给定的人生成一个新的ActionContext   请求,所以我可以确保每个都使用一个新的数据库连接   时间?

由于ActionContext使用ThreadLocal,因此它是线程安全的。 Struts 2为每个请求创建一个ActionContext,每个请求都有自己的线程。所以,是的,如果您创建一个新连接并将其存储在ActionContext中,则每个线程都将拥有自己的连接。但是我不建议你将连接存储在ActionContext中,因为这会将你联系到Struts 2,这不是一件好事,你的服务也不应该调用特定于web的类,因为它也会联系它们。

From Struts 2 Javadoc:

  

ActionContext是执行Action的上下文。每   context基本上是一个动作需要的对象的容器   像会话,参数,语言环境等执行

     

ActionContext是线程本地的,这意味着存储的值   ActionContext是每个线程唯一的。见   ActionContext.ActionContextThreadLocal类以获取更多信息。该   这样做的好处是您无需担心用户特定的问题   行动背景,你得到它:

     

ActionContext context = ActionContext.getContext();最后,因为   线程本地使用你不需要担心你的   动作线程安全。

ActionContext 摘录:

public class ActionContext implements Serializable {

    static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();
    ....
}