`

InitialContext和lookup

阅读更多
最近因为工作需要开始学习Ejb3,遇到了一个让我很郁闷的事情,做一下小小的总结——小心new InitialContext()。

在做客户端的时候,发现连接服务器,搜索数据库,然后返回结果集。每一次执行的时候,第一次总要花更多的时间,之后每一次操作时间就要快很多了。期间找了很多方法,都行不通。一开始以为是Ejb服务器建立服务消耗时间,后来觉得不对,因为Jboss启动的时候,已经将服务启动了。经过一周的排查,终于发现原来是因为new InitialContext()消耗了大量的时间,之后的lookup()方法也会消耗一定的时间。其中,在网络状态良好的情况下,每一次new InitialContext()方法花费大概100毫秒到200毫秒之间,而每一次lookup()大概要花10毫秒到30毫秒之间。因此,决定对代码进行优化,创建了EJBHomeFactory工具类,使用到了单例模式,欢迎大家指教。以下为该类代码:

Java代码
import javax.naming.InitialContext;  
import javax.naming.NamingException;  
 
import com.cithinc.util.Tool;  
 
public class EJBHomeFactory {  
    private static EJBHomeFactory instance;  
    private InitialContext context;  
 
    private EJBHomeFactory() throws NamingException {  
        context = Tool.getInitialContext();  
    }  
 
    public static EJBHomeFactory getInstance() throws NamingException {  
        if (instance == null) {  
            instance = new EJBHomeFactory();  
        }  
        return instance;  
    }  
 
    public Object lookup(String jndiName) throws NamingException {  
        Object obj = new Object();  
        obj = context.lookup(jndiName);  
        return obj;  
    }  


import javax.naming.InitialContext;
import javax.naming.NamingException;

import com.cithinc.util.Tool;

public class EJBHomeFactory {
private static EJBHomeFactory instance;
private InitialContext context;

private EJBHomeFactory() throws NamingException {
context = Tool.getInitialContext();
}

public static EJBHomeFactory getInstance() throws NamingException {
if (instance == null) {
instance = new EJBHomeFactory();
}
return instance;
}

public Object lookup(String jndiName) throws NamingException {
Object obj = new Object();
obj = context.lookup(jndiName);
return obj;
}
}

其中,Tool.java的文件内容如下:

Java代码
import java.util.Hashtable;  
 
import javax.naming.Context;  
import javax.naming.InitialContext;  
import javax.naming.NamingException;  
 
public class Tool {  
    @SuppressWarnings("unchecked")  
    public static InitialContext getInitialContext() throws NamingException {  
        Hashtable environment = new Hashtable();  
        environment.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");  
        environment.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");  
        environment.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");  
        return new InitialContext(environment);  
    }  


import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class Tool {
@SuppressWarnings("unchecked")
public static InitialContext getInitialContext() throws NamingException {
Hashtable environment = new Hashtable();
environment.put(Context.INITIAL_CONTEXT_FACTORY,"org.jnp.interfaces.NamingContextFactory");
environment.put(Context.URL_PKG_PREFIXES,"org.jboss.naming:org.jnp.interfaces");
environment.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
return new InitialContext(environment);
}
}



然后这样调用:

Java代码
EJBHomeFactory f = EJBHomeFactory.getInstance();  
Object o = f.lookup(remote); 

EJBHomeFactory f = EJBHomeFactory.getInstance();
Object o = f.lookup(remote);

这样就可以保证只初始化一次上下文实例,节省大量的时间。

分享到:
评论
3 楼 jerry.zhao 2016-10-27  
ybzshizds 写道
这种用工厂模式解决的办法其实还是有一个问题,就是ejb容器重启后,客户端应该也要重新去new InitialContext,否则用原来的InitialContext去lookup,会抛出错。

想想后,我是这样去解决的。

...



// 缓存Context
private static Context context = initContext();

private static Context initContext() {
try {
Properties properties = new Properties();
properties.put("java.naming.factory.initial",
"org.jnp.interfaces.NamingContextFactory");
properties.put("java.naming.factory.url.pkgs",
"org.jboss.naming:org.jnp.interfaces");
properties.put("java.naming.provider.url", getRemoteUrl());
Context context = new InitialContext(properties);
return context;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

/**
* 根据指定的jndi实例化bean
*
* @param jndi
* @return
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String jndi) {
try {
Object bean = context.lookup(jndi);
return (T) bean;
} catch (Exception e) {
// 当异常时,可能目标服务器重启过,需要重新初始化context
context = initContext();
try {
Object bean = context.lookup(jndi);
return (T) bean;
} catch (Exception e1) {
e.printStackTrace();
throw new RuntimeException(e1);
}
}
}
2 楼 surpassno 2013-08-29  
1 楼 ybzshizds 2010-08-06  
这种用工厂模式解决的办法其实还是有一个问题,就是ejb容器重启后,客户端应该也要重新去new InitialContext,否则用原来的InitialContext去lookup,会抛出错。

想想后,我是这样去解决的。

为每个ejbhome,新建一个ejbHelper类

如:


package com.company.vas.ejb.helper;

import java.rmi.RemoteException;

import javax.ejb.CreateException;
import javax.naming.NamingException;

import com.company.util.Log;
import com.company.vas.ejb.Invoice;
import com.company.vas.ejb.home.InvoiceHome;

public class InvoiceHelper {

    private static final String CLASS_NAME = "InvoiceHelpler";
    private static InvoiceHome home;

    public static Invoice getInvoice() {
	try {
	    if (home == null) {
		home = (InvoiceHome) EjbGetter.getEJBHome(
						IInvoice.JNDI_NAME, InvoiceHome.class);
	     }
	     return home.create();
	} catch (NamingException e) {
			Log.error(CLASS_NAME, "getInvoice()", e.getMessage());
			home = null;
	} catch (RemoteException e) {
			Log.error(CLASS_NAME, "getInvoice()", e.getMessage());
			home = null;
	} catch (CreateException e) {
			Log.error(CLASS_NAME, "getInvoice()", e.getMessage());
			home = null;
	}
	   return null;
	}
}


package com.company.vas.ejb.helper;

import java.util.Properties;

import javax.ejb.EJBHome;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class EjbGetter {

	public static EJBHome getEJBHome(String service_jndiname, Class homeInterface) throws NamingException{
		Properties env = new Properties();
		env.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
		env.put(Context.PROVIDER_URL, "192.168.60.120:1099");
		env.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");
	
		Context ic = new InitialContext(env);
	    EJBHome ejbHome = (EJBHome)javax.rmi.PortableRemoteObject.narrow(ic.lookup(service_jndiname), homeInterface);
		
		return ejbHome;
	}
}

相关推荐

    jndi使用实例

    HelloService helloService = (HelloService) initialContext.lookup("java:global/MyEar/MyEjbModule/HelloService!com.example.HelloService"); ``` 5. **配置JNDI服务**: 在服务器端,JNDI服务需要在应用...

    JNDI连接数据库配置

    在Java开发中,JNDI(Java Naming and Directory Interface)是一种广泛使用的API,它允许Java应用程序查找并定位远程对象和服务,包括数据库连接等资源。本文将详细介绍如何利用JNDI在Tomcat环境下配置和使用数据库...

    数据池连接Name jdbc is not bound in this Context解决方案

    这里,`name`属性定义了数据源的JNDI名称,`auth`表示认证方式,`type`指明数据源类型,`maxActive`、`maxIdle`和`maxWait`分别设置了最大活动连接数、最大空闲连接数和等待超时时间,`username`和`password`是...

    JNDI注入学习1

    JNDI注入漏洞通常发生在应用程序使用`InitialContext.lookup()`方法进行查找时,如果这个查找的URI(统一资源标识符)是由用户输入控制的,攻击者就可以构造恶意URI来执行任意代码。攻击过程通常包含以下步骤: 1. ...

    EJB中JNDI的使用源码例子

    这通常涉及到调用`InitialContext`的`lookup`方法,传入EJB的JNDI名称。 3. **获取EJB引用**:查找成功后,返回的是EJB的引用,而不是实际的EJB实例。这个引用是服务器生成的代理对象,通过它可以调用EJB的方法。 ...

    jndi连接数据库配置方法

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/MyDB"); ``` 3. **获取数据库连接**: 从数据源中获取数据库连接非常简单,只需调用`getConnection()`方法即可。 ```java ...

    j2se中实现jndi的控制、管理

    Object foundObj = initialContext.lookup("my/object/name"); ``` 4. 遍历目录:通过`list()`和`listBindings()`方法可以遍历目录下的所有条目。 5. 解绑对象:使用`unbind()`方法移除JNDI树中的绑定。 ```java ...

    JavaJNDI 数据链接池及 属性文件读取数据链接信息

    - 应用程序通过Context Lookup API查找JNDI上下文中的数据源名称,例如`InitialContext().lookup("java:comp/env/jdbc/MyDB")`。 4. **属性文件读取数据链接信息**: - 数据连接的配置信息,如URL、用户名、密码...

    jndi配置

    4. **JNDI Lookup**:查找操作是通过`InitialContext`类的`lookup()`方法完成的,它需要一个名字作为参数,这个名字可以是绝对名(全局唯一的)或相对名(相对于当前命名上下文)。 5. **JNDI Bind**:绑定操作将一...

    jndi 数据库连接池 & 监听

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/myDataSource"); ``` 3. **获取和释放连接**:通过数据源获取数据库连接,执行SQL操作后,及时释放连接回连接池,避免资源浪费...

    JNDI代码样例

    4. **类型转换和调用**:查找成功后,`lookup()`方法返回的是一个`Object`类型,你需要将其转换为适当的类型,这通常是通过`Class.forName()`和`newInstance()`完成的。转换完成后,你就可以调用DLL中的方法了。 `...

    JNDI简单应用示例

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/MyDB"); ``` 3. **绑定资源**:JNDI还允许你将对象绑定到命名空间中。例如,你可以创建一个新的数据源对象并将其绑定到特定的...

    基于Java的实例开发源码-EJB中JNDI的使用源码例子.zip

    MyRemoteInterface myBean = (MyRemoteInterface) initialContext.lookup("ejb:/MyApp/MyModule/MyBean!com.example.MyRemoteInterface"); ``` 在这个例子中,`com.sun.jndi.rmi.registry.RegistryContextFactory`...

    j2ee JNDI 存储 和 读取程序 weblogic

    JNDI 提供了两种主要操作:查找(lookup)和绑定(bind)。查找允许我们根据名字获取对象,而绑定则将一个名字与特定的对象关联起来。 在J2EE中,JNDI通常用于存储和读取资源,如数据源(DataSource)。数据源是一...

    DBCP 数据库连接池JNDI连接 学习笔记

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/myDB"); Connection conn = dataSource.getConnection(); ``` 4. **优势与优化** - JNDI结合DBCP使得数据库连接管理更加集中...

    JNDI解析

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/myDataSource"); Connection connection = dataSource.getConnection(); ``` 综上所述,JNDI是Java中一种重要的服务发现和管理...

    javaservlet连接mysql数据库.pdf

    在Servlet中,我们可以通过`InitialContext`和`lookup`方法来查找服务器配置的数据源,然后从中获取连接。例如: ```java Context initialContext = new InitialContext(); DataSource dataSource = (DataSource...

    jdni配置

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/MyDB"); System.out.println("Data Source found: " + dataSource); } catch (NamingException e) { e.printStackTrace(); }...

    Jndi连接池

    DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/MyDB"); Connection conn = dataSource.getConnection(); ``` 这段代码首先创建了一个`InitialContext`实例,然后通过`lookup`...

    Java通用Dao包括JDBC和JNDI两种连接方式

    2. 查找数据源:DataSource dataSource = (DataSource) initialContext.lookup("java:comp/env/jdbc/yourDataSourceName")。 3. 获取连接:Connection conn = dataSource.getConnection()。 4. 使用连接并关闭:执行...

Global site tag (gtag.js) - Google Analytics