036.[转] JNDI 学习
使用外置服务器(如tomcat)时,如果一个服务器启动多个项目,可以使用JNDI配置数据源,这样每个项目都可以获取到Tomcat 配置的 JNDI的数据源。
在学习 jsp 的时候,作用域对象
pageContext < request < session < application(ServletContext) ; 最多能从当前servlet容器获取到参数值
在Tomcat配置JNDI数据源的三种方式
https://blog.csdn.net/dyllove98/article/details/7706218
(1)JNDI为何而生?
(2)什么是JNDI?
(3)在Tomcat中怎么使用JNDI?
(4)Spring Boot中怎么使用JNDI
一、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
https://juejin.im/post/5ca6214f51882543e85f0fd6
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 关联
https://blog.csdn.net/bjl3738/article/details/86295024
https://blog.csdn.net/muyiyangyang/article/details/80807256
036.[转] JNDI 学习的更多相关文章
- JNDI学习总结(一)——JNDI数据源的配置
一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Class.forName("数据库驱动类");) ②连接数据库(Connec ...
- JNDI学习总结(三)——Tomcat下使用Druid配置JNDI数据源
com.alibaba.druid.pool.DruidDataSourceFactory实现了javax.naming.spi.ObjectFactory,可以作为JNDI数据源来配置. 一.下载D ...
- JNDI学习总结(二)——Tomcat下使用C3P0配置JNDI数据源
一.C3P0下载 C3P0下载地址:http://sourceforge.net/projects/c3p0/files/?source=navbar
- JNDI学习总结——Tomcat下使用C3P0配置JNDI数据源
一.C3P0下载 C3P0下载地址:http://sourceforge.net/projects/c3p0/files/?source=navbar
- JNDI学习总结(一)——JNDI数据源的配置(转)
一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Class.forName("数据库驱动类");) ②连接数据库(Conn ...
- Java JNDI 学习
一.概念: 1.JNDI(JavaNaming and Directory Interface,Java命名和目录接口)是SUN公司提供的一种标准的Java命名系统接口,JNDI提供统一的客户端API ...
- JNDI学习总结(2)——JNDI数据源的配置
一.数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Class.forName("数据库驱动类");) ②连接数据库(Con ...
- JNDI学习总结(1)——JNDI入门
JNDI是 Java 命名与目录接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之一,不少专家认为,没有透彻理解JNDI的意义和作用,就没有 ...
- JNDI学习总结(4)——Tomcat下使用Druid配置JNDI数据源
com.alibaba.druid.pool.DruidDataSourceFactory实现了javax.naming.spi.ObjectFactory,可以作为JNDI数据源来配置. 一.下载D ...
随机推荐
- Win32 API编程——前言
一丶什么是Win32 API? 微软为了保护操作系统的安全性和稳定性,把系统分为内核层和用户层(内核层的代码只能在当CPU的特权级为R0状态下执行,用户层的代码在CPU特权级为R0和R3都能执行),w ...
- 【机器学习实战】计算两个矩阵的成对距离(pair-wise distances)
矩阵中每一行是一个样本,计算两个矩阵样本之间的距离,即成对距离(pair-wise distances),可以采用 sklearn 或 scipy 中的函数,方便计算. sklearn: sklear ...
- React的setState学习及应用
React的setState学习及应用 一:作用: setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件.这是用于更新 ...
- seaborn画出的一些好看的图片
PYSPARK_DRIVER_PYTHON=/home/zhangyu/anaconda3/bin/jupyter-notebook PYSPARK_DRIVER_PYTHON_OPTS=" ...
- 百度地图API 拖拽或点击地图位置获取坐标
function setPlace(map,myValue,callback){ function getAddress(){ var pp = local.getResults().getPoi(0 ...
- Android项目实战之高仿网易云音乐创建项目和配置
这一节我们来讲解创建项目:说道大家可能就会说了,创建项目还有谁不会啊,还需要讲吗,别急听我慢慢到来,肯定有你不知道的. 使用项目Android Studio创建项目我们这里就不讲解了,主要是讲解如何配 ...
- VUE添加网站favicon.ico图标
1.修改webpack.dev.conf文件 webpack.prod.conf文件 new HtmlWebpackPlugin({ filename: 'index.html', templat ...
- thinkphp6安装报错,composer install tp6 报错 Parse error: syntax error
composer install thinkphp6 报错 Parse error: syntax error, unexpected ':', expecting '{' in vendor\top ...
- Linux后台运行和关闭jar项目
直接用java -jar xxx.jar,当退出或关闭shell时,程序就会停止掉.以下方法可让jar运行后一直在后台运行. java -jar server.jar & 如果想要关闭java ...
- MVC(实战一)
一.创建MVC项目 二.界面分布 Content:是存放css文件等,暂时先不考虑. Controllers:重要, 控制层,控制界面显示和界面逻辑的,其实真正业务逻辑层,建议分层出去. Models ...