之前,我们在学JSP时曾提到“JSP四种范围对象的大小依次是pageContext
JNDI的全称是Java Naming and Directory Interface(JAVA命名与目录接口),是一种将对象和名字绑定的技术。使用JNDI,应用程序可以通过资源名字来获得相应的对象、服务或目录。我们以使用JNDI访问Tomcat为例,来详细介绍一下JNDI的使用。
Servers项目中有一个context.xml文件(即Tomcat目录中的context.xml文件),此文件中的信息就可以被所有Web项目共享。
我们在context.xml中,加入以下代码:
其中Context是context.xml文件的根标签。Environment可以用来设置JNDI的元素:name表示当前Environment元素的名字,相当于唯一标示符;value表示name对应的内容值,即name与value构成了一组键值对;type表示value中的内容类型。此Environment的作用就类似于String jndiName =“jndiValue”。之后,在该tomcat中的任意一个Web项目里,均可以获取到此Environment的value值了。
JNDI的演示项目名是StudentManagerWithJNDIPool,该项目是建立在StudentManagerWithPage项目基础之上:
在index.jsp中加入以下代码,用于获取context.xml中的Environment值:
index.jsp
Context和InitialContext都属于javax.naming包。Context对象的lookup()方法可以根据名字查询到context.xml中Environment的value值,并且lookup()中需要使用"java:comp/env/"作为固定前缀。lookup()的返回值为Object,需要强转为需要的类型。
运行结果如图所示。
图运行结果
可以发现,使用JNDI定义的变量(通过context.xml中的Environment元素定义),可以在任意一个Web项目中使用(同一个Tomcat中)。
2连接池与数据源
我们之前一直采用传统的JDBC方式访问数据库。而每次使用JDBC访问数据库时,都需要建立连接和关闭连接,但连接的建立和关闭又是非常耗费系统资源的。为了解决这个问题,我们可以使用数据库连接池技术。
(1)连接池
数据库连接池可以分配、管理及释放数据库连接,它可以使得应用程序重复的使用一个已有的数据库连接,而不再是重新建立一个。而且,如果某一个数据库连接超过了最大空闲时间,数据库连接池也会自动将该连接释放掉,从而明显提高数据库的性能及安全。
数据库连接池的工作原理是,在初始化时连接池会创建一定数量的数据库连接,并将这些连接放在数据库连接池之中。连接的数量不会小于用户设置的最小值;而如果应用程序的连接请求数量大于用户设置的最大值,那么大于最大值的那些请求会被加入在等待队列之中,只有当某些应用程序把正在使用的连接使用完毕并归还给连接池时,在等待队列的请求才会获取到连接。
(2)数据源
数据源(javax.sql.DataSource,简称DataSource)中包含了连接池的具体实现,并且可以管理连接池。应用程序可以从直接数据源中获得数据库连接。
实际开发中,有多种可供使用的数据源:Tomcat内置数据源(Apache dbcp)、DBCP数据源、C3P0数据源、自定义数据源等。
Tomcat内置数据源
Tomcat内置数据源也称为Apache dbcp。我们可以使用JNDI从Tomcat中直接获取该数据源对象。
现在就来讲解如何在项目中使用Apache dbcp:
和JNDI一样,首先需要在Servers项目的context.xml中增加元素。不同的是,配置数据源需要使用Resource元素,而不是Environment,如下,
context.xml
Resource元素的属性介绍如表所示。
表Resource元素属性
与JNDI不同的是:配置数据库连接池,除了要在context.xml中配置以外,还需要在Web应用的web.xml中配置元素:
web.xml
元素中的可以用来对配置的资源进行描述说明,其他的子元素值只需要和context.xml中的相关值保持一致即可,具体如下:
值对应于中的name值;
值对应于中的type值;
值对应于中的auth值。
此外,还需要注意采用数据源方式访问数据库,数据源是由Tomcat创建并维护的,因此还需要把JDBC的驱动包(ojdbc6.jar)复制到Tomcat的lib目录下。
最后,我们修改StudentManagerWithJNDIPool项目的DBUtil.java文件,将传统的JDBC方式替换为数据源方式来访问数据库,如下,
运行此项目,运行结果与之前的完全相同。不同的是,使用连接池的方式来访问数据库,可以提高项目的性能。
我们总结一下,使用Apache dbcp实现数据库连接的步骤:
1配置context.xml文件:在Tomcat的context.xml中加入元素及相关属性
2配置web.xml文件:在项目的web.xml中元素及相关属性
3给Tomcat的lib目录加入相应的数据库驱动
4编码查找数据源(使用lookup()方法),实现连接数据库
DBCP数据源
DBCP(DataBase connection pool,数据库连接池),是Apache组织提供的一个开源连接池。以下是使用DBCP的具体方法:
使用DBCP前,需要先在项目中导入以下JAR包:
其中,commons-dbcp.jar中包含了DBCP的2个核心类:BasicDataSource和BasicDataSourceFactory。我们可以根据这两个类,设计出两种不同的DBCP实现方式:基于BasicDataSource的手动编码方式,以及基于BasicDataSourceFactory的配置文件方式。
a.基于BasicDataSource的手动编码方式
BasicDataSource是DataSource(数据源)接口的实现类,包含了设置数据源对象的具体方法,如表所示。
可以先通过BasicDataSource构造方法产生一个数据源对象,再手动给数据源对象设置属性值,最后返回该数据源对象,如下:
以上,就是使用DBCP数据源获取连接对象(connection)的方法。有了连接对象connection以后,就可以通过createStatement()方法产生Statement对象(或者通过prepareStatement()方法产生PreparedStatement等),进而执行数据库访问
b.基于BasicDataSourceFactory的配置文件方式
BasicDataSourceFactory可以通过createDataSource()方法,从配置文件(Properties文件)中读取数据库配置信息,并获取数据库连接对象。createDataSource()方法的完整定义如下:
以下,是通过BasicDataSourceFactory方式获取DBCP数据源对象的具体代码:
创建并编写配置文件
创建配置文件:
在src上点击鼠标右键àNewàFileà输入dbcpconfig.propertiesàFinish,如图所示。
图新建File
图创建properties文件
编写配置文件:dbcpconfig.properties
获取数据源对象
C3P0数据源
C3P0性能优越并易于扩展,是目前最流行、使用最广的数据源之一。著名的Hibernate、Spring等开源框架,使用的都是该数据源。C3P0实现了DataSource数据源接口,并提供了一个重要的实现类:ComboPooledDataSource,该类的常见方法如表所示。
表ComboPooledDataSource常见方法
可以发现,DBCP和C3P0的实现类都提供了3类方法:(1)设置数据库信息的方法;(2)初始化连接池的方法();(3)获取连接对象的getConnection()方法。
与DBCP类似,在使用C3P0前,需要先导入以下JAR包,如表所示。
表 C3P0所需JAR文件
此外,C3P0也提供了手动编码及配置文件两种方式来获取数据源对象,具体如下:
a.基于无参构造方法ComboPooledDataSource()的手动编码方式
通过手动编码方式获取c3p0对象,依赖于无参构造方法ComboPooledDataSource(),如下:
b.基于有参构造方法ComboPooledDataSource(String configName)的配置文件方式
通过配置文件方式获取c3p0对象,依赖于有参构造方法ComboPooledDataSource(String configName),如下:
创建并编写配置文件
与DBCP不同,c3p0使用的是XML格式的配置文件,并且配置文件必须满足:存放于src根目录下;文件名是c3p0-config.xml。
在src下创建并编写一个c3p0-config.xml文件,如下:
c3p0-config.xml
可以发现,中包含了两套配置数据源信息:和。其中,配置的是默认信息,而是自定义配置。一个中可以包含任意数量的,当包含一个或多个时,用户可以通过有参构造方法ComboPooledDataSource(String configName)中的参数configName来指定实际使用哪一个。此外,如果某些信息在中没有配置,那么c3p0就会自动使用中的相应信息,例如user、password等。
获取数据源对象
有参构造方法ComboPooledDataSource(String configName)会在c3p0-config.xml文件中的所有name="…">里,寻找name=configName的配置信息。
以下代码,通过ComboPooledDataSource("lanqiao"),指定使用c3p0-config.xml中name="lanqiao">的配置信息,再根据配置信息创建数据源对象。
在实际开发中,经常会遇到DBCP或C3P0,因此可以将二者封装到一个工具类中,如下:
领取专属 10元无门槛券
私享最新 技术干货