tomcat配置全局和私有JNDI数据源

发布时间 2023-04-14 11:06:38作者: 苦逼运维

  本人CentOS上部署了tomcat,在配置JNDI数据源时,先后遇到了两种报错。

  第一种,Cannot create JDBC driver of class '' for connect URL 'null',这个根据我个人理解是没有获取到数据源的任何信息,只要根据配置的方式(全局或私有)检查一下配置文件即可;

  第二种,Cannot create PoolableConnectionFactory (IO Error: Got minus one from a read call),查下来说是Oracle连接数问题,简单粗暴的方式是根据配置的方式(全局或私有)检查一下配置文件中是否存在maxIdle和maxActive配置项,将其删除

(1).全局

  目前找到的全局配置方法有两种。

  1)主修改tomcat根目录下的conf/context.xml文件

    在tomcat根目录下的conf/context.xml文件中<context>标签内添加如下内容:

<Resource name="[自定义数据源名称]"
          auth="Container"
          type="javax.sql.DataSource"
          username="[数据库用户名]"
          password="[数据库密码]"
          driverClassName="oracle.jdbc.driver.OracleDriver"
          url="jdbc:oracle:thin:@[数据库IP地址]:[数据库端口]/[服务名]" />

    注意:driverClassName和url根据数据库类型和jar包而存在差异。首先看Mysql,如下:

driverClassName:
com.mysql.jdbc.Driver    # mysql-connector-java 5.x及之前版本中的
com.mysql.cj.jdbc.Driver # mysql-connector-java 6.x及后续版本中的

url:
jdbc:mysql://[数据库IP地址]:[数据库端口]/[库名]

    再看Orcale,如下:

driverclassName:
oracle.jdbc.driver.OracleDriver    #ojdbc类型的jar包
com.mchange.v2.c3p0.ComboPooledDataSource    #没用过,查到是c3p0类型的jar包

url:
jdbc:oracle:thin:@[数据库IP地址]:[数据库端口]:[SID]
jdbc:oracle:thin:@//[数据库IP地址]:[数据库端口]/[服务名]  #Oracle 11g及以上版本,@后面的//可以省略
jdbc:oracle:thin:@[TNSName]  #oracle 10.2.0.1及以上版本支持TNSName

    其他常见数据库连接可以参考:https://blog.csdn.net/l13880647015/article/details/106571467/。

    接着,在项目目录下WEB-INF/web.xml文件的<webapp>标签内添加如下内容:

<resource-ref>
  <res-ref-name>[数据源名称]</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

    注意:<res-ref-name>标签的值与<Resource>中name参数的值相同。

    最后,重启tomcat程序。

  2)主修改tomcat根目录下的conf/server.xml文件,辅修改tomcat根目录下的conf/context.xml文件

    首先,在tomcat根目录下的conf/server.xml文件的<GlobalNamingResources>标签内添加如下内容:

<Resource name="[自定义资源名称]"
          auth="Container"
          type="javax.sql.DataSource"
          username="[数据库用户名]"
          password="[数据库密码]"
          driverClassName="oracle.jdbc.driver.OracleDriver"
          url="jdbc:oracle:thin:@[数据库IP地址]:[数据库端口]/[服务名]" />

    其次,在tomcat根目录下的conf/context.xml文件的<Context>标签内添加如下内容:

<ResourceLink name="[自定义数据源名称]" global="[资源名称]" type="javax.sql.DataSource" />

    接着,在项目目录下WEB-INF/web.xml文件的<webapp>标签内添加如下内容:

<resource-ref>
  <res-ref-name>[数据源名称]</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

    注意:<ResourceLink>中global参数的值与<Resource>中name参数的值相同,<res-ref-name>标签的值与<ResourceLink>中name参数的值相同。

    最后,重启tomcat程序。

(2).私有

  目前找到的私有配置方法也是两种。

  1)主修改tomcat根目录下的conf/server.xml文件

    首先,在tomcat根目录下的conf/server.xml文件的<Host>标签内添加如下内容:

<Context path="/ygfp" docBase="ygfp" reloadable="true">
  <Resource name="[自定义数据源名称]"
            auth="Container"
            type="javax.sql.DataSource"
            username="[数据库用户名]"
            password="[数据库密码]"
            driverClassName="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@[数据库IP地址]:[数据库端口]/[服务名]"/>
</Context>    

    接着,在项目目录下WEB-INF/web.xml文件的<webapp>标签内添加如下内容:

<resource-ref>
  <res-ref-name>[数据源名称]</res-ref-name>
  <res-type>javax.sql.DataSource</res-type>
  <res-auth>Container</res-auth>
  <res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>

    注意:<res-ref-name>标签的值与<Resource>中name参数的值相同。

    最后,重启重启tomcat程序。

  2)创建项目目录的META-INF\context.xml文件

    创建项目目录的META-INF\context.xml文件,并添加如下内容:

<?xml version="1.0" encoding="UTF-8"?>
<Context reloadable="true">
  <Resource name="[自定义数据源名称]"
            auth="Container"
            type="javax.sql.DataSource"
            username="[数据库用户名]"
            password="[数据库密码]"
            driverClassName="oracle.jdbc.driver.OracleDriver"
            url="jdbc:oracle:thin:@[数据库IP地址]:[数据库端口]/[服务名]"/>
</Context>

    通过tomcat web管理页面启动项目即可。

(3).补充

  1)项目配置文件或程序中调用的JNDI要与自定义数据源名称保持一致;

  2)补充Resource中参数说明:

    maxIdle:数据库最大空闲连接的数量(待命),设 0 为没有限制。

    maxWait:最大建立连接等待时间,单位为ms,设-1表示无限制。

    maxActive:数据库最大连接数,设0为没有限制。

  3)同时存在多种配置方式且同名,会获取哪一个:

    首先,全局配置大于私有配置,也就是说若全局和私有同时存在,优先获取全局配置的数据源

    全局:在context.xml中,<Resource>和<ResourceLink>(引用server.xml中<GlobalNamingResources> )同时存在,哪个标签在前获取到哪一个,即按顺序获取。

    私有:1. 若只存在<Host>标签中的配置,不存在META-INF中的context.xml,则优先获取<Host>中配置的第一个数据源;2. 若两种私有配置方式都存在,会获取META-INF中context.xml配置的数据源。

  4)为什么web.xml中的配置可有可无,却要加上呢?

    详情见tomcat的docs:jndi-resources-howto.html

    其中有这么一句话:

If a resource has been defined in a <Context> element it is not necessary for that resource to be defined in /WEB-INF/web.xml.
However, it is recommended to keep the entry in /WEB-INF/web.xml to document the resource requirements for the web application.

    也就是说,在web.xml加入的那段代码仅起到说明作用,说明这个Web应用引用了哪些资源!详情请翻阅文档。

 

参考文档:JNDI学习总结(二):tomcat配置全局和私有JNDI数据源的几种方式 - 水狼一族 - 博客园 (cnblogs.com)

     https://blog.csdn.net/digyso888/article/details/3671170