weblogic启动后会产生一个RMI Register的service并管理JNDI tree
weblogic.xml: http://download.oracle.com/docs/cd/E13222_01/wls/docs81/webapp/weblogic_xml.html#1054859
The reference-descriptor element maps a name used in the Web application to the JNDI name of a server resource.
<resource-description>
<res-ref-name>jdbc/myds</res-ref-name>
<jndi-name>myDataSource</jndi-name>
</resource-description>
web.xml: http://download.oracle.com/docs/cd/E13222_01/wls/docs81/webapp/web_xml.html#1045815
The optional resource-ref element defines a reference lookup name to an external resource. This allows the servlet code to look up a resource by a "virtual" name that is mapped to the actual location at deployment time.
<resource-ref>
<res-ref-name>jdbc/myds</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
配置好引用之后我们可以通过如下的方式使用名称jdbc/myds(这样可以避免在java代码中直接调用JNDI名称):
下面是另外一个例子:
<ejb-ref>
<ejb-ref-name>ejb/foohome</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.foo.bar.FooHome</home>
<remote>com.foo.bar.Foo</remote>
</ejb-ref>
<!-- weblogic.xml entry: -->
<ejb-reference-description>
<ejb-ref-name>ejb/foohome</ejb-ref-name>
<jndi-name>FooHome</jndi-name>
</ejb-reference-description>
FooHome fh = (FooHome) PortableRemoteObject.narrow(home, FooHome.class);
同样的,这里也避免了在java代码中显示的调用JNDI名称。
实际上不需要上面的2段也可以得到应用服务器中的资源(只需要得到一个InitalContext,当JNDI服务启动之后就可以通过lookup得到需要的资源了)。
下面是一个利用RMI访问weblogic的例子:
2 Properties properties = new Properties();--Properties extends HashTable
3 properties.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory");
4 properties.put(Context.PROVIDER_URL, "t3://localhost:7001");
5 InitialContext initialcontext = new InitialContext(properties);
6 Object obj = null;
7 obj = initialcontext.lookup("jndiname");
8 TestHome testHome = (TestHome)PortableRemoteObject.narrow(obj, com.TestHome.class);
9 Test test = testHome.create();
10
11 String str = test.getDOM(s,s1,s2);
12 Document document = XmlUtil.String2DOM(str);
13 ......
14
15 -------------------------------------------
16 --EJBHome:
17 public interface TestHome
18 extends EJBHome
19 {
20
21 public abstract Test create()
22 throws RemoteException, CreateException;
23 }
24
25 --EJBObject
26 public interface Test
27 extends EJBObject
28 {
29
30 public abstract String getDOM(String s, String s1, String s2)
31 throws RemoteException, Exception;
32
33 public abstract Document getDOM(Document document, Document document1, String s)
34 throws RemoteException, Exception;
35 }
利用jndi获取数据源的一个例子
利用J2EE建立一个Application Client Project如下:
首先启动weblogic,建立一个连接池Test Pool, 然后利用此连接池创建一个DataSource:TEST_DS
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.rmi.PortableRemoteObject;
import javax.sql.DataSource;
public class Main {
public static void main(String[] args) throws Exception{
Context ctx = null;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory");
env.put(Context.PROVIDER_URL, "t3://localhost:7001");
ctx = new InitialContext(env);
Object obj = ctx.lookup("TEST_DS");
//通过PortableObject获取conn对象,效率比较高
DataSource ds = (DataSource) PortableRemoteObject.narrow(obj, DataSource.class);
Connection conn = ds.getConnection();
/* 利用反射也可以获取到conn,但是效率没有上面的快
Class class1 = obj.getClass();
Class paramType[] = new Class[0];
Object param[] = new Object[0];
Method method = class1.getMethod("getConnection", paramType);
Connection conn = (Connection)method.invoke(obj, param);
*/
Statement stmt = conn.createStatement();
String sql = "select sysdate from dual";
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getDate(1));
}
}
public Main() {
super();
}
}
Tomcat下JNDI:
logger.error(e);
e.printStackTrace();