0

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

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

我可以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()只会访问给定请求唯一的数据库连接?

谢谢。

4

2 回答 2

3

要回答这个问题:

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

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

能说下用的是什么struts2版本吗?

我找不到任何使用的版本

ServletActionContext.getActionContext()

但是签名是

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

要回答关于线程本地是静态的评论并且 ActionContext 实例仍然是每个请求唯一的,因为这样做

ActionContext.getContext()

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

 actionContext.get()

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

但是要深入研究,该方法

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);
}

获取操作上下文

获取值堆栈

下面是一些额外的参考资料(源代码)。

价值栈

OgnlValueStack

动作上下文

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

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

  2. struts2-actioncontext-and-valuestack

更新 2:

想要添加这里提到的(上面的链接 1),在涉及ActionChaining的情况下,将使用自己的拦截器堆栈和结果调用该操作。

但是,执行它的线程是相同的。

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

一旦链调用完成,动作上下文的状态就会被重置。(参见 DefaultActionProxy#execute() )。

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

资料来源:

默认操作调用

DefaultActionProxy

DefaultActionProxyFactory

动作链结果

FilterDispatcher(已弃用)

于 2013-11-03T17:09:17.407 回答
2

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

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

来自 Struts 2 Javadoc:

ActionContext 是执行 Action 的上下文。每个上下文基本上都是一个操作执行所需的对象容器,例如会话、参数、语言环境等。

ActionContext 是线程本地的,这意味着存储在 ActionContext 中的值对于每个线程都是唯一的。有关详细信息,请参阅 ActionContext.ActionContextThreadLocal 类。这样做的好处是您无需担心用户特定的操作上下文,您只需了解它:

ActionContext 上下文 = ActionContext.getContext(); 最后,由于线程本地使用,您无需担心使您的操作线程安全。

动作上下文摘录:

public class ActionContext implements Serializable {

    static ThreadLocal<ActionContext> actionContext = new ThreadLocal<ActionContext>();
    ....
}
于 2013-10-17T21:06:06.490 回答