JNDI(Java Naming and Directory Interface, Java命名和目錄接口),說白了,就是通過配置一些xml文件,方便用戶直接調用API使用某些通用的資源。
舉個簡單的例子,如果在tomcat中部署了很多應用,應用都需要使用同一個數據庫,如果每個應用都在代碼中配置數據庫的連接,肯定是很麻煩的。
所以通過JNDI就可以簡單的通過 InitialContext 獲取到統一配置的資源,簡化代碼的編寫。
本篇主要內容按照上面來講解,其中樣例部分主要說明一下通用javabeans和userdatabase,javamail很少使用,JDBC又很大眾化,網上很多資料,可以參考 JNDI配置數據源,就不做重復工作了。
為了避免篇幅過長,自定義JNDI則留到后面再說。
配置
這里說明的內容,不是每次編碼必須的步驟,只是先說明一下都有哪些地方涉及到配置。
web.xml
這部分內容配置資源引用,舉個例子:
<resource-env-ref> <description> 資源配置說明 </description> <resource-env-ref-name> bean/MyBeanFactory </resource-env-ref-name> <resource-env-ref-type> com.mycompany.MyBean </resource-env-ref-type> </resource-env-ref>
在web.xml中可以配置三種形式的資源:
<env-entry> 用於配置一些應用程序的變量,比如參考 tomcat下部署solr。
<resource-ref> 資源引用,通常是一個對象工廠資源,比如典型的JDBC數據源。
<resource-env-ref> 資源環境引用,他是servlet2.4中新引入的特性,在resource-ref的基礎上,可以更簡單方便的配置信息而不用經過身份驗證,比如簡單的javabean。
context.xml
這部分定義其引用的資源工廠以及一些必要的額外信息,比如:
<Context ...> ... <Resource name="bean/MyBeanFactory" auth="Container" type="com.mycompany.MyBean" factory="org.apache.naming.factory.BeanFactory" bar="23"/> ... </Context>
這里需要注意的是,<context>標簽有三種配置位置:
1 在conf/server.xml中;
2 在conf/context.xml中;
3 在/webapps/xxx/WEB-INF/context.xml;
這三種的區別是,server.xml與context.xml類似都是所有應用通用的,但是context.xml只是把它分離出來單獨形成了一個文件而已。在WEB-INF/下的context.xml則是應用自己的,所以如果不想把某些信息公開,放在這里就可以了。
在<context>中可以配置如下的標簽:
<Environment> 配置一些鍵值對變量,類似於<env-entry>
<Resource> 配置一些資源的類型和變量信息,類似於<resouce-ref>
<ResourceLink> 指定資源鏈接到全局上下文中的配置,比如在server.xml中配置了全局的一個標簽,這里可以直接引入該標簽名字。
<Transaction> 添加工廠資源實例
server.xml
這個文件中可以配置<context>標簽,前面說過了;還可以配置全局JNDI資源,比如默認的tomcat就配置了一個userdatabase的資源
<GlobalNamingResources> <!-- Editable user database that can also be used by UserDatabaseRealm to authenticate users --> <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/> </GlobalNamingResources>
它就是一個全局的配置。
使用
配置好相應的xml文件,就可以在代碼中直接通過創建Context實例,例如在配置數據源中:
Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env");
//上面寫法都是不變的,下面這行中lookup中的字符串就是配置的JNDI名稱,
//比如context中的<resource name="xxx">或者web.xml中的<resource-env-ref-name> DataSource ds = (DataSource)envCtx.lookup("jdbc/EmployeeDB"); Connection conn = ds.getConnection(); ... use this connection to access the database ... conn.close();
樣例
最后參考幾個樣例,了解一下編碼細節。
1 通用JavaBean資源
首先,創建自己的javabean,並配置其構造方法設置初始化值。

package com.mycompany; public class MyBean { //配置變量foo private String foo = "xingoo"; public String getFoo() { return (this.foo); } public void setFoo(String foo) { this.foo = foo; } //配置變量bar private int bar = 0; public int getBar() { return (this.bar); } public void setBar(int bar) { this.bar = bar; } }
然后,配置web.xml中資源引用

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>JSPTest</display-name> <resource-env-ref> <description> javaBean測試 </description> <resource-env-ref-name> bean/MyBeanFactory </resource-env-ref-name> <resource-env-ref-type> com.mycompany.MyBean </resource-env-ref-type> </resource-env-ref> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</welcome-file> </welcome-file-list> </web-app>
接下來,在tomcat conf/context.xml中配置工廠資源引用,並設置初始化的值

<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --><!-- The contents of this file will be loaded for each web application --><Context> <!-- Default set of monitored resources --> <WatchedResource>WEB-INF/web.xml</WatchedResource> <!-- Uncomment this to disable session persistence across Tomcat restarts --> <!-- <Manager pathname="" /> --> <!-- Uncomment this to enable Comet connection tacking (provides events on session expiration as well as webapp lifecycle) --> <!-- <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" /> --> <Resource name="bean/MyBeanFactory" auth="Container" type="com.mycompany.MyBean" factory="org.apache.naming.factory.BeanFactory" bar="23"/> </Context>
最后在JSP中調用lookup方法,獲得實例。

<%@ page language="java" contentType="text/html; charset=utf-8" import="java.net.*,javax.naming.*,com.mycompany.*" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>test JNDI</title> </head> <body> <h1>test JNDI</h1> <hr> <% Context initCtx = new InitialContext(); Context envCtx = (Context) initCtx.lookup("java:comp/env"); MyBean bean = (MyBean) envCtx.lookup("bean/MyBeanFactory"); %> foo:<%=bean.getFoo() %><br> bar:<%=bean.getBar() %> </body> </html>
運行效果:
由於foo沒有在<Resouce>標簽中設置值,因此讀取的還是默認的值,而bar則為設置的值。
2 Userdatabase使用
userdatabase即用戶數據庫,主要用於配置用戶信息,以供某些應用進行授權驗證。
關於其他的配置比如web.xml的Realm配置這里就不多說了,看看server.xml中如何設置全局資源引用:
<?xml version="1.0" encoding="UTF-8"?> <Server port="8005" shutdown="SHUTDOWN"> ... <GlobalNamingResources> <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/> </GlobalNamingResources> <Service name="Catalina"> ... <Engine defaultHost="localhost" name="Catalina"> <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/> ... </Engine> </Service> </Server>
其中<GlobalNamingResources>配置了全局命名資源UserDatabase,后面再進行Realm域管理時,直接通過resourceName鏈接到該資源。
3 JNDI數據源配置
這部分就不多說了,參考下面的JNDI配置數據源即可。
參考
【1】tomcat 6 JNDI resource : http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html
【2】通過JNDI配置數據源:http://www.blogjava.net/supercrsky/articles/174931.html