JNDI具体用法详解

网友投稿 968 2022-11-15

JNDI具体用法详解

JNDI具体用法详解

JNDI全称(java Naming and Directory InteTLAFtJCserface),是java命名和目录接口。它是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用、统一的接口,类似JDBC都是构建在抽象层上。

1、命名的概念与应用

JNDI中的命名(Naming),就是将Java对象以某个名称的形式绑定(binding)到一个容器环境(Context)中,以后调用容器环境到JNDI容器环境(Context)的查找(lookup)方法又可以查找出某个名称所绑定的Java对象。

这样做的好处在于在真实的项目应用中,通常是由系统程序或框架程序先将资源对象绑定到JNDI环境中,以后在该系统或框架中运行的模块程序就可以从JNDI环境中查找这些资源对象了。比如,Tomcat服务器在启动时可以创建一个连接到某种数据库系统的数据源(DataSource)对象,并将该数据源(DataSource)对象绑定到JNDI环境中,以后在这个Tomcat服务器中运行的Servlet和jsP程序就可以从JNDI环境中查询出这个数据源(DataSource)对象进行使用,而不用关心数据源(DataSource)对象是如何创建出来的,这种方式极大的增强了系统的可维护性,这样,当数据库系统的连接参数发生变更时,就只是Tomcat系统管理员一个人要关心的事情,而与所有的应用程序开发人员无关。

容器环境(Context)本身也是一个Java对象,它可以通过一个名称绑定到另一个容器环境中。将一个Context对象绑定到另一个Context对象中,这就形成了一种父子级联关系,多个Context对象最终可以级联成一种树状结构,树中的每个Context对象中都可以绑定若干个Java对象。

上图中的每个方框分别代表以后个Context对象,它们分别绑定的名称分别为a、b、c、d、e,其中b和c是a的子Context,d是b的子Context,e又是d的子Context。各个方框内的每个小椭圆分别代表一个Java对象,它们也都有一个绑定的名称,这些名称分别为dog、pig、sheet等,在同一个Context不能绑定两个相同名称的Java对象,在不同的Context中可以出现同名的绑定对象。可见,Context树的级联结构与文件系统中的目录结构非常类似,Context与其中绑定的Java对象的关系也非常类似于文件系统的目录与文件的关系。

想要得到一个Context对象,就可以调用它的查询(lookup)方法来获得其中绑定的java对象。另外,调用某个Context对象的lookup方法也可以获得Context树中的任意一个Context对象,这只需要在lookup方法中指定相应的Context路径即可。

在JNDI中不存在着“根”Context的概念,也就是说,执行JNDI操作不是从一个“根”Context对象开始,而是可以从Context树中的任意以后个Context开始。如论如何程序必须获得一个作为操作入口的Context对象后才能执行各种JNDI命名操作,为此,JNDI API中提供了一个InitialContext类来创建用作JNDI命名操作的入口Context对象。

Context是一个接口,Context对象实际上是Context的某个实现类的实例对象,选择这个具体的Context实现类并创建其实例对象的过程是由一个Context工厂类来完成的,这个工厂类的类名可以通过JNDI的环境属性java.naming.factory.initial指定,也可以根据Context的操作方法的url参数的Schema来选择。

2、目录的概念与应用

JNDI中的目录(Directory)与文件系统中的目录概念有很大的不同,JNDI中的目录(Directory)是指将一个对象的所有属性信息保存到一个容器环境中。JNDI的目录(Directory)原理与JNDI的命令(Naming)原理非常相似,主要的区别在于目录容器环境中保存的是对象的属性信息,而不是对象本身,所以,目录提供的是对属性的各种操作。事实上,JNDI的目录(Directory)与命名(Naming)往往是结合在一起使用的,JNDI API中提供的代表目录容器环境的类为DirContext,DirContext是Chttp://ontext的子类,显然它除了能完成目录相关操作外,也能完成所有的命令(Naming)操作。DirContext是对Context的扩展,它在Context的基础上增加了对目录属性的操作功能,可以在其中绑定对象的属性信息和查找对象的属性信息。JNDI中的目录(Directory)的结构示意图如下:

上图中的每个外层的方框分别代表一个DirContext对象,它们绑定的名称分别为a、b,b是a的子DirContext。图中的每个小椭圆分别代表一个java对象,各个里层的方框分别代表一个对象属性。从名称为a的DirContext中的内容可以看到,一个DirContext容器环境中即可以绑定对象自身,也可以绑定对象的属性信息,绑定的对象和绑定的属性是完全独立的两个事物,即使它们的绑定名称相同,它们的操作也是完全独立的。另外,一个属性可以有多个属性值,例如,dog对象的category属性就设置了两个属性值:meat和pet。

从名称为b的DirContext中的内容可以看到,一个DirContext容器环境中也可以只绑定对象的属性信息,而不绑定任何对象自身。与Context的操作原理类似,JNDI API中提供了一个InitialDirContext类创建用作JNDI命名与目录属性操作的入口DirContext对象。

3、JNDI的用法:创建一个数据源

没有JNDI时的做法

Connection conn = null;

try{

Class.forName("com.mysql.jdbc.Driver",true,Thread.currentThread().getContextClassLoader());

conn = DriverManager.getConnection("jdbc:mysql://MyDBServer?user=xxx&password=xxx");

.....

conn.close();

}catch(Exception e){

e.printStackTrace();

}finally{

if(conn!=null){

try{

conn.close();

}catch(SQLException e){}

}

}

这种做法只适用于小规模开发,在大规模开发中就会存在许多问题,比如:

数据库服务器名称MyDBServer、用户名和口令都可能需要改变,由此引发JDBC URL需要修改。

数据库可能改用别的产品,引发JDBC驱动程序包和类名需要修改。

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

在开发过程中,程序员应该不需要关心“具体的数据库后台是什么?JDBC驱动程序是什么?”等这些问题,程序员编写的程序应该没有对JDBC驱动程序的引用,没有服务器名称,没有用户名称等,而是把这些问题交给容器来配置和管理,这样程序员只需要对这些配置和管理进行引用即可。

使用JNDI

context.xml配置数据库连接信息:

<Context>

WEB-INF/web.xml

${catalina.base}/conf/web.xml

type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"

url="jdbc:mysql://127.0.0.1:3306/task"

username="root" password="123456" maxTotal="20" maxIdle="10"

maxWaitMillis="-1"/>

web.xml中引入数据源:

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

version="4.0">

index.html

jdbc/mysql

javax.sql.DataSource

Container

获取Connection对象,查询数据库:

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.sql.DataSource;

import java.io.IOException;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

@WebServlet("/test")

public class Servlet1 extends HttpServlet {

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {

try {

Context initContext = new InitialContext();

Context envContext = (Context) initContext.lookup("java:/comp/env");

DataSource ds = (DataSource) envContext.lookup("jdbc/mysql");

Connection conn = ds.getConnection();

PreparedStatement ps = conn.prepareStatement("select * from t_role");

ResultSet rs = ps.executeQuery();

System.out.println(rs.next());

rs.close();

conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

type="javax.sql.DataSource" driverClassName="com.mysql.jdbc.Driver"

url="jdbc:mysql://127.0.0.1:3306/task"

username="root" password="123456" maxTotal="20" maxIdle="10"

maxWaitMillis="-1"/>

web.xml中引入数据源:

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

version="4.0">

index.html

jdbc/mysql

javax.sql.DataSource

Container

xmlns:xsi="http://w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"

version="4.0">

index.html

jdbc/mysql

javax.sql.DataSource

Container

获取Connection对象,查询数据库:

import javax.naming.Context;

import javax.naming.InitialContext;

import javax.servlet.ServletException;

import javax.servlet.annotation.WebServlet;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.sql.DataSource;

import java.io.IOException;

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

@WebServlet("/test")

public class Servlet1 extends HttpServlet {

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws IOException {

try {

Context initContext = new InitialContext();

Context envContext = (Context) initContext.lookup("java:/comp/env");

DataSource ds = (DataSource) envContext.lookup("jdbc/mysql");

Connection conn = ds.getConnection();

PreparedStatement ps = conn.prepareStatement("select * from t_role");

ResultSet rs = ps.executeQuery();

System.out.println(rs.next());

rs.close();

conn.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:一个简单的loading
下一篇:JS生成某个范围的随机数
相关文章

 发表评论

暂时没有评论,来抢沙发吧~