[英]Get database connection from a connection pool
我正在重构其他代码。 我注意到的一件事是关于系统如何从连接池获得连接的方式。
样品是这样的。 在每次调用服务方法时,系统都会在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
按如下方式配置:
<context-param>
<param-name>database.name</param-name>
<param-value>jdbc/mysqldb</param-value>
</context-param>
<listener>
<listener-class>com.example.Config</listener-class>
</listener>
您可以在servlet中获取它,如下所示( init()
或doXXX()
方法,您可以选择):
DataSource dataSource = Config.getInstance(getServletContext()).getDataSource();
然而,我会进一步重构它,JDBC代码最好放在它自己的类中,而不是放在servlet中。 查找DAO模式。
我刚刚做了一些测试,发现jndi的查找时间并不那么重。 这里约1秒内查找50.000次。
所以在很多情况下,我根本没有看到缓存DataSource的原因。
缓存问题是您最终可能会使用过时的DataSource,如果您更改了与数据源定义相关的任何内容,则会强制您重新启动应用程序。
我过去使用的方法是创建一个包含数据源的单例类
例如
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查找开销。
除此之外,还有一种名为Service Locator的设计模式,它基本上是一个单独的包含一个名为“service”的注册表,用于保存您的JNDI对象。
基本上,如果在注册表中找不到该对象,则该服务将从JNDI池中获取并在注册表中注册。 下一个调用只是从注册表中拉出对象。
希望这可以帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.