036.[转] JNDI 学习
需求: 在spring boot中如何使用 jndi
(1)jndi为何而生?
(2)什么是jndi?
(3)在tomcat中怎么使用jndi?
(4)spring boot中怎么使用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等容器,这样对于开发者就不用关心数据库配置是什么,使用的什么数据库驱动连接数据库等。
三、在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。
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中添加的资源引用可有可无。
四、在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 关联
下一篇: PHP读取Excel内的图片