JavaEE應用往往需要通路資料庫、JMS服務等各種資源。相對于JavaEE應用來說,一個具體的資源就是一個能夠提供連接配接資料庫伺服器或JMS消息系統的對象。每個資源都有一個唯一的的名字作為辨別,這個名字就是JNDI命名。
JNDI (Java Naming and DirectoryInterface)就是Java命名服務的标準接口。從JavaEE 7的标準體系開始,JNDI已經成為JavaSE的組成部分,以命名與目錄服務的形式提供給應用。
在JavaEE伺服器中,資源首先在伺服器的容器中配置,然後通過命名與目錄服務将資源及其JNDI命名綁定在一起釋出,JavaEE應用不必考慮資源庫的具體類型和配置參數,隻要通過JNDI命名就可以找到對應的資源,并進而通路具體的資源。JNDI為JavaEE應用提供了一種統一的、松耦合的定位并通路資源的方式。
1. JNDI的命名空間
顯然,應用能夠通路資源的前提條件是必須首先通過JNDI命名找到需要的資源,而且這種JNDI的命名必須遵守統一的命名規範。為了區分JNDI命名的作用範圍,命名與目錄服務将JNDI命名的環境上下文劃分為若幹個命名空間,将資源及其JNDI命名以“name/object”對的形式加入到命名空間中,進而實作資源的JNDI釋出并供應用查找通路。
JavaEE提供了如下4種标準的命名空間:
- java:comp,目前元件範圍内有效的命名空間,如伺服器提供的預設JDBC資料源、預設JMS連接配接工廠等
- java:module,目前類庫子產品範圍内有效的命名空間
- java:app,目前應用範圍内有效的命名空間
- java:global,整個伺服器範圍内有效的命名空間
除了上述4種标準的命名空間,WildFly還另外提供了如下2種命名空間,他們都在整個伺服器範圍内有效:
- java:/
- java:jboss
其中可供遠端JNDI通路的命名空間是java:jboss的子空間java:jboss/exported。
2. WildFly伺服器提供了如下4種釋出JNDI命名的方式:
- 在web.xml檔案中使用<env-entry>元素
- 在standalone.xml檔案中配置naming子系統
- 使用标準的JNDI API
- 在标準的JNDI API的基礎上結合使用WildFly的Modules/Extensions API
3.JNDI命名的查找
JavaEE應用中查找JNDI命名的方式有多種,具體可以分為在本地(伺服器上)查找和在遠端(伺服器上)查找。
1) 對于本地JNDI命名查找,WildFly提供了如下3種方式:
- 資源注入,例如@Resource(lookup="...")
- 标準JNDI API,例如new InitialContext().lookup("...");
- http-remoting JNDI lookup,例如env.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");
注意,對于第三種方式,由于WildFly不再支援remoting port(4447)等端口,而是隻有一個http port(預設8080),是以JNDI命名查找時的URL也從remote://localhost:4447的形式變為http-remoting://localhost:8080。
2) 對于遠端JNDI命名查找,在JBoss AS 7(不含)之前,使用jnp查找JNDI命名,但是由于安全性的控制粒度太大而被JBoss AS 7放棄。JBoss AS 7提供了如下2種查找遠端JNDI命名的方式:
- EJB client API,針對無狀态EJB的lookup進行了優化
例如:
env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
(MyRemoteInterface) remoteContext.lookup("ejb:myapp/myejbjar/MyEjbName\!com.test.MyRemoteInterface");
(MyStatefulRemoteInterface) remoteContext.lookup("ejb:myapp/myejbjar/MyStatefulName\!comp.test.MyStatefulRemoteInterface?stateful");
- jboss-remote-naming(不建議用于EJB)
例如:
env.put(Context.PROVIDER_URL, "http-remoting://remoteIP:8080");