JNDI具体用法详解

JNDI全称(Java Naming and Directory Interface),是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是Context的子类,显然它除了能完成目录相关操作外,也能完成所有的命令(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配置数据库连接信息:

<?xml version="1.0" encoding="UTF-8"?>

<Context>
    <!-- Default set of monitored resources. If one of these changes, the    -->
    <!-- web application will be reloaded.                                   -->
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>

    <!-- Uncomment this to disable session persistence across Tomcat restarts -->
    <!--<Manager pathname="" />-->

    <Resource name="jdbc/mysql" auth="Container"
              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"/>
</Context>

web.xml中引入数据源:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.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">
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>
    <resource-ref>
        <res-ref-name>jdbc/mysql</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>
</web-app>

获取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();

        }
    }
}

到此这篇关于JNDI具体用法详解的文章就介绍到这了,更多相关JNDI 用法内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JNDI,JTA和JMS简介

    什么是JNDI 原理:在DataSource中事先建立多个数据库连接,保存在数据库连接池中.当程序访问数据库时,只用从连接池中取空闲状态的数据库连接即可,访问结束,销毁资源,数据库连接重新回到连接池,这与每次去直接访问数据库相比,会节省大量时间和资源. JNDI( Java Naming and DirectoryInterface ),是Java平台的一个标准扩展,提供了一组接口.类和关于命名空间的概念.如同其它很多Java技术一样,JDNI是provider-based的技术,暴露了一个 A

  • Java JNDI案例详解

    JNDI的理解 JNDI是 Java 命名与文件夹接口(Java Naming and Directory Interface),在J2EE规范中是重要的规范之中的一个,不少专家觉得,没有透彻理解JNDI的意义和作用,就没有真正掌握J2EE特别是EJB的知识.  那么,JNDI究竟起什么作用?//带着问题看文章是最有效的  要了解JNDI的作用,我们能够从"假设不用JNDI我们如何做?用了JNDI后我们又将如何做?"这个问题来探讨.  没有JNDI的做法:  程序猿开发时,知道要开发訪

  • JNDI简介_动力节点Java学院整理

    一.JNDI是什么? JNDI--Java 命名和目录接口(Java Naming and Directory Interface),是一组在Java应用中访问命名和目录服务的API. 二.JNDI好处 解耦:通过注册.查找JNDI服务,可以直接使用服务,而无需关心服务提供者,这样程序不至于与访问的资源耦合! JNDI优点  包含了大量的命名和目录服务,使用通用接口来访问不同种类的服务: 可以同时连接到多个命名或目录服务上: 建立起逻辑关联,允许把名称同Java对象或资源关联起来,而不必知道对象

  • 基于JNDI的应用程序开发

    JNDI(The Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API.命名服务将名称和对象联系起来,使得我们可以用名称访问对象.目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性. 命名或目录服务使你可以集中存储共有信息,这一点在网络应用中是重要的,因为这使得这样的应用更协调.更容易管理.例如,可以将打印机设置存储在目录服务中,以便被与打印机有关的应用使用. 本文用代码示例的方式给出了一个快

  • JNDI具体用法详解

    JNDI全称(Java Naming and Directory Interface),是java命名和目录接口.它是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通用.统一的接口,类似JDBC都是构建在抽象层上. 1.命名的概念与应用 JNDI中的命名(Naming),就是将Java对象以某个名称的形式绑定(binding)到一个容器环境(Context)中,以后调用容器环境到JNDI容器环境(Context)的查找(lookup)方法又可以查找出某个名称所绑定的Ja

  • Oracle中游标Cursor基本用法详解

    查询 SELECT语句用于从数据库中查询数据,当在PL/SQL中使用SELECT语句时,要与INTO子句一起使用,查询的 返回值被赋予INTO子句中的变量,变量的声明是在DELCARE中.SELECT INTO语法如下: SELECT [DISTICT|ALL]{*|column[,column,...]} INTO (variable[,variable,...] |record) FROM {table|(sub-query)}[alias] WHERE............ PL/SQL

  • JSP 中request与response的用法详解

    JSP 中request与response的用法详解 概要: 在学习这两个对象之前,我们应该已经有了http协议的基本了解了,如果不清楚http协议的可以看我的关于http协议的介绍.因为其实request和response的使用大部分都是对http协议的操作. request对象的介绍 我们先从request对象进行介绍: 我们知道http协议定义了请求服务器的格式: 请求行 请求头 空格 请求体(get请求没有请求体) 好了,这里我们就不详细介绍了,我们只看几个应用就可以了,没什么难度: 应

  • 基于C++中setiosflags()的用法详解

    cout<<setiosflags(ios::fixed)<<setiosflags(ios::right)<<setprecision(2); setiosflags 是包含在命名空间iomanip 中的C++ 操作符,该操作符的作用是执行由有参数指定区域内的动作:   iso::fixed 是操作符setiosflags 的参数之一,该参数指定的动作是以带小数点的形式表示浮点数,并且在允许的精度范围内尽可能的把数字移向小数点右侧:   iso::right 也是se

  • Require.js的基本用法详解

    一:什么是require.js ①:require.js是一个js脚本加载器,它遵循AMD(Asynchronous Module Definition)规范,实现js脚本的异步加载,不阻塞页面的渲染和其后的脚本的执行,并提供了在加载完成之后的执行相应回调函数的功能: ②:require.js要求js脚本必须要实现模块化,即文件化:而require.js的作用之一就是加载js模块,也就是js文件. ③:require.js可以管理js模块/文件之间的依赖;即不同的框架例如Jquery,Angul

  • JSP中EL表达式的用法详解(必看篇)

    EL 全名为Expression Language EL 语法很简单,它最大的特点就是使用上很方便.接下来介绍EL主要的语法结构: ${sessionScope.user.sex} 所有EL都是以${为起始.以}为结尾的.上述EL范例的意思是:从Session的范围中,取得 用户的性别.假若依照之前JSP Scriptlet的写法如下: User user =(User)session.getAttribute("user"); String sex =user.getSex( );

  • OGNL表达式基本语法与用法详解

    一.OGNL中的#.%和$符号 #.%和$符号在OGNL表达式中经常出现,而这三种符号也是开发者不容易掌握和理解的部分.在这里我们简单介绍它们的相应用途. 1.#符号的三种用法 1)访问非根对象属性,例如示例中的#session.msg表达式,由于Struts 2中值栈被视为根对象,所以访问其他非根对象时,需要加#前缀.实际上,#相当于ActionContext. getContext():#session.msg表达式相当于ActionContext.getContext().getSessi

  • oracle数据库中sql%notfound的用法详解

    SQL%NOTFOUND 是一个布尔值.与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true.否则返回false.这样的语句在实际应用中,是非常有用的.例如要update一行数据时,如果没有找到,就可以作相应操作.如: begin update table_name set salary = 10000 where emp_id = 10; if sql%notfound then insert into

  • Oracle中的INSTR,NVL和SUBSTR函数的用法详解

    Oracle中INSTR的用法: INSTR方法的格式为 INSTR(源字符串, 要查找的字符串, 从第几个字符开始, 要找到第几个匹配的序号) 返回找到的位置,如果找不到则返回0. 例如:INSTR('CORPORATE FLOOR','OR', 3, 2)中,源字符串为'CORPORATE FLOOR', 在字符串中查找'OR',从第三个字符位置开始查找"OR",取第三个字后第2个匹配项的位置. 默认查找顺序为从左到右.当起始位置为负数的时候,从右边开始查找. 所以SELECT I

  • jQuery选择器之属性筛选选择器用法详解

    在这么多属性选择器中[attr="value"]和[attr*="value"]是最实用的 [attr="value"]能帮我们定位不同类型的元素,特别是表单form元素的操作,比如说input[type="text"],input[type="checkbox"]等 [attr*="value"]能在网站中帮助我们匹配不同类型的文件 <!DOCTYPE html> <

随机推荐