jndi(Java Naming and Directory Interface,Java命名和目录接口)是一组在Java应用中访问命名和目录服务的API。命名服务将名称和对象联系起来,使得我们可以用名称

访问对象。目录服务是一种命名服务,在这种服务里,对象不但有名称,还有属性。

tomcat配置jndi有全局配置和局部配置。大致的有以下三种配置方式:


第一种:全局配置。

1)在tomcat的conf文件夹下的context.xml配置文件中加入:


<Resource name="jndi/mybatis"                  auth="Container"                  type="javax.sql.DataSource"                  driverClassName="com.mysql.jdbc.Driver"                  url="jdbc:mysql://localhost:3306/appdb"                  username="root"                  password="123456"                  maxActive="20"                  maxIdle="10"                  maxWait="10000"/>


2)在项目的web.xml中加入资源引用:


<resource-ref>   <description>JNDI DataSource</description>   <res-ref-name>jndi/mybatis</res-ref-name>   <res-ref-type>javax.sql.DataSource</res-ref-type>   <res-auth>Container</res-auth> </resource-ref>


其中res-ref-name值要和context.xml的name值一致。


3)jndi测试方法:


public void testJNDI() throws NamingException, SQLException{         Context ctx = new InitialContext();         DataSource ds = (DataSource) ctx.lookup("java:comp/env/jndi/mybatis");         Connection conn = ds.getConnection();         System.out.println(conn.isClosed());      }


4)在jsp中调用加载jndi方式,不可以直接用main方法测试,必须通过启动容器从jsp中调用:


TestPageAccessURL test = new TestPageAccessURL();         test.testJNDI();


第二种:局部配置(不推荐)。

1)在tomcat的server.xml的<host>标签内,添加:


<Context path="/demo_jndi" docBase="/demo_jndi">            <Resource              name="jndi/mybatis"              type="javax.sql.DataSource"              driverClassName="com.mysql.jdbc.Driver"              maxIdle="2"              maxWait="5000"              username="root"              password="123456"              url="jdbc:mysql://localhost:3306/appdb"              maxActive="4"/>         </Context>


其他配置同第一种方式。


第三种:局部配置。

1)在项目的META-INFO下面新建context.xml。加入:


<?xml version="1.0" encoding="UTF-8"?> <Context>     <Resource name="jndi/mybatis"                  auth="Container"                  type="javax.sql.DataSource"                  driverClassName="com.mysql.jdbc.Driver"                  url="jdbc:mysql://localhost:3306/appdb"                  username="root"                  password="123456"                  maxActive="20"                  maxIdle="10"                  maxWait="10000"/>     </Context>


其他配置同第一种方式。

总结:如果要配置局部的话,推荐使用第三种方式,这样不依赖tomcat了。但是还是推荐使用第一种方式好,虽然依赖tomat,但是是全局的,而且可以配置
多个。对于以后切换使用方便。
在项目的web.xml中添加的资源引用可有可无。


实验---用第三种方式配置:

创建web项目

contex.xml


<?xml version="1.0" encoding="UTF-8"?> <Context>     <Resource name="jndi/mysql"                  auth="Container"                  type="javax.sql.DataSource"                  driverClassName="com.mysql.jdbc.Driver"                  url="jdbc:mysql://localhost:3306/ask"                  username="root"                  password="root"                  maxActive="20"                  maxIdle="10"                  maxWait="10000"/>     </Context>


JndiTestServlet.java


package org.ccnt.jndi;  import java.io.IOException; import java.io.PrintWriter; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement;  import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.sql.DataSource;  /**  * Servlet implementation class JndiTestServlet  */ @WebServlet("/JndiTestServlet") public class JndiTestServlet extends HttpServlet {     private static final long serialVersionUID = 1L;             /**      * @see HttpServlet#HttpServlet()      */     public JndiTestServlet() {         super();         // TODO Auto-generated constructor stub     }      /**      * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)      */     protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {         // TODO Auto-generated method stub         PrintWriter writer = response.getWriter();         writer.println("get");         try {             testJndi();         } catch (NamingException | SQLException e) {             // TODO Auto-generated catch block             e.printStackTrace();         }         writer.println("end");     }      /**      * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)      */     protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {         // TODO Auto-generated method stub     }          public void testJndi() throws NamingException, SQLException {         Context ctx = new InitialContext();         DataSource ds = (DataSource) ctx.lookup("java:comp/env/jndi/mysql");         Connection conn = ds.getConnection();         Statement stat = conn.createStatement();         ResultSet rs = stat.executeQuery("select COUNT(*) FROM diseases");         while (rs.next()) {             System.out.println(rs.getString(1));         }         System.out.println("connect ok\n" + conn.isClosed());     }  }


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_3_0.xsd" id="WebApp_ID" version="3.0">   <display-name>Jndi</display-name>      <resource-ref>     <description>JNDI DataSource</description>     <res-ref-name>jndi/mysql</res-ref-name>     <res-type>javax.sql.DataSource</res-type>     <res-auth>Container</res-auth>   </resource-ref>      <servlet>       <servlet-name>JndiTest</servlet-name>       <servlet-class>org.ccnt.jndi.JndiTestServlet</servlet-class>   </servlet>   <servlet-mapping>       <servlet-name>JndiTest</servlet-name>       <url-pattern>/test</url-pattern>   </servlet-mapping>      <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>



测试:

浏览器输入:​http://localhost:8080/Jndi/test">​http://localhost:8080/Jndi/test​

浏览器结果:


get end


控制台结果:


1511 connect ok false



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

参考和扩展:

​tomcat下jndi的三种配置方式​

​JNDI教程​

JNDI的扩展: 

JNDI在满足了数据源配置的要求的基础上,还进一步扩充了作用:所有与系统外部的资源的引用,都可以通过JNDI定义和引用。 


所以,在J2EE规范中,J2EE 中的资源并不局限于 JDBC 数据源。引用的类型有很多,其中包括资源引用(已经讨论过)、环境实体和 EJB 引用。特别是 EJB 引用,它暴露了 JNDI 在 J2EE 中的另外一项关键角色:查找其他应用程序组件。 


EJB 的 JNDI 引用非常类似于 JDBC 资源的引用。在服务趋于换的环境中,这是一种很有效的方法。可以对应用程序架构中所得到的所有组件进行这类配置管理,从 EJB 组件到 JMS 队列和主题,再到简单配置字符串或其他对象,这可以降低随时间的推移服务变更所产生的维护成本,同时还可以简化部署,减少集成工作。 外部资源”。 

总结: 

J2EE 规范要求所有 J2EE 容器都要提供 JNDI 规范的实现。JNDI 在 J2EE 中的角色就是“交换机” —— J2EE 组件在运行时间接地查找其他组件、资源或服务的通用机制。在多数情况下,提供 JNDI 供应者的容器可以充当有限的数据存储,这样管理员就可以设置应用程序的执行属性,并让其他应用程序引用这些属性(Java 管理扩展(Java Management Extensions,JMX)也可以用作这个目的)。JNDI 在 J2EE 应用程序中的主要角色就是提供间接层,这样组件就可以发现所需要的资源,而不用了解这些间接性。

在 J2EE 中,JNDI 是把 J2EE 应用程序合在一起的粘合剂,JNDI 提供的间接寻址允许跨企业交付可伸缩的、功能强大且很灵活的应用程序。这是 J2EE 的承诺,而且经过一些计划和预先考虑,这个承诺是完全可以实现的。