读书人

由Tomcat上的JNDI数据源引出的.

发布时间: 2012-10-26 10:30:58 作者: rapoo

由Tomcat下的JNDI数据源引出的......

??? 众所周知,Tomcat是支持数据库连接池的,并且还支持通过JNDI接口来获得这一服务。要想在你的程序中使用这一特性,需要你对Tomcat做一些配制。


??? 我以往的做法都是现到网上去找,然后人家说在哪个配制文件下加一段什么代码,就照着做,成功后这事儿也就结了。过了一段时间又遇到这个问题,还是同样的做法......。为了结束这种痛苦的、无休止的循环,我决定花点儿时间把这个问题搞清楚,要做到不仅要知其然还要知其所以然。


Tomcat的配制文件体系(以Tomcat 6.0.18为例)


??? 在%TOMCAT_HOME%/conf目录下一般会有server.xml、context.xml、web.xml、tomcat-users.xml等配制文件,下面重点说一下server.xml和context.xml两个文件:


1、server.xml
??? 这个文件是整个Tomcat的一个缩影,从它可以看出Tomcat的架构和工作方式。

Server(1)----元素代表了整个Catalina servlet容器

|
|------ Service(n)----元素代表了一个用于处理请求的组合,这个组合包括了一个或多个Connector和
|???????? | ? ? ? ? ? ? ? ? ? ?一个Engin,这些Connector共享这个Engin。?

|???????? |
|???????? |------ Connector(n)----主要用于监听来自client的请求,一个Connector监听一个端口。
|???????? |
|???????? |------ Engin(1)----元素代表了和一个特定联系的,用于请求处理的机构。它接受和
|?????????????????? |???????????????????? 处理来自同属一个Service下的所有Connector的请求,并生成完整的回应(response)
|?????????????????? |
|?????????????????? |------ Host(n)----元素代表了一个虚拟主机
|???????????????????????????? |
|???????????????????????????? |------ Context(n)----元素代表了一个特定的虚拟主机下的web application
|
|------ GlobalNamingResources(1)----元素定义的是整个容器级别的全局的资源,

??????????????????????????????????????????????????????????????????? 这些 资源对容器中的每个Web Application都是不可见的。

??????????????????????????????????????????????????????????????????? 某个Web Application想要使用某个全局资源,可以在此

??????????????????????????????????????????????????????????????????? Web Application的?? 元素下使用元素

???????????????????????????????????????????????????????????????????? 来引用想要使用的全局资源。


??? 在这想要说的主要是GlobalNamingResources这个节点。正如上面的说明所述,定义在它下面的资源都是整个容器级别的全局资源,也就是说这些资源可以被部署在这个容器中的所有webapp所使用。但是必须在webapp和这些资源之间搭一座桥------在webapp对应的Context节点下使用元素来引用想要使用的全局资源。


2、context.xml

??? 从上面我们可以知道一个Host(虚拟主机)下可以有多个Context,每个Context就代表了一个部署在该虚拟主机下的webapp。tomcat 5以后就不推荐大家在server.xml的Host节点下直接追加Context,因为对Host节点下的Context的修改,会导致server.xml改变这样一来就必须要重新起动服务器才能加载新的server.xml。所以在tomcat 5以后就多了context.xml这个文件,在这个文件下配制的资源所有webapp都能够访问到。


??? 以上是对tomcat做的一些粗略的介绍,回到正题,下面就tomcat下的JNDI数据源的配制来实践一下上面的说法。

方案一:使用%TOMCAT_HOME%/conf/context.xml
??? 直接上代码:

</Context>        <Resource name="jdbc/test"                type="javax.sql.DataSource"              username="root"              password="mysql"                driverClassName="com.mysql.jdbc.Driver"                maxIdle="2"                maxWait="5000"                url="jdbc:mysql://localhost:3306/test"                maxActive="4"/></Context>

?

??????? 以上的<Resource>节点是针对MySql的数据源配制信息,以上工作做完后,Tomcat起动时就会把这个数据源生成好放到上下文环境中。该Tomcat下的所有webapp都能通过JNDI接口找到该数据源。

?

??? 这下东西有了,但怎么来找到并使用它呢?

?

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"><resource-ref>   <description>TomcatJNDI数据源</description>   <res-ref-name>jdbc/test</res-ref-name>   <res-type>javax.sql.DataSource</res-type>   <res-auth>Container</res-auth></resource-ref></web-app>

??? 以上是在自己的webapp下添加对配制在context.xml下的数据源的引用。试验了一下,在Tomcat 6.0.18下这个<resource-ref>不用,也能正确找到那个数据源。但最好还是写上吧!

?

??? 桥已经搭好了,来试着lookup一下吧!

?

    public static Connection getConnection() {        Connection conn = null;        try {            Context ctx = new InitialContext();            DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/test");            conn = ds.getConnection();        } catch (NamingException e) {            e.printStackTrace();        } catch (SQLException e) {            e.printStackTrace();        }        if(conn != null){            System.out.println("Connected!");        }else {            System.out.println("Connect failed!");        }        return conn;    }

??? 你"connected"了吗?

?

方案二:使用%TOMCAT_HOME%/conf/server.xml下的<GlobalNamingResources>节点。

??? 直接上代码:

<Server port="8005" shutdown="SHUTDOWN"><GlobalNamingResources><Resource  name="jdbc/test"                  type="javax.sql.DataSource"  factory=""                            password="mysql"                             driverClassName="com.mysql.jdbc.Driver"                             maxIdle="2"                             maxWait="5000"                             username="root"                             url="jdbc:mysql://localhost:3306/test"                             maxActive="4"/>...</GlobalNamingResources>...</Server>

??? 顾名思义,这也是面向所有webapp的。但跟方案一有所不同的是<GlobalNamingResources>需要跟<ResourceLink>配合使用。详细情况参见下面:

?

<Context><ResourceLink name="jdbc/link" global="jdbc/test" type="javax.sql.DataSource"/>...</Context>

??? 此时lookup时需要用"java:comp/env/jdbc/link"

??? Context ctx = new InitialContext();
??????????? DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/link");

?

方案三:<Host>节点下追加<context>节点。具体内容跟方案一类似,但tomcat5后就不推荐使用这种方法了。

?

读书人网 >软件架构设计

热点推荐