(一)JNDI基础
一、简介
- 在Tomcat 4.1.27之后,在服务器上就直接增加了数据源的配置选项,直接在服务器上配置好数据源连接池即可。在J2EE服务器上保存着一个数据库的多个连接。每一个连接通过DataSource可以找到。DataSource被绑定在了JNDI树上(为每一个DataSource提供一个名字)客户端通过名称找到在JNDI树上绑定的DataSource,再由DataSource找到一个连接。如下图所示:
- 如果要想使用数据源的配置,则必须配置虚拟目录,因为此配置是在虚拟目录之上起作用的。需要注意的是,如果要想完成以上的功能,在Tomcat服务器上一定要有各个数据库的驱动程序。
二、连接池
常用的连接池:Tomcat-dbcp/C3P0/Proxool/阿里的durid
三、局部连接池第一种配置方法
3.1 连接池必须在虚拟目录上,所以需要以下操作
3.2 在server.xml中配置虚拟目录和连接池。
<Context path="/JNDITest" docBase="D:\workspace\JNDITest\WebContent" reloadable="true"> <Resource name="jdbc/mysql" type="javax.sql.DataSource" username="root" password="" url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC" driverClassName="com.mysql.jdbc.Driver" maxActive="50" maxIdle="20" maxWait="5000" /> </Context>
- 注意: mysql数据库的url记得加上serverTimezone=UTC 否则会报 Cannot create PoolableConnectionFactory 错误。
3.3 测试
index.jsp
<a href="<%=path%>/servlet/TestJNDI">测试JNDI</a>
TestJNDI.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 1、初始化名称查找上下文 Context context = new InitialContext(); // 2、通过JNDI名称找到DataSource,对名称进行定位java:comp/env是必须加的,后面跟的是DataSource名 DataSource dateSource = (DataSource) context.lookup("java:comp/env/jdbc/mysql"); Connection conn = dateSource.getConnection(); Statement stat = conn.createStatement(); int res = stat.executeUpdate("insert into users values(5,'test_user','test_password') "); if (res > 0) { System.out.println("新增成功"); } else { System.out.println("新增失败"); } } catch (Exception e) { e.printStackTrace(); } }
3.4 结果
- 缺陷:该配置方法的缺陷是我们需要修改tomcat的server.xml,但在开发环境中一般该server.xml是无法修改的,所以一般都用第二种配置方法。
四、 局部连接池第二种配置方法(最常用):在工程中配置
4.1 在WebContent目录下,新建一个文件夹 META-INF(eclipse/myeclipse一般自动生成,就不需要新建)
4.2 在META-INF目录下新建一个文件 context.xml,配置连接池。
<?xml version="1.0" encoding="UTF-8"?> <Context reloadable="true"> <Resource name="jdbc/mysql" type="javax.sql.DataSource" username="root" password="" url="jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC" driverClassName="com.mysql.jdbc.Driver" maxActive="50" maxIdle="20" maxWait="5000" /> </Context>
- 其中,path和docBase属性就不需要配了,因为该文件就是在本工程目录下。
4.3 将工程部署到Tomcat中运行,并测试
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { // 1、初始化名称查找上下文 Context context = new InitialContext(); // 2、通过JNDI名称找到DataSource,对名称进行定位java:comp/env是必须加的,后面跟的是DataSource名 DataSource dateSource = (DataSource) context.lookup("java:comp/env/jdbc/mysql"); Connection conn = dateSource.getConnection(); Statement stat = conn.createStatement(); int res = stat.executeUpdate("insert into users values(6,'test_user2','test_password2') "); if (res > 0) { System.out.println("新增成功"); } else { System.out.println("新增失败"); } } catch (Exception e) { e.printStackTrace(); } }
4.4 结果
五、JNDI缺陷
- 缺陷:jndi只能运行于WEB环境中,因为获取是的容器的环境。不能运行在main方法/SE环境。
- 解决方法:将Tomcat-dbcp/C3P0/Proxool/阿里的durid产生连接池的方式,用SE的代码来产生。
5.1:将连接池的jar拷到工程中。
5.2:改造jdbc获取连接的方法。
package servlet; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import javax.naming.Context; import javax.naming.InitialContext; import javax.sql.DataSource; import com.mchange.v2.c3p0.ComboPooledDataSource; public class DBUtil { private static final String DRIVER="com.mysql.jdbc.Driver"; private static final String USER="root"; private static final String PASSWD=""; private static final String URL="jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC"; private static ComboPooledDataSource dataSource=null; static{ try { Class.forName(DRIVER); Context context=new InitialContext(); dataSource=new ComboPooledDataSource(); dataSource.setMaxPoolSize(50); dataSource.setInitialPoolSize(20); dataSource.setJdbcUrl(URL); dataSource.setDriverClass(DRIVER); dataSource.setUser(USER); dataSource.setPassword(PASSWD); } catch (Exception e) { throw new RuntimeException("驱动包加载故障"); } } public static Connection getConn(){ Connection conn=null; try { conn= dataSource.getConnection(); } catch (SQLException e) { e.printStackTrace(); } return conn; } public static void main(String[] args) { for(int i=0;i<100;i++){ System.out.println(DBUtil.getConn()+"\t "+i); } } }
5.3:结果