晚上好!我有一个登录注销的网络应用程序,您可以在其中购买或出售一些产品。我的查询存储在一个名为DBManager
的java类中,它只有从servlet调用的静态方法(我不能使用JSP,因为在这个项目中我们不能使用它们,教授给我们这个约束)。
所以这就是问题:我曾经用ServletContextListener
来管理连接。在contextInitialized
我设置了连接,在contextDestroyed
我关闭它。使用ServletContext.setAttribute(Connection)
存储属性“连接”。
如何通过java类(而不是servlet)DBManager
获取此参数?我必须在servlet中使用getServletContext()
获取对象,而不是将其作为属性传递,或者有一个快捷方式来避免它?
答案 0 :(得分:4)
在方法contextInitialized中打开连接并在contextDestroyed中关闭它是一个糟糕的解决方案。想象一下,您的网站同时有两个访问者。他们现在将共享相同的数据库连接。如果您使用事务处理,则最终会出现意外结果,其中一个访问者提交由另一个访问者执行的事务的中间状态。如果连接丢失(可能是因为重新启动了DB服务器),您的应用程序将失败,因为它不会重新建立连接(除非您有一个非常智能的JDBC驱动程序)。
一个非常昂贵但安全的解决方案是为每个数据库操作打开一个新连接,并在操作后立即再次关闭它。
要获得完美的解决方案,您可以使用某种连接池。每当您需要执行数据库语句(或一系列语句)时,您都会从池中借用一个连接。完成后,您将返回到池的连接。大多数池实现负责验证(检查连接是否仍然“活动”),多个线程(不同访问者同时发送的不同HTTP请求)可以并行执行语句。
如果您想使用此解决方案,可能Commons DbUtils库适合您:http://commons.apache.org/dbutils/
或者您查看Java应用程序服务器或servlet引擎(Tomcat?)的文档,以查看它提供的内置数据库连接池功能。
答案 1 :(得分:1)
您可以更改类以接收连接,而不是任意获取连接。这允许您传递任何连接实例(如果您需要从另一个数据库获取数据会发生什么?)。
此外,假设代码将移植到桌面。使用这种方法,您可以重复使用DAO而无需任何更改。
class DBManager {
private Connection connection;
public DBManager(Connection connection) {
this.connection = connection;
}
//methods that will use the connection
}
答案 2 :(得分:0)
在您的HttpServlet
doPost
或doGet
方法中,您可以致电getServletContext()
。
ServletContext sc = getServletContext();
DataSource ds = (DataSource) sc.getAttribute("ds");
Connection conn = ds.getConnection();
servlet可以通过名称将对象属性绑定到上下文中。绑定到上下文中的任何属性都可用于属于同一Web应用程序的任何其他servlet。
Context属性是创建它们的JVM的LOCAL。这可以防止ServletContext属性成为分布式容器中的共享内存。当需要在分布式环境中运行的servlet之间共享信息时,应将信息放入会话,存储在数据库中或设置在Enterprise JavaBeans组件中。