一、什么是JNDI?
JNDI(Java Naming and Directory Interface,Java命名和目录接口):在程序中使用JNDI获取数据源。说白了就是把数据源取个名字,再根据名字来找数据源。
在JDBC时代,需要把数据库信息,写在代码中去连接。
使用JNDI就是把数据库的连接信息放到j2ee的容器中取一个名字。例如放到tomcat的conf/context.xml中
二、本地springboot项目JNDI怎么配置?
1、配置文件增加jndi的name
spring.datasource.jndi-name=java:comp/env/jdbc/mysql/test
2、增加配置类,定义内置tomcat工厂bean。先打开jndi数据源,再添加Context资源到tomcat上下文中。
@Configuration
public class TomcatConfigs {
@Bean
public TomcatEmbeddedServletContainerFactory tomcatFactory() {
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.setName("jdbc/mysql/test");
resource.setType(DataSource.class.getName());
resource.setProperty("driverClassName", "com.mysql.jdbc.Driver");
resource.setProperty("url", "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8");
resource.setProperty("username", "root");
resource.setProperty("password","root");
//数据库连接池
resource.setProperty("maxTotal","100");
resource.setProperty("maxIdle","80");
resource.setProperty("minIdle","10");
resource.setProperty("maxWaitMillis","30000");
resource.setProperty("testOnCreate","false");
resource.setProperty("testOnBorrow","true");
resource.setProperty("testOnReturn","false");
resource.setProperty("testWhileIdle","false");
resource.setProperty("numTestsPerEvictionRun","3");//设定在进行后台对象清理时,每次检查几个链接
resource.setProperty("minEvictableIdleTimeMillis","1800000");//空闲逐出连接池的时间 毫秒
context.getNamingResources().addResource(resource);
}
};
}
}
3、之后项目启动时,满足springboot-autoconfig的JndiDataSourceAutoConfiguration。就开始使用jndi连接数据库,创建连接池。
4、完毕
JndiDataSourceAutoConfiguration源码如下:
注意:JNID使用的是org.apache.tomcat.dbcp.dbcp2.BasicDataSource数据源、连接池是:GenericObjectPool<PoolableConnection>
附加:手动获取JNDI数据库连接方式
// 获取数据库连接
public Connection getConnection() {
try {
//初始化上下文
Context cxt=new InitialContext();
//获取与逻辑名相关联的数据源对象
DataSource ds=(DataSource)cxt.lookup("java:comp/env/jdbc/test");
conn=ds.getConnection();
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
JNDI包括5个包:
- javax.naming:主要用于命名操作,它包含了命名服务的类和接口,该包定义了Context接口和InitialContext类;
- javax.naming.directory:主要用于目录操作,它定义了DirContext接口和InitialDir- Context类;
- javax.naming.event:在命名目录服务器中请求事件通知;
- javax.naming.ldap:提供LDAP支持;
- javax.naming.spi:允许动态插入不同实现,为不同命名目录服务供应商的开发人员提供开发和实现的途径,以便应用程序通过JNDI可以访问相关服务。
常用的JNDI操作如下:
- void bind(String sName,Object object),绑定:把名称同对象关联的过程。
- void rebind(String sName,Object object),重新绑定:用来把对象同一个已经存在的名称重新绑定。一般使用rebind()而不使用bind(),因为当有重名的时候rebind()不会出现异常,而bind()会报异常。
- void unbind(String sName),释放:用来把对象从目录中释放出来。
- void lookup(String sName,Object object),查找:返回目录总的一个对象。
- void rename(String sOldName,String sNewName),重命名:用来修改对象名称绑定的名称。
- NamingEnumeration listBindings(String sName),清单:返回绑定在特定上下文中指定属性名对象的清单列表,它返回名字、类和对象本身,它用于那些需要对对象进行实际操作的应用。
三、生产环境tomcat JNDI怎么配置?
1、在lib/server.xml文件中<Server>节点下的<GlobalNamingResources>节点下添加下面的资源定义
<Resource name="jdbc/mysql/test"
auth="Container"
type="javax.sql.DataSource"
maxTotal="1000"
maxWaitMillis="10000"
driverClassName="com.mysql.jdbc.Driver"
username="root"
password="root"
url="jdbc:mysql://192.168.1.10:3306/jsw?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=fals
e"
/>
参数:
name=指定Resource的JNDI名称
auth=指定管理Resource的Manager(Container由容器创建和管理,Application由Web应用创建和管理)
type=指定Resource的java类
maxActive=指定连接池中处于活动状态的数据库连接的最大数量
maxIdle=指定连接池中处于空闲状态的数据库的最大数量
maxWait=指定连接池中连接处于空闲的最长时间,超过这个时间会提示异常
2、在lib/context.xml文件中<Context>节点中添加下面的资源引用<ResourceLink>。
<ResourceLink name="jdbc/mysql/test" global="jdbc/mysql/test" type="javax.sql.DataSource" />
3、将数据库的驱动jar包,放到Tomcat安装目录下的lib文件夹中。
提示:jndi数据源配置的密码应该是要加密存放在<Resources>中,只是我没有细致了解,请另行百度