从连接池获取数据库连接

我正在重构其他代码。 我注意到的一件事是关于系统如何从连接池获得连接的方式。

样品是这样的。 在每次调用服务方法时,系统都会在JNDI上为数据源进行上下文查找。

public class CheckinServlet extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { //Obtain Connection InitialContext initialContext = new InitialContext(); javax.sql.DataSource ds = (javax.sql.DataSource) initialContext .lookup("jdbc/mysqldb"); java.sql.Connection conn = ds.getConnection(); //business logic //redirect } finally { conn.close(); } } } 

我确实认为每次这样做都会影响性能。 我正在考虑另外一种方法来解决如何从连接池中检索连接。

我正在考虑使用servlet的init()方法,但我认为这不是最佳的。

ServletContextListener执行一次,而不是每次在许多servlet的init()中执行。 contextInitialized()方法在webapp启动期间只执行一次。

 public class Config implements ServletContextListener { private static final String ATTRIBUTE_NAME = "config"; private DataSource dataSource; @Override public void contextInitialized(ServletContextEvent event) { ServletContext servletContext = event.getServletContext(); String databaseName = servletContext.getInitParameter("database.name"); try { dataSource = (DataSource) new InitialContext().lookup(databaseName); } catch (NamingException e) { throw new RuntimeException("Config failed: datasource not found", e); } servletContext.setAttribute(ATTRIBUTE_NAME, this); } @Override public void contextDestroyed(ServletContextEvent event) { // NOOP. } public DataSource getDataSource() { return dataSource; } public static Config getInstance(ServletContext servletContext) { return (Config) servletContext.getAttribute(ATTRIBUTE_NAME); } } 

web.xml按如下方式配置:

  database.name jdbc/mysqldb   com.example.Config  

您可以在servlet中获取它,如下所示( init()doXXX()方法,您可以选择):

 DataSource dataSource = Config.getInstance(getServletContext()).getDataSource(); 

然而,我会进一步重构它,最好将JDBC代码放在它自己的类中,而不是放在servlet中。 查找DAO模式。

我过去使用的方法是创建一个包含数据源的单例类

例如

 public class DatabaseConnectionManager { DataSource ds; public void init() { InitialContext initialContext = new InitialContext(); ds = (javax.sql.DataSource)initialContext.lookup("jdbc/mysqldb"); } public Connection getConnection() { if(ds == null) init(); return ds.getConnection(); } } 

这意味着您拥有对数据源的共享引用,从而消除了jndi查找开销。

我刚刚做了一些测试,发现jndi查找时间并不那么重。 这里约1秒内查找50.000次。

所以在很多情况下,我根本没有看到缓存DataSource的原因。

缓存问题是您最终可能会遇到过时的DataSource,如果您更改了与数据源定义相关的任何内容,则会强制您重新启动应用程序。

除此之外,还有一种名为Service Locator的设计模式,它基本上是一个单独的包含一个名为“service”的注册表,用于保存您的JNDI对象。

基本上,如果在注册表中找不到该对象,则该服务将从JNDI池中获取并在注册表中注册。 下一个调用只是从注册表中拉出对象。

希望这可以帮助。