第十八天 “恰到好处”与“好中择优”—JNDI的使用

        5月12日,晴天。“纷纷红紫已成尘,布谷声中夏令新。夹路桑麻行不尽,始知身是太平人。”

    1、恰到好处的JDBC

     在学生的练习、案例和小规模的开发,JDBC使用的很多。配置简单,规范,一眼就能明白是主要原因。但也存在问题,所以企业的实际开发时,多用JNDI。

         主要问题:

         (1)数据库服务器名称 、用户名和口令都可能需要改变,由此引发JDBC URL需要修改;

         (2)数据库可能更换产品,比如开发使用MySQL,实际部署改为DB2或者Oracle,引发JDBC驱动程序包和类名需要修改;

           (3)随着实际使用终端的增加,原配置的连接池参数可能需要调整。而JDBC的API中没有提供连接池的方法。

       2、DataSource对象

        在Java语言中,DataSource对象就是一个代表数据源实体的对象。应用程序通过一个连接来访问数据源,那么一个DataSource对象就是用于提供连接数据源的工具。DataSource接口提供了两个方法用于建立和数据源的连接,使用DataSource对象建立和数据库的连接比起使用DriverManager接口更加高效,虽然两者的使用范围都很相似,并且都提供了方法用于建立和数据库的连接

        但两者之间的区别更加明显,和DriverManager不同,一个DataSource对象能够识别和描述它所代表的数据源的属性,而DataSource对象的工作和JNDI(Javatm Naming and Directory Interface)具有密切的关系, DataSource的建立、发布、独立于应用程序的管理都依靠JNDI技术。

      JDBC2.0提供了javax.sql.DataSource接口,它负责建立与数据库的连接,在应用程序访问数据库时不需要编写连接数据库的代码,可以直接从数据源获得数据库连接。在DataSource中事先建立了多个数据库连接,这些数据库连接保存在连接池(Connect Pool)中。Java程序访问数据库时,只需要从连接池中取出空闲状态的数据库连接;当程序访问数据库结束,再将数据库连接放回连接池。

     3、好中择优的JNDI

      可以简单地把JNDI理解为一种将对象和名字绑定的技术,对象工厂负责生产出对象,这些对象都和惟一的名字绑定。外部程序可以通过名字来获取对某个对象的引用。

      DataSource对象是由Tomcat提供的,因此不能在程序中采用创建一个实例的方式来生产DataSource对象,而需要采用Java的另一个技术JNDI,来获得DataSource对象的引用。

         Tomcat把DataSource作为一种可以配置的JNDI资源来处理。生成DataSource对象的工厂为org.apache.commons.dbcp.BasicDataSourceFactory。

      在javax.naming包中提供了Context接口,该接口提供了将对象和名字绑定,以及通过名字检索对象的方法。Context中的主要方法有:
       bind(String name,Object object):将对象与一个名字绑定。
       lookup(String name):返回与指定的名字绑定的对象。

      4、Tomcat中数据源的配置

        自tomcat 5.5起数据库连接池的配置和以前的不同了,不推荐在server.xml中进行配置,而是在%Tomcat_Home%\webapps\yourApp\META-INF\context.xml中进行配置才是更好的方法。

         而不是以前版本%Tomcat_Home%\conf\context.xml文件。这样就可以在不同的web应用下单独配置连接池了,且Tomcat会自动重载。当然你也可以更改%Tomcat_Home%\conf下的context.xml文件,将所有web应用下的连接池进行统一配置。
       因为server.xml是不可动态重加载的资源,服务器一旦启动了以后,要修改这个文件,就得重启服务器才能重新加载。而context.xml文件则不然,tomcat服务器会定时去扫描这个文件。一旦发现文件被修改(时间戳改变了),就会自动重新加载这个文件,而不需要重启服务器。

             注:这一步容易报错:Cannot create JDBC driver of class for connect URL null 一定要记得把你的MYSQL5.0驱动jar包考到Tomcat6.0 的lib文件下。
          5、Web应用中使用数据源
       javax.naming.Context提供了查找JNDI Resource的接口,可以通过三个步骤来使用数据源对象:

       A.获得对数据源的引用:
    Context ctx = new InitalContext();
              DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/BookDb");

       B.获得数据库连接对象:
             Connection con = ds.getConnection();
  C.返回数据库连接到连接池:
             con.close();

           在连接池中使用close()方法和在非连接池中使用close()方法的区别是:前者仅仅是把数据库连接对象返回到数据库连接池中,是连接对象又恢复到空闲状态,而非关闭数据库连接,而后者将直接关闭和数据库的连接。

              6、实例说明

        (1)使用MySQL建个数据库jsp_db,供测试之用。

drop database IF EXISTS jsp_db;
create database if not exists jsp_db;

USE jsp_db;
DROP TABLE IF EXISTS student;
CREATE TABLE student (
  sid varchar(20) NOT NULL,
  name varchar(30) default NULL,
  sex int(1) default NULL,
  phone varchar(16) default NULL,
  birth date default NULL,
  Constraint primary key pk_student(sid)
  ) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

               (2)编写context.xml

           context.xml的位置:在Eclipse中放的位置,如下图

第十八天 “恰到好处”与“好中择优”—JNDI的使用_第1张图片

               

           如果直接放在在Tomcat下面,就放在\conf文件夹下。       

<?xml version="1.0" encoding="UTF-8"?>
 <Context >
        <Resource name="jdbc/bn" 
                  auth="Container"
                  type="javax.sql.DataSource"
                  maxActive="30" 
                  maxIdle="10" 
                  maxWait="10000"
                  driverClassName="com.mysql.jdbc.Driver"
                  url="jdbc:mysql://localhost:3306/jsp_db?characterEncoding=gb2312"
                  username="root" password="root" />       
 </Context>
相关说明: name      为当前数据源JNDI的名字,可以随意设定;
auth       为验证方式;
type       资源类型;
 maxActiv     为连接池最大激活的连接数,设为0表示无限制;
maxIdle 为连接池最大空闲的连接数,数据库连接的最大空闲时间。超过空闲时间,
            数据库连接将被标记为不可用,然后被释放。设为0表示无限制;
maxWait       为连接最大的等待时间,单位毫秒,如果超过此时间将接到异常。设为-1表示无限制;
driverClassName 为驱动引用;
url                 为连接数据库的连接地址;
username             为数据库的一个用户名;
password             为username的密码;

        (3)编写测试代码

<!--测试连接池-->
<%@ page contentType="text/html; charset=gb2312"%>
<%@ page import="javax.naming.Context"%>
<%@ page import="javax.sql.DataSource"%>
<%@ page import="javax.naming.InitialContext"%>
<%@ page import="java.sql.*"%>

<%
	//request.setCharacterEncoding("UTF-8");
	DataSource ds = null;
	try {
		Context initCtx = new InitialContext();
		//从Context中查找数据源
		ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/bn");
		if (ds != null) {
			out.println("已经获得DataSource!");
			out.println("<br>");
			Connection conn = ds.getConnection();
			java.sql.Statement stmt = conn.createStatement();
			stmt.executeUpdate("insert into student(sid,name,sex,phone,birth) values('034','王五',1,'8725698','1986/06/01')");
			out.println("数据:'034','王五',1,'8725698','1986/06/01' 添加成功");
			//关闭连接、释放资源    
			stmt.close();
			conn.close();
		} else
			out.println("连接失败!");
	} catch (Exception ne) {
		out.println(ne);
	}
%>
   (4)运行结果

第十八天 “恰到好处”与“好中择优”—JNDI的使用_第2张图片

          说明:1、java:comp/env 是环境命名上下文(environment naming context(ENC)),是在EJB规范1.1以后引入的,引入这个是为了解决原来JNDI查找所引起的冲突问题,也是为了提高EJB或者J2EE应用的移植性。

                    2、java:comp/env/jdbc/bn(虚地址)   ------>    映射描述符   ------>        jdbc/bn (实际的地址)。

                          3、逻辑名jdbc/bn作为数据源名称的好处是为了提高可移植性,移植的时候只需要把配置文件改一下就可以,而应用程序可不用改动,JNDI名字其实说白了就是把JNDI名放到配置文件里。大笑

               4、通过jndi配置多个数据源。

<?xml version="1.0" encoding="UTF-8"?>
 <Context >
        <Resource name="jdbc/bn" 
                  auth="Container"
                  type="javax.sql.DataSource"
                  maxActive="30" 
                  maxIdle="10" 
                  maxWait="10000"
                  driverClassName="com.mysql.jdbc.Driver"
                  url="jdbc:mysql://localhost:3306/jsp_db?characterEncoding=gb2312"
                  username="root" password="root" />  
        <Resource name="jdbc/biz" 
                  auth="Container"
                  type="javax.sql.DataSource"
                  maxActive="30" maxIdle="10" maxWait="10000"
                  driverClassName="com.mysql.jdbc.Driver"
                  url="jdbc:mysql://localhost:3306/bizdemo"
                  username="root" password="root" />             
 </Context>
               5、 再编写一个测试代码

<%@ page language="java" contentType="text/html; charset=utf-8"
	pageEncoding="utf-8"%>
<%@page import="java.sql.*"%>
<%@page import="javax.naming.*"%>
<%@page import="javax.sql.DataSource"%>
<!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>Tomcat6.0 JNDI 测试</title>
</head>
<body>
	This is my JSP page.
	<br> JNDI配置测试开始 ...
	<br>
	<%
		try {
			//初始化 Context 上下文对象;   
			Context ctx = new InitialContext();
			//Context envContext = (Context) ctx.lookup("java:/comp/env");
			//DataSource ds = (DataSource) envContext.lookup("jdbc/biz"); //查找配置    
			//方法二:    
			DataSource ds = (DataSource) ctx
					.lookup("java:comp/env/jdbc/biz");
			Connection conn = ds.getConnection();
			conn.close();
			out.println("JNDI数据源配置成功了!");
		} catch (NamingException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	%>
</body>
</html>
            运行结果

第十八天 “恰到好处”与“好中择优”—JNDI的使用_第3张图片






你可能感兴趣的:(eclipse,Web,jdbc,架构,JNDI)