首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 冲浪宝典-> 联络聊天
Servlet中jdbc应用高级篇-JSP教程,Jsp/Servlet
作者:网友供稿 点击:18
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 
 jdbc使用数据库url来说明数据库驱动程序。数据库url类似于通用的url,但sun 在定义时作了一点简化,其语法如下:

jdbc::[node]/[database]

  其中子协议(subprotocal)定义驱动程序类型,node提供网络数据库的位置和端口号,后面跟可选的参数。例如:

string url=”jdbc:inetdae:myserver:1433?language=us-english&sql7=true”

  表示采用inetdae驱动程序连接1433端口上的myserver数据库服务器,选择语言为美国英语,数据库的版本是mssql server 7.0。

  java应用通过指定drivermanager装入一个驱动程序类。语法如下:

class.forname(“”);



class.forname(“”).newinstance();

  然后,drivermanager创建一个特定的连接:

connection connection=drivermanager.getconnection(url,login,password);

  connection接口通过指定数据库位置,登录名和密码连接数据库。connection接口创建一个statement实

例执行需要的查询:

statement stmt=connection.createstatement();

  statement具有各种方法(api),如executequery,execute等可以返回查询的结果集。结果集是一个resultset对象。具体的可以通过jdbc开发文档查看。可以sun的站点上下载

下面例子来说明:

import java.sql.*; // 输入jdbc package

string url = "jdbc:inetdae:myserver:1433";// 主机名和端口

string login = "user";// 登录名

string password = "";// 密码

try {

  drivermanager.setlogstream(system.out); file://为显示一些的信息打开一个流

  file://调用驱动程序,其名字为com.inet.tds.tdsdriver

  file://class.forname("com.inet.tds.tdsdriver");

  file://设置超时

  drivermanager.setlogintimeout(10);

  file://打开一个连接

  connection connection = drivermanager.getconnection(url,login,password);

  file://得到数据库驱动程序版本

   databasemetadata conmd = connection.getmetadata();

   system.out.println("driver name:\t" + conmd.getdrivername());

   system.out.println("driver version:\t" + conmd.getdriverversion());

  file://选择数据库
  connection.setcatalog( "mydatabase");

  file://创建statement


  statement st = connection.createstatement();

  file://执行查询

  resultset rs = st.executequery("select * from mytable");

  file://取得结果,输出到屏幕

  while (rs.next()){

     for(int j=1; j<=rs.getmetadata().getcolumncount(); j++){

     system.out.print( rs.getobject(j)+"\t");

     }

   system.out.println();

  }

  file://关闭对象

  st.close();

    connection.close();

  } catch(exception e) {

    e.printstacktrace();

  }

  一个动态的网站频繁地从数据库中取得数据来构成html页面。每一次请求一个页面都会发生数据库操作。但连接数据库却是一个需要消耗大量时间的工作,因为请求连接需要建立通讯,分配资源,进行权限认证。这些工作很少能在一两秒内完成。所以,建立一个连接,然后再后续的查询中都使用此连接会大大地提高性能。因为servlet可以在不同的请求间保持状态,因此采用数据库连接池是一个直接的解决方案。

  servlet在服务器的进程空间中驻留,可以方便而持久地维护数据库连接。接下来,我们介绍一个完整的连接池的实现。在实现中,有一个连接池管理器管理连接池对象,其中每一个连接池保持一组数据库连接对象,这些对象可为任何servlet所使用。

一、数据库连接池类 dbconnectionpool,提供如下的方法:

  1、从池中取得一个打开的连接;

  2、将一个连接返回池中;

  3、在关闭时释放所有的资源,并关闭所有的连接。

  另外,dbconnectionpool还处理连接失败,比如超时,通讯失败等错误,并且根据预定义的参数限制池中的连接数。

二、管理者类,dbconnetionmanager,是一个容器将连接池封装在内,并管理所有的连接池。它的方法有:

  1、 调用和注册所有的jdbc驱动程序;

  2、 根据参数表创建dbconnectionpool对象;

  3、 映射连接池的名字和dbconnectionpool实例;

  4、 当所有的连接客户退出后,关闭全部连接池。

这些类的实现,以及如何在servlet中使用连接池的应用在随后的文章中讲解

  dbconnectionpool类代表一个由url标识的数据库连接池。前面,我们已经提到,jdbc的url由三个部分组成:协议标识(总是jdbc),子协议标识(例如,odbc.oracle),和数据库标识(跟特定的数据库有关)。连接池也具有一个名字,供客户程序引用。另外,连接池还有一个用户名,一个密码和一个最大允许连接数。如果web应用允许所有的用户使用某些数据库操作,而另一些操作是有限制的,则可以创建两个连接池,具有同样的url,不同的user name和password,分别处理两类不同的操作权限。现把dbconnectionpool详细介绍如下:

  一、dbconnectionpool的构造


  构造函数取得上述的所有参数:

public dbconnectionpool(string name, string url, string user,

string password, int maxconn) {

this.name = name;

this.url = url;

this.user = user;

this.password = password;

this.maxconn = maxconn;

}

  将所有的参数保存在实例变量中。


  二、从池中打开一个连接


  dbconnectionpool提供两种方法来检查连接。两种方法都返回一个可用的连接,如果没有多余的连接,则创建一个新的连接。如果最大连接数已经达到,第一个方法返回null,第二个方法则等待一个连接被其他进程释放。

public synchronized connection getconnection() {

connection con = null;

if (freeconnections.size() > 0) {

// pick the first connection in the vector

// to get round-robin usage

con = (connection) freeconnections.firstelement();

freeconnections.removeelementat(0);

try {

if (con.isclosed()) {

log("removed bad connection from " + name);

// try again recursively

con = getconnection();

}

}

catch (sqlexception e) {

log("removed bad connection from " + name);

// try again recursively

con = getconnection();

}

}

else if (maxconn == 0 || checkedout < maxconn) {

con = newconnection();

}

if (con != null) {

checkedout++;

}

return con;

}

  所有空闲的连接对象保存在一个叫freeconnections 的vector中。如果存在至少一个空闲的连接,getconnection()返回其中第一个连接。下面,将会看到,进程释放的连接返回到freeconnections的末尾。这样,最大限度地避免了数据库因一个连接不活动而意外将其关闭的风险。

  再返回客户之前,isclosed()检查连接是否有效。如果连接被关闭了,或者一个错误发生,该方法递归调用取得另一个连接。

  如果没有可用的连接,该方法检查是否最大连接数被设置为0表示无限连接数,或者达到了最大连接数。如果可以创建新的连接,则创建一个新的连接。否则,返回null。

  方法newconnection()用来创建一个新的连接。这是一个私有方法,基于用户名和密码来确定是否可以创建新的连接。

private connection newconnection() {

connection con = null;

try {

if (user == null) {

con = drivermanager.getconnection(url);

}

else {

con = drivermanager.getconnection(url, user, password);

}

log("created a new connection in pool " + name);

}

catch (sqlexception e) {

log(e, "can not create a new connection for " + url);

return null;

}

return con;

}

  jdbc的drivermanager提供一系列的getconnection()方法,可以使用url和用户名,密码等参数创建一个连接。

  第二个getconnection()方法带有一个超时参数 timeout,当该参数指定的毫秒数表示客户愿意为一个连接等待的时间。这个方法调用前一个方法。


public synchronized connection getconnection(long timeout) {

long starttime = new date().gettime();

connection con;

while ((con = getconnection()) == null) {

try {

wait(timeout);

}

catch (interruptedexception e) {}

if ((new date().gettime() - starttime) >= timeout) {

// timeout has expired

return null;

}

}

return con;

}


  局部变量starttime初始化当前的时间。一个while循环首先尝试获得一个连接,如果失败,wait()函数被调用来等待需要的时间。后面会看到,wait()函数会在另一个进程调用notify()或者notifyall()时返回,或者等到时间流逝完毕。为了确定wait()是因为何种原因返回,我们用开始时间减去当前时间,检查是否大于timeout。如果结果大于timeout,返回null,否则,在此调用getconnection()函数。


  四、将一个连接返回池中


  dbconnectionpool类中有一个freeconnection方法以返回的连接作为参数,将连接返回连接池。


public synchronized void freeconnection(connection con) {

// put the connection at the end of the vector

freeconnections.addelement(con);

checkedout--;

notifyall();

}

  连接被加在freeconnections向量的最后,占用的连接数减1,调用notifyall()函数通知其他等待的客户现在有了一个连接。

五、关闭


  大多数servlet引擎提供完整的关闭方法。数据库连接池需要得到通知以正确地关闭所有的连接。dbconnectionmanager负责协调关闭事件,但连接由各个连接池自己负责关闭。方法relase()由dbconnectionmanager调用。
public synchronized void release() {

enumeration allconnections = freeconnections.elements();

while (allconnections.hasmoreelements()) {

connection con = (connection) allconnections.nextelement();

try {

con.close();

log("closed connection for pool " + name);

}

catch (sqlexception e) {

log(e, "can not close connection for pool " + name);

}

}

freeconnections.removeallelements();

}

本方法遍历freeconnections向量以关闭所有的连接。

  dbconnetionmanager的构造函数是私有函数,以避免其他类创建其实例。

private dbconnectionmanager() {

init();

}

  dbconnetionmanager的客户调用getinstance()方法来得到该类的单一实例的引用。

static synchronized public dbconnectionmanager getinstance() {

if (instance == null) {

instance = new dbconnectionmanager();

}

clients++;

return instance;

}

  单一的实例在第一次调用时创建,以后的调用返回该实例的静态应用。一个计数器纪录所有的客户数,直到客户释放引用。这个计数器在以后用来协调关闭连接池。


  一、初始化

  构造函数调用一个私有的init()函数初始化对象。

private void init() {

inputstream is = getclass().getresourceasstream("/db.properties");

properties dbprops = new properties();

try {

dbprops.load(is);

}

catch (exception e) {

system.err.println("can not read the properties file. " +

"make sure db.properties is in the classpath");

return;

}

string logfile = dbprops.getproperty("logfile",

"dbconnectionmanager.log");

try {

log = new printwriter(new filewriter(logfile, true), true);

}

catch (ioexception e) {

system.err.println("can not open the log file: " + logfile);

log = new printwriter(system.err);

}

loaddrivers(dbprops);

createpools(dbprops);

}

  方法getresourceasstream()是一个标准方法,用来打开一个外部输入文件。文件的位置取决于类加载器,而标准的类加载器从classpath开始搜索。db.properties文件是一个porperties格式的文件,保存在连接池中定义的key-value对。下面一些常用的属性可以定义:

   drivers 以空格分开的jdbc驱动程序的列表

   logfile 日志文件的绝对路径

  每个连接池中还使用另一些属性。这些属性以连接池的名字开头:

   .url数据库的jdbc url

   .maxconn最大连接数。0表示无限。

   .user连接池的用户名

   .password相关的密码

  url属性是必须的,其他属性可选。用户名和密码必须和所定义的数据库匹配。

  下面是windows平台下的一个db.properties文件的例子。有一个instantdb连接池和一个通过odbc连接的access数据库的数据源,名字叫demo。

drivers=sun.jdbc.odbc.jdbcodbcdriver jdbc.idbdriver

logfile=d:\\user\\src\\java\\dbconnectionmanager\\log.txt

idb.url=jdbc:idb:c:\\local\\javawebserver1.1\\db\\db.prp

idb.maxconn=2

access.url=jdbc:odbc:demo

access.user=demo

access.password=demopw

注意,反斜线在windows平台下必须双写。

  初始化方法init()创建一个porperties对象并装载db.properties文件,然后读取日志文件属性。如果日志文件没有命名,则使用缺省的名字dbconnectionmanager.log在当前目录下创建。在此情况下,一个系统错误被纪录。

方法loaddrivers()将指定的所有jdbc驱动程序注册,装载。

private void loaddrivers(properties props) {

string driverclasses = props.getproperty("drivers");

stringtokenizer st = new stringtokenizer(driverclasses);

while (st.hasmoreelements()) {

string driverclassname = st.nexttoken().trim();

try {

driver driver = (driver)

class.forname(driverclassname).newinstance();

drivermanager.registerdriver(driver);

drivers.addelement(driver);

log("registered jdbc driver " + driverclassname);

}

catch (exception e) {

log("can not register jdbc driver: " +

driverclassname + ", exception: " + e);

}

}

}

  loaddrivers()使用stringtokenizer将dirvers属性分成单独的driver串,并将每个驱动程序装入java虚拟机。驱动程序的实例在jdbc 的drivermanager中注册,并加入一个私有的向量drivers中。向量drivers用来关闭和注销所有的驱动程序。

  然后,dbconnectionpool对象由私有方法createpools()创建。

private void createpools(properties props) {

enumeration propnames = props.propertynames();

while (propnames.hasmoreelements()) {

string name = (string) propnames.nextelement();

if (name.endswith(".url")) {

string poolname = name.substring(0, name.lastindexof("."));

string url = props.getproperty(poolname + ".url");

if (url == null) {

log("no url specified for " + poolname);

continue;

}

string user = props.getproperty(poolname + ".user");

string password = props.getproperty(poolname + ".password");

string maxconn = props.getproperty(poolname + ".maxconn", "0");

int max;

try {

max = integer.valueof(maxconn).intvalue();

}

catch (numberformatexception e) {

log("invalid maxconn value " + maxconn + " for " +

poolname);

max = 0;

}

dbconnectionpool pool =

new dbconnectionpool(poolname, url, user, password, max);

pools.put(poolname, pool);

log("initialized pool " + poolname);

}

}

}

  一个枚举对象保存所有的属性名,如果属性名带有.url结尾,则表示是一个连接池对象需要被实例化。创建的连接池对象保存在一个hashtable实例变量中。连接池名字作为索引,连接池对象作为值。
  二、得到和返回连接

  dbconnectionmanager提供getconnection()方法和freeconnection方法,这些方法有客户程序使用。所有的方法以连接池名字所参数,并调用特定的连接池对象。

public connection getconnection(string name) {

dbconnectionpool pool = (dbconnectionpool) pools.get(name);

if (pool != null) {

return pool.getconnection();

}

return null;

}



public connection getconnection(string name, long time) {

dbconnectionpool pool = (dbconnectionpool) pools.get(name);

if (pool != null) {

return pool.getconnection(time);

}

return null;

}

public void freeconnection(string name, connection con) {

dbconnectionpool pool = (dbconnectionpool) pools.get(name);

if (pool != null) {

pool.freeconnection(con);

}

}

  三、关闭

  最后,由一个release()方法,用来完好地关闭连接池。每个dbconnectionmanager客户必须调用getinstance()方法引用。有一个计数器跟踪客户的数量。方法release()在客户关闭时调用,技术器减1。当最后一个客户释放,dbconnectionmanager关闭所有的连接池。

list 11-14

public synchronized void release() {

// wait until called by the last client

if (--clients != 0) {

return;

}



enumeration allpools = pools.elements();

while (allpools.hasmoreelements()) {

dbconnectionpool pool = (dbconnectionpool) allpools.nextelement();

pool.release();

}

enumeration alldrivers = drivers.elements();

while (alldrivers.hasmoreelements()) {

driver driver = (driver) alldrivers.nextelement();

try {

drivermanager.deregisterdriver(driver);

log("deregistered jdbc driver " + driver.getclass().getname());

}

catch (sqlexception e) {

log(e, "can not deregister jdbc driver: " +

driver.getclass().getname());

}

}

}

当所有连接池关闭,所有jdbc驱动程序也被注销。

  现在我们结合dbconnetionmanager和dbconnectionpool类来讲解servlet中连接池的使用:

  一、首先简单介绍一下servlet的生命周期:

  servlet api定义的servlet生命周期如下:

1、 servlet 被创建然后初始化(init()方法)。

2、 为0个或多个客户调用提供服务(service()方法)。

3、 servlet被销毁,内存被回收(destroy()方法)。

  二、servlet中使用连接池的实例

  使用连接池的servlet有三个阶段的典型表现是:

1. 在init()中,调用dbconnectionmanager.getinstance()然后将返回的引用保存在实例变量中。


2. 在sevice()中,调用getconnection(),执行一系列数据库操作,然后调用freeconnection()归还连接。

3. 在destroy()中,调用release()来释放所有的资源,并关闭所有的连接。

  下面的例子演示如何使用连接池。

import java.io.*;

import java.sql.*;

import javax.servlet.*;

import javax.servlet.http.*;

public class testservlet extends httpservlet {

private dbconnectionmanager connmgr;



public void init(servletconfig conf) throws servletexception {

super.init(conf);

connmgr = dbconnectionmanager.getinstance();

}


public void service(httpservletrequest req, httpservletresponse res)

throws ioexception {

res.setcontenttype("text/html");

printwriter out = res.getwriter();

connection con = connmgr.getconnection("idb");

if (con == null) {

out.println("cant get connection");

return;

}

resultset rs = null;

resultsetmetadata md = null;

statement stmt = null;

try {

stmt = con.createstatement();

rs = stmt.executequery("select * from employee");

md = rs.getmetadata();

out.println("
employee data
");

while (rs.next()) {

out.println("
");

for (int i = 1; i < md.getcolumncount(); i++) {

out.print(rs.getstring(i) + ", ");

}

}

stmt.close();

rs.close();

}

catch (sqlexception e) {

e.printstacktrace(out);

}

connmgr.freeconnection("idb", con);

}

public void destroy() {

connmgr.release();

super.destroy();

}

}


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·Java Unicode转义字符的小小研究-JSP教程,Java技巧及代码
·实现VB与EXCEL的无缝连接-.NET教程,VB.Net语言
·在ASP.NET里通过URL传递参数得到乱码的解决方法-ASP教程,ASP应用
·实例讲解:Java中的SOAP技术-JSP教程,Java技巧及代码
·Session过期问题-ASP教程,ASP应用
·设计模式笔记-抽象工厂模式-.NET教程,评论及其它
·JSP标准标记库促进了网页的开发-JSP教程,Jsp/Servlet
·在Remoting Server上取得Remoting Client的IP地址-ASP教程,ASP应用
·使用JSP标记库校验用户输入-JSP教程,Jsp/Servlet
·c#中DataGrid的数据新增编辑删除操作代码-.NET教程,数据库应用
最新文章
·xp也能享受vista readyboost闪存加速_windows xp
·c# 3.0新特性系列:隐含类型var_c#教程
·如此做google广告,月赚10万美金不成问题_网赚技巧
·王通:个人博客的赚钱之道_网赚技巧
·这一年来风风雨雨-再访中客宋陈磊_站长访谈
·个人网站的定位推广和赚钱-访中国建站站长_站长访谈
·祥瑞网方文春:从800元到6000万元_站长访谈
·行业类、专业性成功网站给个人站长的启示_站长访谈
·网站推广 新招老招齐用上_站长心得
·widnows vista工具栏添加快速启动tabletpc图标_windows vista
相关主题
  • servlet实现访问次数的例子_jsp技巧
  • servlet动态产生jpeg图像的例子_jsp技巧
  • Servlet与Web服务-JSP教程,Jsp/Servlet
  • Servlet中如何捕获Session事件?-JSP教程,Jsp/Servlet
  • Servlet和JSP知识复习(2)Servlet基础-JSP教程,Jsp/Servlet
  • 西部数码虚拟主机

    友情链接
    CNNIC 西部数码
    万网 自助建站
    虚拟主机 asp空间
    域名注册 域名
    域名申请 主页空间
    论坛空间 网站空间
    国际域名 虚拟空间
    空间租用 DDOS防火墙
    成都主机托管 四川主机托管
    主机租用 服务器租用
    网站目录 自助建站
    虚拟主机 网址大全
    软件下载
    自助链接
    虚拟主机资讯 特价虚拟主机
    版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
    关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
    特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
    发表评论 打印  刷新     关闭