环境:tomcat6.0+Maven
要使用数据源就要知道数据源的由来:在java开发使用jdbc都要经历这四步
①加载数据库驱动程序:(Class.forName(“数据库驱动类”);)
②连接数据库(Connection con = DriverManager.getConnection();)
③操作数据库(PreparedStatement stat = con.prepareStatement(sql);
stat.executeQuery();)
④关闭数据库,释放连接(con.close();)
其中就第三步我们是个性化的,1,2,4步都是重复性的。就需要一个解决办法来减去重复性的劳动–>用一个连接池来管理数据库链接。当需要使用时就去这个池子里取,当不用了在放回池子,就不用耗费大量资源去创建和关闭连接了。这个池子就是数据源。
在Tomcat 4.1.27之后,在服务器上就直接增加了数据源的配置选项,直接在服务器上配置好数据源连接池即可。在J2EE服务器上保存着一个数据库的多个连接。每一个连接通过DataSource可以找到。DataSource被绑定在了JNDI树上(为每一个DataSource提供一个名字)客户端通过名称找到在JNDI树上绑定的DataSource,再由DataSource找到一个连接。如下图所示:
<Resource
name="jdbc/oracle"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="lead_oams"
password="p"
driverClassName="oracle.jdbc.driver.OracleDriver"
url="jdbc:oracle:thin:@192.168.1.229:1521:lead"/>
<Resource
name="jdbc/mysql"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://192.168.1.144:3306/leadtest?useUnicode=true&characterEncoding=utf-8"/>
<Resource
name="jdbc/sqlserver"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="sa"
password="passw0rd" driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver" url="jdbc:sqlserver://192.168.1.51:1433;DatabaseName=demo"/>
<Resource
name="jdbc/DB2"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="root"
driverClassName="com.ibm.db2.jcc.DB2Driver"
url="jdbc:db2://10.137.23.130:50000/ntsq"/>
2.1在eclips开发工具这个前置服务Server下对应Tomcat的配置文件中配置。这种方式对在eclips里面Run As Server方式启动项目时使用
2.2 在tomcat目录conf/下对应文件修改。这种配置是用于部署到tomcat/webapps目录下的工程起作用
2.3 如何配置?操作步骤。
不管上面的那种方式修改。修改的文件一样,配置的内容也是一样的。首先都是要在applicationContext.xml中引入jndi数据源。为比较,我这里把常用的一般数据源也拿过来一起比较:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
<property name="initialSize" value="${initialSize}">property>
<property name="maxActive" value="${maxActive}">property>
<property name="maxIdle" value="${maxIdle}">property>
<property name="minIdle" value="${minIdle}">property>
<property name="maxWait" value="${maxWait}">property>
bean>
替换为jndi数据源:
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/dbpoolmysql">
在eclips的Server对应tomcat或者本地对应tomcat/conf目录下的server.xml找到工程的Context节点,添加一个私有数据源(注意,这里如果配置到context.xml文件的<Context>节点下,则变成全局的jndi数据源,即第三种范围配置。)
<Context docBase="WebApp" path="/WebApp" reloadable="true" source="org.eclipse.jst.jee.server:WebApp">
"jdbc/dbpoolmysql"
scope="Shareable"
type="javax.sql.DataSource"
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
url="jdbc:mysql://localhost:3306/test"
driverClassName ="com.mysql.jdbc.Driver"
username="root"
password="root"
/>
Context>
对应位置如下图:
第一种方式-在context.xml
节点中配置。(纠正一下~这个不是单个数据源配置,而是全局数据源的配置方式。是第三中jndi全局配置的一种)
第二种方式-在server.xml 的
节点中配置
优点:重用性,可控性
缺点:配置相对第三种方法要繁琐一点,每个工程都得配
b.配置全局JNDI数据源,应用到单个应用.
这种就是
这样的jndi不用配置了,哪个项目需要引入,只要在自己的项目中引入就可以了,即用第二种情况的第二步即可
第二种分为两步配置:
第一步, 找到Tomcat的server.xml中GlobalNamingResources节点,在节点下加一个全局数据源。这个就是做一次,其他项目在引入就只要第二步就行了。这里我说的是一开始还没有配置的时候最全的配置步骤。
"jdbc/mysql"
scope="Shareable"
type="javax.sql.DataSource"
factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
url="jdbc:mysql://localhost:3306/test"
driverClassName ="com.mysql.jdbc.Driver"
username="root"
password="root"
/>
第二步:同样在本server.xml中找到要应用此JNDI数据源的工程Context节点(在文本最下面几行里找到),增加对全局数据源的引用ResourceLink。这里注意一个映射关系要知道—applicationContext.xml中的name要和server.xml中引入的ResourceLink中的name一样。然后ResourceLink中的global要和GlobalNamingResources引入的全局jnid的name一样。这样应用就会由applicationContext.xml中的数据源找到本项目引入的name,得到对应的global的名字,进而找到了全局jndi。
<Context docBase="WebApp" path="/WebApp" reloadable="true">
<ResourceLink global="jdbc/mysql" name="jdbc/dbpoolmysql" type="javax.sql.DataSource" />
Context>
我把整个server.xml贴出来更直观来看:
<Server port="8006" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
<Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>
<Listener className="org.apache.catalina.core.JasperListener"/>
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>
<GlobalNamingResources>
<Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
<Resource
name="jdbc/mysql"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username="root"
password="root"
driverClassName="com.mysql.jdbc.Driver"/>
GlobalNamingResources>
<Service name="Catalina">
<Connector connectionTimeout="20000" port="8081" protocol="HTTP/1.1" redirectPort="8443"/>
<Connector port="8010" protocol="AJP/1.3" redirectPort="8443"/>
<Engine defaultHost="localhost" name="Catalina">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
Realm>
<Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log." suffix=".txt"/>
<Context docBase="springQuartzReadFile" path="/springQuarztDemo" reloadable="true" source="org.eclipse.jst.jee.server:springQuartzReadFile">
<ResourceLink global="jdbc/mysql" name="jdbc/dbpoolmysql" type="javax.sql.DataSource"/>
Context>
Host>
Engine>
Service>
Server>
c.配置全局JNDI数据源,应用到所有Tomcat下部署的应用。
这里的全局的效果是只要你的项目启动用的是这个tomcat,只要在applicationContext.xml中对应jndi名字对应上就可以直接启动成功。数据源就连接上了。不需要对tomcat做任何操作。
上面第一第二种配置都是基于之前没有配置过的情况下,且不共存,你只能选择三种中的一种。
第三种也是分为两步。第一步和第二种的第一步一样。在server.xml中的GlobalNamingResources标签中引入全局jndi数据源,不用多说了。
第二步是把第二种的引入到server.xml的对应应用上的
换到Context.xml的
标签下即可,如下图:
以上就是数据源的全部配置。这里还有一个点就是:java:comp/env前缀在数据源前面的作用?
在描述JNDI,例如获得数据源时,JNDI地址有两种写法,例如同是 jdbc/testDS 数据源:
A: Java:comp/env/jdbc/testDS
B: jdbc/testDS
这两种写法,配置的方式也不尽相同,第一种方法应该算是一种利于程序移植或迁移的方法,它的实现与“映射”的概念相同,而B方法,则是一个硬引用。
java:comp/env 是环境命名上下文(environment naming context(ENC)),是在EJB规范1.1以后引入的,引入这个是为了解决原来JNDI查找所引起的冲突问题,也是为了提高EJB或者J2EE应用的移植性。
在J2EE中的引用常用的有:
JDBC 数据源引用在java:comp/env/jdbc 子上下文中声明
JMS 连接工厂在java:comp/env/jms 子上下文中声明
JavaMail 连接工厂在java:comp/env/mail 子上下文中声明
URL 连接工厂在 java:comp/env/url子上下文中声明
可以通过下面的结构示意来发现这两种描述的不同之处:
A: java:comp/env/jdbc/testDS(虚地址) ——> 映射描述符 ——> jdbc/testDS (实际的地址)
B: jdbc/testDS (实际的地址)
从这种结构上来看,A的确是便于移植的。
参考博文: