我应该如何在基于 servlet 的应用程序中连接到 JDBC 数据库/数据源?

Posted

技术标签:

【中文标题】我应该如何在基于 servlet 的应用程序中连接到 JDBC 数据库/数据源?【英文标题】:How should I connect to JDBC database / datasource in a servlet based application? 【发布时间】:2022-01-04 02:31:04 【问题描述】:

我有一个外部 mysql 服务器,它已设置好并且工作正常。我在 Eclipse 中创建了一个数据库连接,可以在 Data Source Explorer 选项卡中查看数据库。

现在,我有一个需要访问该数据库的 servlet。我该怎么做?有没有办法引用在数据源浏览器中创建的数据库连接,还是我必须定义所有内容两次?

另外,打开连接的最佳方式是什么?我已经包含了mysql-connector-java-5.1.11-bin.jar 文件,并且我发现了两种可行的方法:

MysqlDataSource d = new MysqlDataSource();
d.setUser("user");
d.setPassword("pass");
d.setServerName("hostname.com");
d.setDatabaseName("db");
Connection c = d.getConnection();

Connection c = DriverManager.getConnection("jdbc:mysql://hostname.com/db","user","pass");

两者都不是最优的,因为首先,它们都使用硬编码的字符串来表示所有内容。这是一个 Java EE Web 应用项目,那么有没有放置连接数据的好地方?或者有没有办法放弃所有这些,只使用数据源浏览器中的连接?

【问题讨论】:

【参考方案1】:

您可以在将 WAR 部署到的任何应用服务器中设置数据源,并使用 JNDI 获取对它的引用。或者,您可以将 WAR 打包到 EAR 中,并在 EAR 的 data-sources.xml 文件中定义数据源(并使用 JNDI 获取对它的引用)。

【讨论】:

【参考方案2】:

一种常见的做法是将其配置为相关servlet container 中的DataSource。它将为您提供连接池设施,这将大大提高性能。还有一种常见的做法是将原始设置外部化到放置在类路径中的某些配置文件中。

如果您使用 Tomcat 作为 servletcontainer,您需要根据其 JNDI documentation 配置数据源。你会看到有几种方法。最简单的方法是在动态 Web 项目的 Web 内容中创建一个 /META-INF/context.xml(需要明确的是,/META-INF 与 Web 应用的 /WEB-INF 处于同一级别)并用以下内容填充它:

<?xml version="1.0" encoding="UTF-8"?>

<Context>
    <Resource
        name="jdbc/db" type="javax.sql.DataSource"
        maxActive="100" maxIdle="30" maxWait="10000" 
        url="jdbc:mysql://hostname.com/db"
        driverClassName="com.mysql.jdbc.Driver"
        username="user" password="pass"
    />
</Context>

这大致意味着Tomcat服务器应该创建一个JNDI名称为jdbc/db的数据源,活动连接最多100个,空闲连接最多30个,等待时间最长10000毫秒应该从您的应用程序返回一个连接(实际上:由您的应用程序关闭,因此您的应用程序在获取连接和关闭连接之间有 10 秒的时间)。设置的剩余部分应该对您来说足够熟悉和不言自明;这些是 JDBC 设置。

最后在您的网络项目中,编辑文件/WEB-INF/web.xml 以添加以下条目:

<resource-env-ref>
    <resource-env-ref-name>jdbc/db</resource-env-ref-name>
    <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
</resource-env-ref>

这大致意味着网络应用程序应该使用名称为jdbc/db的服务器提供的数据源。

然后将您的连接管理器更改为以下内容:

private DataSource dataSource;

public Database(String jndiname) 
    try 
        dataSource = (DataSource) new InitialContext().lookup("java:comp/env/" + jndiname);
     catch (NamingException e) 
        // Handle error that it's not configured in JNDI.
        throw new IllegalStateException(jndiname + " is missing in JNDI!", e);
    


public Connection getConnection() 
    return dataSource.getConnection();

..并将所有Class.forName(driver) 调用替换为new Database("jdbc/db"),并将所有DriverManager.getConnection() 调用替换为database.getConnection()。如有必要,您可以从某个配置文件 (Properties file?) 中获取值 jdbc/db

或者,通过@Resource 注释在容器管理的工件中注入DataSource,例如@WebServlet servlet 类:

@Resource(name="jdbc/db")
private DataSource dataSource;

应该是这样的。只需使用上述更改部署您的 Web 应用程序并运行它。不要忘记将数据库 JDBC 驱动程序放在 Tomcat/lib 中,或者将其路径添加到 Tomcat/conf/catalina.propertiesshared.loader 属性中,因为加载 JDBC 驱动程序的责任现在从 web 应用程序转移到了服务器。如需更多提示和其他基本 JDBC/JNDI 示例,您可能会发现 this article 也很有用。

另见:

How to install JDBC driver in Eclipse web project without facing java.lang.ClassNotFoundexception Where do I have to place the JDBC driver for Tomcat's connection pool? Is it safe to use a static java.sql.Connection instance in a multithreaded system? Show JDBC ResultSet in html in JSP page using MVC and DAO pattern How to retrieve and display images from a database in a JSP page?

【讨论】:

这看起来很有帮助。还有两个问题。 1:不知道是不是我这样,还是正常,但是没有tomcat/lib目录,在common/lib、server/lib、shared/lib下有几个lib目录。我的罐子应该放进哪个?问题 2:这会处理此处设置的连接池吗?每次使用后我应该在 getConnection() 返回的连接上调用 close() 吗? 1) 您显然使用的是 6~8 年前的 Tomcat 5.x。如果可以(强烈推荐)升级到 Tomcat 6.0 或获取 Tomcat 5.x 的/shared/lib。 2)是的,它将处理连接池。是的,您应该始终在finally 中致电close()。连接池实现本身会担心关闭或释放。还要检查最后提到的链接的最后一章。 @BalusC 虽然帖子有点旧,但我有一个问题。有没有办法让密码加密?在 context.xml 中,密码是明文,所以无论如何要将数据源创建与 Eclipse 中的 Web 应用程序集成? 对于tomcat 7,应该是MySQL Datasourcejdbc/dbjavax.sql.DataSource Container

以上是关于我应该如何在基于 servlet 的应用程序中连接到 JDBC 数据库/数据源?的主要内容,如果未能解决你的问题,请参考以下文章

如何连接 Derby 数据库和 Servlet?

如何在基于 servlet 的 Web 应用程序中运行后台任务?

如何在基于servlet的Web应用程序中运行后台任务?

在基于 servlet 的应用程序中放置以及如何读取配置资源文件?

关于 servlet 应用程序中的连接池的一些问题

Servlet和JDBC如何配合使用请给一个例子?