我正在使用JSP开发一个小型Web应用程序,这个应用程序需要一个数据库连接,我提供了一个servlet。
问题是,我希望服务器上的所有文件都可以使用这个类来访问数据库而不必每次都创建一个新连接,实际上在每个文件中我都会创建一个新的Database
对象每次都会建立一个新的连接。
有没有办法避免这种情况,可能会声明一个全局对象,例如session
和request
,这样它只会初始化一次,然后被我所有的JSP文件使用?
由于
答案 0 :(得分:4)
你为什么要这样做?这两种解决方案都是错误的方法。
这是一个坏主意,因为数据库连接不是线程安全的。创建全局对象会降低应用程序的吞吐量,因为每个用户都必须共享连接。
更好的解决方案是拥有一个由应用服务器维护的连接池。执行JNDI查找以检查池中的连接,在尽可能最窄的范围内使用它,并关闭该方法范围内的连接。
您的应用会更好地扩展,不会冒线程安全。
答案 1 :(得分:2)
您不需要全局变量,您需要一个适用于您的上下文的功能,您的应用程序将使用该功能。所以你需要使用JNDI,在Tomcat网页中你有一个如何做,它很好地解释和易于实现。最好的问候。
http://tomcat.apache.org/tomcat-7.0-doc/jndi-datasource-examples-howto.html
答案 2 :(得分:0)
您似乎在谈论直接使用JSP文件中的数据库连接,不是吗?嗯,这不是一个理论上正确的解决方案,因为在关注点分离原则之后,您的视图 - 您的JSP文件 - 根本不应该对数据库或数据访问有任何了解。检查MVC模式的任何描述,例如这非常明显; - ):
但是,如果你想获取shorcut并让你的视图知道你的数据库,在我看来,你有两个选项,它们都涉及JNDI查找之前在你的appplication中定义的数据源为Marcelo Tataje已经说过了。
关于如何在Tomcat上定义基于连接池的JNDI数据源:
http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html
在同一页面中,您可以看到如何使用此连接池直接从您的JSP发出查询(在我看来再次非常不可取)
<%@ taglib uri="http://java.sun.com/jsp/jstl/sql" prefix="sql" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<sql:query var="rs" dataSource="jdbc/TestDB">
select id, foo, bar from testdata
</sql:query>
<html>
<head>
<title>DB Test</title>
</head>
<body>
<h2>Results</h2>
<c:forEach var="row" items="${rs.rows}">
Foo ${row.foo}<br/>
Bar ${row.bar}<br/>
</c:forEach>
</body>
</html>
Is java.sql.Connection thread safe?
另一个稍微好一点的解决方案是,在你的java代码中,JNDI从你的上下文监听器中查找这样的数据源:
public void contextInitialized(ServletContextEvent contextEvent) {
// JNDI Datasource lookup
InitialContext context = new InitialContext();
DataSource dataSource = (DataSource) context
.lookup("jdbc/DataSource");
// Storing datasource in application context
contextEvent.getServletContext().setAttribute("datasource",dataSource);
}
并且在任何servlet之后使用该存储的数据源来获取您需要的数据库连接,如此
((DataSource)contextEvent.getServletContext().getAttribute("datasource")).getConnection()
请不要直接使用Connection类。这是非常原始和过时的。如今,在严肃的工作环境中没有人处理这样的连接。如果您执行AmitG提议的操作,您将获得所有并发访问共享的唯一连接。看看为什么这不是要走的路