手动绑定Context

原创 2011年01月25日 15:33:00
原创声明:
    本文章为原创,欢迎转载,但请给出本文链接,多谢合作。
    本文链接:http://blog.csdn.net/epinszteinic/archive/2011/01/25/6163196.aspx

手动绑定Context

为什么会有这个需求?

一个jboss的web应用,DataSource(以下简称DS)通过jboss的配置文件设置,如下:
<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
    <jndi-name>DS_abcd</jndi-name>
    。。。
  </local-tx-datasource>
</datasources>

众所周知,jboss启动很慢,测试很痛苦。我不需要跑画面,我只需要运行逻辑!!
怎么办?自己手动绑定DS!!

需要知道两个常量:
Context.INITIAL_CONTEXT_FACTORY = "java.naming.factory.initial"
Constant that holds the name of the environment property for specifying the initial context factory to use. The value of the property should be the fully qualified class name of the factory class that will create an initial context. This property may be specified in the environment parameter passed to the initial context constructor, an applet parameter, a system property, or an application resource file. If it is not specified in any of these sources, NoInitialContextException is thrown when an initial context is required to complete an operation. 

The value of this constant is "java.naming.factory.initial".

Context.URL_PKG_PREFIXES = "java.naming.factory.url.pkgs"
Constant that holds the name of the environment property for specifying the list of package prefixes to use when loading in URL context factories. The value of the property should be a colon-separated list of package prefixes for the class name of the factory class that will create a URL context factory. This property may be specified in the environment, an applet parameter, a system property, or one or more resource files. The prefix com.sun.jndi.url is always appended to the possibly empty list of package prefixes. 

The value of this constant is "java.naming.factory.url.pkgs".

在jboss的debug状态下,Context context = new InitialContext(),可以看到,context里的myProps设置有两个key,就是上面这两个常量。
它们的value是:
Context.INITIAL_CONTEXT_FACTORY => org.jnp.interfaces.NamingContextFactory
Context.URL_PKG_PREFIXES => org.jnp.interfaces
哦,原来jboss用的是org.jnp.interfaces.NamingContextFactory和org.jnp.interfaces包下的类。那么,我们就开始手动构造Context吧!
org.jnp.interfaces在哪里呢?在/JBOSS_HOME/client/jnp-client.jar里,另外还需要jboss-common-client.jar(需要里面的Logger)
好,把这两个jar包拷贝到classpath里。

System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES, "org.jnp.interfaces");
Context context = new InitialContext();
DataSource ds = .....; // DS的构造看下面
context.bind("DS_abcd", ds);

似乎失败了,报错:javax.naming.CommunicationException: Receive timed out [Root exception is java.net.SocketTimeoutException: Receive timed out]
恩,jboss似乎用RMI来取DS。。。怎么办?继续往下看。

JNDI(Java Naming and Directory Interface)是sun的一个规范,所以,必然有很多实现,jboss有一套实现,apache也有一套实现,等等。
但是,因为遵循了相同的规范,结果也必然是一致的!

所以,我们可以利用apache的实现,去替换掉jboss的实现!!
怎么替换?对,就是那两个常量!!改之:
System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");
那么org.apache.naming.java.javaURLContextFactory和org.apache.naming又是在哪里呢?
在naming-java-5.0.28.jar和naming-common-5.0.28.jar里。
这回应该正确绑定上了。

DS如何构造?debug一下jboss,看看真正的DS是哪个类,new出来就可以啦。
MysqlConnectionPoolDataSource ds_1 = new MysqlConnectionPoolDataSource();
ds_1.setURL(url); // jdbc:mysql://192.168.1.100/DBTEST1?characterEncoding=utf8
ds_1.setUser(dbUser);
ds_1.setPassword(dbPassword);

关于jndi-name,还有话要说。
典型的jndi-name像这样:
  java:/comp/evn/DS_abcd
InitialContext里有这么一段代码:
    private static String getURLScheme(String str) {
        int colon_posn = str.indexOf(':');
        int slash_posn = str.indexOf('/');

        if (colon_posn > 0 && (slash_posn == -1 || colon_posn < slash_posn))
            return str.substring(0, colon_posn);

        return null;
    }
只有冒号和斜杠都存在,并且冒号在斜杠之前的话,会把冒号前的"java"作为schema使用。
不管内部如何实现,schema有没有都无所谓。
所以,某种意义上说,"java:"神马的都只是浮云!!那个冒号,只是弄得好像操作系统里那个C盘盘符后面的冒号一样,跟普通的字符没有任何区别。
如果要创建上面那个典型的jndi-name的Context,应该怎么做?
Context就像目录结构一样,而jndi名则以斜杠"/"为目录分隔符。
所以,就像创建文件夹一样,先父后子。

context.createSubcontext("java:");// 创建目录java:
context.createSubcontext("java:/comp");// 创建目录java:/comp
context.createSubcontext("java:/com/evn");// 创建目录java:/comp/evn
context.bind("java:/com/evn/DS_abcd", ds);// 创建文件java:/comp/evn/DS_abcd

或者
context.createSubcontext("java:").createSubcontext("comp").createSubcontext("evn").bind("DS_abcd", ds);

其实,createSubcontext会返回一个Context对象,就是刚刚创建的目录对象。

下面这样将会出错:
context.createSubcontext("java:");
context.createSubcontext("comp");
context.createSubcontext("evn");
context.bind("java:/com/evn/DS_abcd", ds);
结果是什么呢?就是你在根目录下,创建了3个并列的目录:"java:","comp","evn"。然后企图往一个不存在的目录"java:/comp/evn"上创建文件"DS_abcd"。当然会失败。

以上的说明和代码,都是基于jre1.5做的(jre6也测试通过)。

最后献上查看Context里所有目录所有绑定对象的信息的方法:
// 调用方法
showAll(context, 0);

private static void showAll(Context context, int step) throws NamingException {
    NamingEnumeration<NameClassPair> ne = context.list("");
    while(ne.hasMore()){
        NameClassPair e = ne.next();
        System.out.println(makeSpace(step) + e);
        Object o = context.lookup(e.getName());
        if(o instanceof Context){
            showAll((Context)o, step + 1);
        }
    }
}

private static String makeSpace(int step){
    String ret = "";
    for(int i=0;i<step;i++){
        ret += "  ";
    }
    return ret;
}

Java LDAP操作

命名和目录操作 您可以使用JNDI执行以下操作:读取操作和更新命名空间的操作。本节介绍这两个操作: l         查询对象 l         列出上下文内容 l    ...
  • liumm0000
  • liumm0000
  • 2012年09月01日 13:32
  • 14583

Linux网络编程——绑定( bind )端口需要注意的问题

所谓绑定(bind)是指别人连接我只能通过我所绑定的端口,相当于,我买了一个手机,别人要想联系我,必须要知道我的手机号码,这时候,我需要怎么办呢?我需要给手机插上电话卡,固定一个电话号码,这样别人就能...
  • lianghe_work
  • lianghe_work
  • 2015年05月06日 20:29
  • 2257

bind函数绑定

转载:http://blog.csdn.net/zhangxiangdavaid/article/details/43638747前言 函数绑定bind函数用于把某种形式的参数列表与已知的函...
  • icandoit2010
  • icandoit2010
  • 2016年12月27日 10:23
  • 375

上半年遇到的一些service绑定失败的分析

对于近期4.4和5.x上出现服务无法绑定的问题分析如下: 【具体原因分析】 一、    用户侧数据 我们从用户侧拿到的servicedump信息: 从用户侧拿到的sevices文件,都有这几特...
  • tanno1
  • tanno1
  • 2016年06月14日 23:03
  • 1070

安卓服务——bind service一个绑定式的服务

绑定式服务的介绍 学习笔记,欢迎指导。 △绑定式的服务定义:一个由bindService()方法所开启的服务成为绑定式的服务。     →其他组件可以与该服务绑定,同时可以与他进行通信(包括向服务发...
  • u010707039
  • u010707039
  • 2015年06月12日 17:07
  • 1624

关于std::function和std::bind绑定成员函数

关于std::bind绑定成员函数与虚函数的方法。 #include #include using namespace std; class A { public:     A() :m_a(...
  • x82488059
  • x82488059
  • 2015年07月28日 11:39
  • 4558

C++拾遗--bind函数绑定

C++拾遗--bind函数绑定 前言 函数绑定bind函数用于把某种形式的参数列表与已知的函数进行绑定,形成新的函数。这种更改已有函数调用模式的做法,就叫函数绑定。需要指出:bind就是函数适...
  • zhangxiangDavaid
  • zhangxiangDavaid
  • 2015年02月08日 19:16
  • 4483

linux网络编程/tcp_server中server bind失败原因的调研

问题模型:server1为服务端,在本地的9999端口监听,server2相对server1是客户端,server2启动后首先向server1发起连接,然后再8888端口监听。程序代码不在列出。先后启...
  • s25691011
  • s25691011
  • 2017年06月26日 11:34
  • 983

js事件绑定的几种方式与on()、bind()的区别

js事件绑定的几种方式与on()、bind()的区别
  • nianzhi1202
  • nianzhi1202
  • 2016年09月11日 10:13
  • 8435

React事件处理函数中绑定this的bind()函数

今天在看最新的React官方教程时发现了一个问题,开始全面使用ES6语法的React在Handling Events这节中,提到了绑定的事件处理函数要现在构造函数中使用bind()将this进行正确的...
  • Jutal_ljt
  • Jutal_ljt
  • 2016年11月28日 18:19
  • 12568
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:手动绑定Context
举报原因:
原因补充:

(最多只允许输入30个字)