Tomcat 6 --- JNDI詳解

xingoo發表於2015-06-11

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;
    }
}
View Code

  然後,配置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>
View Code

  接下來,在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>
View Code

  最後在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>
View Code

  執行效果:

    

  由於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

相關文章