欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

036.[转] JNDI 学习

程序员文章站 2022-05-16 12:02:32
需求: 在spring boot中如何使用 jndi (1)JNDI为何而生? (2)什么是JNDI? (3)在Tomcat中怎么使用JNDI? (4)Spring Boot中怎么使用JNDI https://*.com/questions/26504913/spring-b ......

需求: 在spring boot中如何使用 jndi

 

(1)jndi为何而生?

(2)什么是jndi?

(3)在tomcat中怎么使用jndi?

(4)spring boot中怎么使用jndi 

036.[转] JNDI 学习

 https://*.com/questions/26504913/spring-boot-with-jndi-data-source

 

实际应用中,可以把datasource注册到jndi,也可以单独使用datasource。

// 初始化数据源实例
datasource ods = new datasource();

ods.setdrivertype("thin");
ods.setservername("chicago");
ods.setnetworkprotocol("tcp");
ods.setdatabasename("chidb");
ods.setportnumber(1521);
ods.setuser("guest");
ods.setpassword("guest");

// 从数据源中获取数据库连接
connection conn = ods.getconnection();
// 通过数据库连接进行数据操作

 

 

一、jndi为何而生?

1.1 jdbc的天下

我们如果要在程序中连接数据库的话,在没有jndi的时候,就是使用jdbc(java database connectivity,java数据库连接)了,是不是已经忘得差不多了,一起来回顾下吧,看如下连接数据库代码

        connection conn = null;
        try {
            class.forname("com.mysql.jdbc.driver", true, thread.currentthread().getcontextclassloader());
            conn = drivermanager.getconnection("jdbc:mysql://localhost:3306/mydb?user=root&password=root");
            string sql = "select *from test";
            preparedstatement ps = conn.preparestatement(sql);
            resultset rs = ps.executequery();
            while (rs.next()) {
                system.out.println("id:" + rs.getint("id") + ",name:" + rs.getstring("name") + "");
            }
            conn.close();
        } catch (exception e) {
            e.printstacktrace();
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (sqlexception e) {
                }
            }
        }

 

       这是在没有jndi的连接方式。

 

1.2 存在问题?

       上面的这种方式存在的问题是什么呢?

(1)数据库服务器名称mydb 、用户名和口令都可能需要改变,由此引发jdbc url需要修改;

(2)数据库可能改用别的产品,如改用db2或者oracle,引发jdbc驱动程序包和类名需要修改;

(3)随着实际使用终端的增加,原配置的连接池参数可能需要调整;

注意:实际上在使用了spring等牛逼的框架之后,实际上上面这些问题已经不再是问题了。

 

1.3 解决方法

程序员应该不需要关心“具体的数据库后台是什么?jdbc驱动程序是什么?jdbc url格式是什么?访问数据库的用户名和口令是什么?”等等这些问题,程序员编写的程序应该没有对 jdbc 驱动程序的引用,没有服务器名称,没有用户名称或口令 —— 甚至没有数据库池或连接管理。而是把这些问题交给j2ee容器来配置和管理,程序员只需要对这些配置和管理进行引用即可。

由此,就有了jndi。从上面的分析可以得出,实际上是由容器来管理我们的数据库连接信息了。

 

二、什么是jndi?

我们看下百度百科的描述(https://baike.baidu.com/item/jndi/3792442):

jndi(java naming and directory interface,java命名和目录接口)是sun公司提供的一种标准的java命名系统接口,jndi提供统一的客户端api,通过不同的访问提供者接口jndi服务供应接口(spi)的实现,由管理者将jndi api映射为特定的命名服务和目录系统,使得java应用程序可以和这些命名服务和目录服务之间进行交互。

       看完了之后,是不是感觉很抽象呢,这里我们需要理解这么几点:

(1)jndi是j2ee的规范之一。

(2)jndi主要有两部分组成:应用程序编程接口和服务供应商接口。应用程序编程接口提供了java应用程序访问各种命名和目录服务的功能,服务供应商接口提供了任意一种服务的供应商使用的功能。

(3)j2ee 规范要求全部 j2ee 容器都要提供 jndi 规范的实现。

(4)jndi 提出的目的是为了解藕,避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。

画外音:jndi的出现,让数据库连接代码交给容器管理,比如tomcat、jboss等容器,这样对于开发者就不用关心数据库配置是什么,使用的什么数据库驱动连接数据库等。

 

https://mp.weixin.qq.com/s?__biz=mza4odiymzewmg==&mid=2447533543&idx=1&sn=7a3aeab6a2fb29c026a420af2a70460d&chksm=843bb9f6b34c30e0ed2da36b25af7a96b08c696b22ed7767e1271ed71707cc129c007253d4a7&scene=21#wechat_redirect

 

三、在tomcat中如何使用jndi?

 tomcat配置jndi有全局配置和局部配置。大致的有以下三种配置方式:

(1)全局配置:基于context.xml的配置。

(2)局部配置:基于server.xml的配置。

(3)局部配置:基于meta-inf 的配置。

 

第一种:全局配置:基于context.xml的配置

1)在tomcat的conf/context.xml配置文件中加入

<?xml version="1.0" encoding="utf-8"?>
<context >  
 <resource name="jdbc/mydb" 
     auth="container" 
     type="javax.sql.datasource" 
     driverclassname="com.mysql.jdbc.driver" 
     url="jdbc:mysql://localhost:3306/mydb" 
     username="root" password="root" 
     maxactive="20" maxidle="10" 
     maxwait="10000"/>
</context>

 

特别注意:如果是使用了eclipse进行开发测试的话,可能会碰到如下的异常信息:

cannot create jdbc driver of class '' for connect url 'null'

      这是由于context.xml是在开发工具中的servers下的/context.xml,所以需要将配置信息配置servers/tomcat/context.xml。

036.[转] JNDI 学习

 

2)在项目的web.xml中加入资源引用(非必须的):

    <resource-ref>   
        <description>db connection</description>   
        <res-ref-name>jdbc/mydb</res-ref-name>   
        <res-type>javax.sql.datasource</res-type>   
        <res-auth>container</res-auth>   
    </resource-ref>   

其中res-ref-name值要和context.xml的name值一致。

特别说明:这个配置是可有可无的,不配置这个的话,也是可以正常运行的。

 

3)在jsp中调用加载jndi方式:

    connection conn =null;
      try{
           //初始化查找命名空间
           context ctx = new initialcontext(); 
           //initialcontext ctx = new initialcontext();亦可 
           //找到datasource,对名称进行定位java:comp/env是必须加的,后面跟你的datasource名
           datasource ds = (datasource)ctx.lookup("java:comp/env/jdbc/mydb");
           //取出连接
            conn = ds.getconnection();
           string sql = "select *from test";
           preparedstatement ps = conn.preparestatement(sql);
           resultset rs = ps.executequery();
            while(rs.next()){
                 system.out.println("id:"+rs.getint("id")+",name:"+rs.getstring("name")+"");
            }
           out.println(conn);
           out.println(conn.isclosed());
           out.println("</br>");
            system.out.println("connection pool connected !!");   
      } catch (namingexception e) {
       system.out.println(e.getmessage());
      } catch (sqlexception e) {
       e.printstacktrace();
      }finally{
           //注意不是关闭,是放回连接池.
           conn.close();
      }

特别注意:不可以直接用main方法测试,必须通过启动容器从jsp中调用

 

第二种:局部配置:基于server.xml的配置(不推荐使用)

在tomcat的server.xml的<host>标签内,添加:

   <context docbase="demo-jndi" path="/demo-jndi">
           <resource name="jdbc/mydb" 
             auth="container" 
             type="javax.sql.datasource" 
             driverclassname="com.mysql.jdbc.driver" 
             url="jdbc:mysql://localhost:3306/mydb" 
             username="root" password="root" 
             maxactive="20" maxidle="10" 
            maxwait="10000"/>
   </context>

 

其他配置同第一种方式。

 

第三种:局部配置:基于meta-info的配置

在项目的meta-inf 下面新建context.xml加入:

<?xml version="1.0" encoding="utf-8"?>
<context >  
 <resource name="jdbc/mydb" 
     auth="container" 
     type="javax.sql.datasource" 
     driverclassname="com.mysql.jdbc.driver" 
     url="jdbc:mysql://localhost:3306/mydb" 
     username="root" password="root" 
     maxactive="20" maxidle="10" 
     maxwait="10000"/>
</context>

其他配置同第一种方式。

 

总结:

如果要配置局部的话,推荐使用第三种方式,这样不依赖tomcat了。但是还是推荐使用第一种方式好,虽然依赖tomcat,但是是全局的,而且可以配置多个。对于以后切换使用方便。另外在项目的web.xml中添加的资源引用可有可无。

 

https://mp.weixin.qq.com/s?__biz=mza4odiymzewmg==&mid=2447533547&idx=1&sn=dbc4385eca1ba546fe3bf19f674e4ec3&chksm=843bb9fab34c30ecc62643616e859539bfbcd4d2eb9ba99ae5eee04096bd13d8bbfabcd4bce6&scene=21#wechat_redirect

 

 

四、在springboot中如何使用jndi?

springboot使用内置的tomcat

 

1、新增application-dev.properties文件:

# dev环境配置
datasource.jndiname=jdbc/timcore/defaultds
datasource.auth=container
datasource.driverclassname=org.postgresql.driver
datasource.url=jdbc:postgresql://30.31.0.14:7523/timc
datasource.username=timcopr
datasource.pwd=123456
datasource.maxactive=100
datasource.maxidle=30
datasource.maxwait=10000

 

2、创建一个propconfig类,接收配置

@getter
@setter
@component
@configurationproperties(prefix = "datasource")
public class datasourcepropconfig {
    private string jndiname;
    private string auth;
    private string driverclassname;
    private string url;
    private string username;
    private string pwd;
    private string maxactive;
    private string maxidle;
    private string maxwait;
}

 

3、javaconfig 方式修改配置,加入数据源

@configuration
public class mywebmvcconfigureradapter extends webmvcconfigureradapter {
    
    @resource
    private datasourcepropconfig datasourcepropconfig;
    
    // dev 环境数据源。
    @conditionalonproperty(name = "spring.profiles.active", havingvalue = "dev") 
    @bean
    public tomcatembeddedservletcontainerfactory servletcontainerfactory() {
        return new tomcatembeddedservletcontainerfactory() {
            @override
            protected tomcatembeddedservletcontainer gettomcatembeddedservletcontainer(tomcat tomcat) {
                tomcat.enablenaming(); // 打开jndi数据源
                return super.gettomcatembeddedservletcontainer(tomcat);
            }
            
            @override
            protected void postprocesscontext(context context) {
                contextresource resource = new contextresource();
                resource.settype(datasource.class.getname());
          // jndi name resource.setname(datasourcepropconfig.getjndiname()); resource.setauth(datasourcepropconfig.getauth()); resource.setproperty("driverclassname", datasourcepropconfig.getdriverclassname()); resource.setproperty("url", datasourcepropconfig.geturl()); resource.setproperty("username", datasourcepropconfig.getusername()); resource.setproperty("password", datasourcepropconfig.getpwd()); // 连接池配置,和测试、生产配置一致。 resource.setproperty("maxactive", datasourcepropconfig.getmaxactive()); // 最大连接数 resource.setproperty("maxidle", datasourcepropconfig.getmaxidle()); // 空闲连接数 resource.setproperty("maxwait", datasourcepropconfig.getmaxwait()); // 最大等待时间 context.getnamingresources().addresource(resource); } }; } }

 

4、springboot使用jndi数据源

application.properties文件中配置

spring.datasource.jndi-name=java:comp/env/jdbc/timcore/defaultds

 

? 如何配置 sqlsessionfactory 与 datasource 关联