【问题标题】:Caching InitialContext and DataSource in a Java EE web-app在 Java EE Web 应用程序中缓存 InitialContext 和 DataSource
【发布时间】:2011-02-19 00:38:49
【问题描述】:

在下面的 JDBC/MySQL 连接器/J 参考中,它建议我们缓存 InitialContext 和 Datasource 的实例。将其设为私有静态实例会解决缓存问题吗?不应该关心线程安全(如果有的话)吗?为网络应用(Restlet + glassfish/Java EE + mysql)缓存这个的最佳“位置”是什么?

有一个 GenericDAO 类,可以说是数据访问类的根。那么只有静态实例真的能解决问题吗?它会迫使某些方法成为我们不想要的静态方法。建议??

谢谢!

public void doSomething() throws Exception {
/*
* Create a JNDI Initial context to be able to
* lookup the DataSource
**
In production-level code, this should be cached as
* an instance or static variable, as it can
* be quite expensive to create a JNDI context.
**
Note: This code only works when you are using servlets
* or EJBs in a Java EE application server. If you are
* using connection pooling in standalone Java code, you
* will have to create/configure datasources using whatever
* mechanisms your particular connection pooling library
* provides.
*/
InitialContext ctx = new InitialContext();
/*
* Lookup the DataSource, which will be backed by a pool
* that the application server provides. DataSource instances
* are also a good candidate for caching as an instance
* variable, as JNDI lookups can be expensive as well.
*/
DataSource ds =
(DataSource)ctx.lookup("java:comp/env/jdbc/MySQLDB");

/*
*Remaining code here...
*/
    }

【问题讨论】:

  • 我对 Restlet 部分一无所知,但在普通的 Servlet 环境中,您会为此使用 ServletContextListener。 Example here。如果您熟悉 Servlet,这可能会带来新的见解。
  • @BalusC:似乎可行...我会在实施后发布确认!自从我开始编写网络应用程序以来已经有一段时间了——我完全忘记了 ServletContext!非常感谢。
  • 由于 InitialContexts 不是线程安全的(docs.oracle.com/javase/7/docs/api/javax/naming/…),我猜缓存必须小心。我不确定 DataSource 是否有同样的问题(似乎没有)

标签: jdbc jakarta-ee restlet-2.0 connector-j


【解决方案1】:

如果您使用的是 JAX-RS,那么您可以使用 @Context 注释。

例如

@Context
private ServletContext context;

@GET
@Path("whatevers")
public List<Whatever> getWhatevers() {
    DataSource dataSource = Config.getInstance(context).getDataSource();
    // ...
}

但是,如果您的 Restlet 环境也支持 @Resource 注释,您可以好好利用它。

@Resource(mappedName="jdbc/MySQLDB")
private DataSource dataSource

这反过来在技术上更好地放置在一个 EJB 中,然后您通过 @EJB 在您的 Web 服务中注入该 EJB。

@Stateless
public class WhateverDAO {

    @Resource(mappedName="jdbc/MySQLDB")
    private DataSource dataSource

    public List<Whatever> list() {
        // ...
    }

}

与

@EJB
private WhateverDAO whateverDAO;

@GET
@Path("whatevers")
public List<Whatever> getWhatevers() {
    return whateverDAO.list();
}

【讨论】:

    【解决方案2】:

    跟进 BalusC 的 link,我可以确认我们可以在使用 Restlet 时做同样的事情。但是,根据the example 中的代码来获取您作为参数传入 ServletContext 的配置实例。 Restlet 就像“另一个”框架,它使用 Servlet 作为适配器来配置自身。因此,将 ServletContext 作为参数从代码中的其他位置传递会很棘手(Restlet 使用它自己的 Context 对象,该对象在概念上类似于 ServletContext)

    就我而言,返回缓存数据源的静态方法似乎“足够干净”,但可能还有其他设计/组织方法。

    【讨论】:

    • 值得一提的是,在标准 JAX-RS API 上,您可以通过 @Context 注释在 webservice 类中注入 ServletContext。
    • @BalusC:这很有趣……我知道这个注释,但不知道如何使用它。谷歌搜索也没有多大帮助。有什么建议/链接吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多