天天看點

JavaEE命名服務與JNDI

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");

繼續閱讀