乐观 发表于 2015-1-18 11:32:46

JAVA教程之Servlet中jdbc使用初级篇

比如模式、敏捷方法什么的,这些思想好,但是实施的人没有理解而且没有正确运用这些知识导致了开发周期的延长。比如说对象,通过getName()方法不能获取对象的名字。servlet|初级JDBC利用数据库URL来讲明数据库驱动程序。数据库URL相似于通用的URL,但SUN在界说时作了一点简化,其语法以下:

Jdbc::/

  个中子协定(subprotocal)界说驱动程序范例,node供应收集数据库的地位和端标语,前面跟可选的参数。比方:

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

  暗示接纳inetdae驱动程序毗连1433端口上的myserver数据库服务器,选择言语为美国英语,数据库的版本是mssqlserver7.0。

  java使用经由过程指定DriverManager装进一个驱动程序类。语法以下:

Class.forName(“”);



Class.forName(“”).newInstance();

  然后,DriverManager创立一个特定的毗连:

Connectionconnection=DriverManager.getConnection(url,login,password);

  Connection接口经由过程指定命据库地位,登录名和暗码毗连数据库。Connection接口创立一个Statement实

例实行必要的查询:

Statementstmt=connection.createStatement();

  Statement具有各类办法(API),如executeQuery,execute等能够前往查询的了局集。了局集是一个ResultSet对象。详细的能够经由过程jdbc开辟文档检察。能够sun的站点高低载

上面例子来讲明:

importjava.sql.*;//输出JDBCpackage

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

Stringlogin="user";//登录名

Stringpassword="";//暗码

try{

  DriverManager.setLogStream(System.out);file://为显现一些的信息翻开一个流

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

  file://Class.forName("com.inet.tds.TdsDriver");

  file://设置超时

  DriverManager.setLoginTimeout(10);

  file://翻开一个毗连

  Connectionconnection=DriverManager.getConnection(url,login,password);

  file://失掉数据库驱动程序版本

   DatabaseMetaDataconMD=connection.getMetaData();

   System.out.println("DriverName:        "+conMD.getDriverName());

   System.out.println("DriverVersion:        "+conMD.getDriverVersion());

  file://选择数据库
  connection.setCatalog("MyDatabase");

  file://创立Statement


  Statementst=connection.createStatement();

  file://实行查询

  ResultSetrs=st.executeQuery("SELECT*FROMmytable");

  file://获得了局,输入到屏幕

  while(rs.next()){

     for(intj=1;j<=rs.getMetaData().getColumnCount();j++){

     System.out.print(rs.getObject(j)+"        ");

     }

   System.out.println();

  }

  file://封闭对象

  st.close();

    connection.close();

  }catch(Exceptione){

    e.printStackTrace();

  }

  一个静态的网站频仍地从数据库中获得数据来组成html页面。每次哀求一个页面城市产生数据库操纵。但毗连数据库倒是一个必要损耗大批工夫的事情,由于哀求毗连必要创建通信,分派资本,举行权限认证。这些事情很少能在一两秒内完成。以是,创建一个毗连,然后再后续的查询中都利用此毗连会年夜年夜地进步功能。由于servlet能够在分歧的哀求间坚持形态,因而接纳数据库毗连池是一个间接的办理计划。

  Servlet在服务器的历程空间中驻留,能够便利而耐久地保护数据库毗连。接上去,我们先容一个完全的毗连池的完成。在完成中,有一个毗连池办理器办理毗连池对象,个中每个毗连池坚持一组数据库毗连对象,这些对象可为任何servlet所利用。

1、数据库毗连池类DBConnectionPool,供应以下的办法:

  1、从池中获得一个翻开的毗连;

  2、将一个毗连前往池中;

  3、在封闭时开释一切的资本,并封闭一切的毗连。

  别的,DBConnectionPool还处置毗连失利,好比超时,通信失利等毛病,而且依据预界说的参数限定池中的毗连数。

2、办理者类,DBConnetionManager,是一个容器将毗连池封装在内,并办理一切的毗连池。它的办法有:

  1、挪用和注册一切的jdbc驱动程序;

  2、依据参数表创立DBConnectionPool对象;

  3、映照毗连池的名字和DBConnectionPool实例;

  4、当一切的毗连客户加入后,封闭全体毗连池。

这些类的完成,和怎样在servlet中利用毗连池的使用在随后的文章中解说

  DBConnectionPool类代表一个由url标识的数据库毗连池。后面,我们已提到,jdbc的url由三个部分构成:协定标识(老是jdbc),子协定标识(比方,odbc.oracle),和数据库标识(跟特定的数据库有关)。毗连池也具有一个名字,供客户程序援用。别的,毗连池另有一个用户名,一个暗码和一个最年夜同意毗连数。假如web使用同意一切的用户利用某些数据库操纵,而另外一些操纵是无限制的,则能够创立两个毗连池,具有一样的url,分歧的username和password,分离处置两类分歧的操纵权限。现把DBConnectionPool具体先容以下:

  1、DBConnectionPool的机关


  机关函数获得上述的一切参数:

publicDBConnectionPool(Stringname,StringURL,Stringuser,

Stringpassword,intmaxConn){

this.name=name;

this.URL=URL;

this.user=user;

this.password=password;

this.maxConn=maxConn;

}

  将一切的参数保留在实例变量中。


  2、从池中翻开一个毗连


  DBConnectionPool供应两种办法来反省毗连。两种办法都前往一个可用的毗连,假如没有过剩的毗连,则创立一个新的毗连。假如最年夜毗连数已到达,第一个办法前往null,第二个办法则守候一个毗连被其他历程开释。

publicsynchronizedConnectiongetConnection(){

Connectioncon=null;

if(freeConnections.size()>0){

//PickthefirstConnectionintheVector

//togetround-robinusage

con=(Connection)freeConnections.firstElement();

freeConnections.removeElementAt(0);

try{

if(con.isClosed()){

log("Removedbadconnectionfrom"+name);

//Tryagainrecursively

con=getConnection();

}

}

catch(SQLExceptione){

log("Removedbadconnectionfrom"+name);

//Tryagainrecursively

con=getConnection();

}

}

elseif(maxConn==0||checkedOut<maxConn){

con=newConnection();

}

if(con!=null){

checkedOut++;

}

returncon;

}

  一切余暇的毗连对象保留在一个叫freeConnections的Vector中。假如存在最少一个余暇的毗连,getConnection()前往个中第一个毗连。上面,将会看到,历程开释的毗连前往到freeConnections的开端。如许,最年夜限制地制止了数据库因一个毗连不举动而不测将其封闭的风险。

  再前往客户之前,isClosed()反省毗连是不是无效。假如毗连被封闭了,大概一个毛病产生,该办法递回挪用获得另外一个毗连。

  假如没有可用的毗连,该办法反省是不是最年夜毗连数被设置为0暗示无穷毗连数,大概到达了最年夜毗连数。假如能够创立新的毗连,则创立一个新的毗连。不然,前往null。

  办法newConnection()用来创立一个新的毗连。这是一个公有办法,基于用户名和暗码来断定是不是能够创立新的毗连。

privateConnectionnewConnection(){

Connectioncon=null;

try{

if(user==null){

con=DriverManager.getConnection(URL);

}

else{

con=DriverManager.getConnection(URL,user,password);

}

log("Createdanewconnectioninpool"+name);

}

catch(SQLExceptione){

log(e,"Cannotcreateanewconnectionfor"+URL);

returnnull;

}

returncon;

}

  jdbc的DriverManager供应一系列的getConnection()办法,可使用url和用户名,暗码等参数创立一个毗连。

  第二个getConnection()办法带有一个超时参数timeout,当该参数指定的毫秒数暗示客户乐意为一个毗连守候的工夫。这个办法挪用前一个办法。


publicsynchronizedConnectiongetConnection(longtimeout){

longstartTime=newDate().getTime();

Connectioncon;

while((con=getConnection())==null){

try{

wait(timeout);

}

catch(InterruptedExceptione){}

if((newDate().getTime()-startTime)>=timeout){

//Timeouthasexpired

returnnull;

}

}

returncon;

}


  部分变量startTime初始化以后的工夫。一个while轮回起首实验取得一个毗连,假如失利,wait()函数被挪用来守候必要的工夫。前面会看到,Wait()函数会在另外一个历程挪用notify()大概notifyAll()时前往,大概比及工夫流逝终了。为了断定wait()是由于何种缘故原由前往,我们用入手下手工夫减往以后工夫,反省是不是年夜于timeout。假如了局年夜于timeout,前往null,不然,在此挪用getConnection()函数。


  4、将一个毗连前往池中


  DBConnectionPool类中有一个freeConnection办法以前往的毗连作为参数,将毗连前往毗连池。


publicsynchronizedvoidfreeConnection(Connectioncon){

//PuttheconnectionattheendoftheVector

freeConnections.addElement(con);

checkedOut--;

notifyAll();

}

  毗连被加在freeConnections向量的最初,占用的毗连数减1,挪用notifyAll()函数关照其他守候的客户如今有了一个毗连。

5、封闭


  年夜多半servlet引擎供应完全的封闭办法。数据库毗连池必要失掉关照以准确地封闭一切的毗连。DBConnectionManager卖力和谐封闭事务,但毗连由各个毗连池本人卖力封闭。办法relase()由DBConnectionManager挪用。
publicsynchronizedvoidrelease(){

EnumerationallConnections=freeConnections.elements();

while(allConnections.hasMoreElements()){

Connectioncon=(Connection)allConnections.nextElement();

try{

con.close();

log("Closedconnectionforpool"+name);

}

catch(SQLExceptione){

log(e,"Cannotcloseconnectionforpool"+name);

}

}

freeConnections.removeAllElements();

}

本办法遍历freeConnections向量以封闭一切的毗连。

  DBConnetionManager的机关函数是公有函数,以免其他类创立实在例。

privateDBConnectionManager(){

init();

}

  DBConnetionManager的客户挪用getInstance()办法来失掉该类的单一实例的援用。

staticsynchronizedpublicDBConnectionManagergetInstance(){

if(instance==null){

instance=newDBConnectionManager();

}

clients++;

returninstance;

}

  单一的实例在第一次挪用时创立,今后的挪用前往该实例的静态使用。一个计数器记录一切的客户数,直到客户开释援用。这个计数器在今后用来和谐封闭毗连池。


  1、初始化

  机关函数挪用一个公有的init()函数初始化对象。

privatevoidinit(){

InputStreamis=getClass().getResourceAsStream("/db.properties");

PropertiesdbProps=newProperties();

try{

dbProps.load(is);

}

catch(Exceptione){

System.err.println("Cannotreadthepropertiesfile."+

"Makesuredb.propertiesisintheCLASSPATH");

return;

}

StringlogFile=dbProps.getProperty("logfile",

"DBConnectionManager.log");

try{

log=newPrintWriter(newFileWriter(logFile,true),true);

}

catch(IOExceptione){

System.err.println("Cannotopenthelogfile:"+logFile);

log=newPrintWriter(System.err);

}

loadDrivers(dbProps);

createPools(dbProps);

}

  办法getResourceAsStream()是一个尺度办法,用来翻开一个内部输出文件。文件的地位取决于类加载器,而尺度的类加载器从classpath入手下手搜刮。Db.properties文件是一个Porperties格局的文件,保留在毗连池中界说的key-value对。上面一些经常使用的属性能够界说:

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

   logfile日记文件的相对路径

  每一个毗连池中还利用另外一些属性。这些属性以毗连池的名字开首:

   .url数据库的JDBCURL

   .maxconn最年夜毗连数。0暗示无穷。

   .user毗连池的用户名

   .password相干的暗码

  url属性是必需的,其他属性可选。用户名和暗码必需和所界说的数据库婚配。

  上面是windows平台下的一个db.properties文件的例子。有一个InstantDB毗连池和一个经由过程odbc毗连的access数据库的数据源,名字叫demo。

drivers=sun.jdbc.odbc.JdbcOdbcDriverjdbc.idbDriver

logfile=D:usersrcjavaDBConnectionManagerlog.txt

idb.url=jdbc:idb:c:localjavawebserver1.1dbdb.prp

idb.maxconn=2

access.url=jdbc:odbc:demo

access.user=demo

access.password=demopw

注重,反斜线在windows平台下必需双写。

  初始化办法init()创立一个Porperties对象并装载db.properties文件,然后读取日记文件属性。假如日记文件没有定名,则利用缺省的名字DBConnectionManager.log在以后目次下创立。在此情形下,一个体系毛病被记录。

办法loadDrivers()将指定的一切jdbc驱动程序注册,装载。

privatevoidloadDrivers(Propertiesprops){

StringdriverClasses=props.getProperty("drivers");

StringTokenizerst=newStringTokenizer(driverClasses);

while(st.hasMoreElements()){

StringdriverClassName=st.nextToken().trim();

try{

Driverdriver=(Driver)

Class.forName(driverClassName).newInstance();

DriverManager.registerDriver(driver);

drivers.addElement(driver);

log("RegisteredJDBCdriver"+driverClassName);

}

catch(Exceptione){

log("CannotregisterJDBCdriver:"+

driverClassName+",Exception:"+e);

}

}

}

  loadDrivers()利用StringTokenizer将dirvers属性分红独自的driver串,并将每一个驱动程序装进java假造机。驱动程序的实例在JDBC的DriverManager中注册,并到场一个公有的向量drivers中。向量drivers用来封闭和刊出一切的驱动程序。

  然后,DBConnectionPool对象由公有办法createPools()创立。

privatevoidcreatePools(Propertiesprops){

EnumerationpropNames=props.propertyNames();

while(propNames.hasMoreElements()){

Stringname=(String)propNames.nextElement();

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

StringpoolName=name.substring(0,name.lastIndexOf("."));

Stringurl=props.getProperty(poolName+".url");

if(url==null){

log("NoURLspecifiedfor"+poolName);

continue;

}

Stringuser=props.getProperty(poolName+".user");

Stringpassword=props.getProperty(poolName+".password");

Stringmaxconn=props.getProperty(poolName+".maxconn","0");

intmax;

try{

max=Integer.valueOf(maxconn).intValue();

}

catch(NumberFormatExceptione){

log("Invalidmaxconnvalue"+maxconn+"for"+

poolName);

max=0;

}

DBConnectionPoolpool=

newDBConnectionPool(poolName,url,user,password,max);

pools.put(poolName,pool);

log("Initializedpool"+poolName);

}

}

}

  一个列举对象保留一切的属性名,假如属性名带有.url开头,则暗示是一个毗连池对象必要被实例化。创立的毗连池对象保留在一个Hashtable实例变量中。毗连池名字作为索引,毗连池对象作为值。
  2、失掉和前往毗连

  DBConnectionManager供应getConnection()办法和freeConnection办法,这些办法有客户程序利用。一切的办法以毗连池名字所参数,并挪用特定的毗连池对象。

publicConnectiongetConnection(Stringname){

DBConnectionPoolpool=(DBConnectionPool)pools.get(name);

if(pool!=null){

returnpool.getConnection();

}

returnnull;

}



publicConnectiongetConnection(Stringname,longtime){

DBConnectionPoolpool=(DBConnectionPool)pools.get(name);

if(pool!=null){

returnpool.getConnection(time);

}

returnnull;

}

publicvoidfreeConnection(Stringname,Connectioncon){

DBConnectionPoolpool=(DBConnectionPool)pools.get(name);

if(pool!=null){

pool.freeConnection(con);

}

}

  3、封闭

  最初,由一个release()办法,用来无缺地封闭毗连池。每一个DBConnectionManager客户必需挪用getInstance()办法援用。有一个计数器跟踪客户的数目。办法release()在客户封闭时挪用,手艺器减1。当最初一个客户开释,DBConnectionManager封闭一切的毗连池。

List11-14

publicsynchronizedvoidrelease(){

//Waituntilcalledbythelastclient

if(--clients!=0){

return;

}



EnumerationallPools=pools.elements();

while(allPools.hasMoreElements()){

DBConnectionPoolpool=(DBConnectionPool)allPools.nextElement();

pool.release();

}

EnumerationallDrivers=drivers.elements();

while(allDrivers.hasMoreElements()){

Driverdriver=(Driver)allDrivers.nextElement();

try{

DriverManager.deregisterDriver(driver);

log("DeregisteredJDBCdriver"+driver.getClass().getName());

}

catch(SQLExceptione){

log(e,"CannotderegisterJDBCdriver:"+

driver.getClass().getName());

}

}

}

当一切毗连池封闭,一切jdbc驱动程序也被刊出。

  如今我们分离DBConnetionManager和DBConnectionPool类来说解servlet中毗连池的利用:

  1、起首复杂先容一下Servlet的性命周期:

  ServletAPI界说的servlet性命周期以下:

1、Servlet被创立然后初始化(init()办法)。

2、为0个或多个客户挪用供应服务(service()办法)。

3、Servlet被烧毁,内存被接纳(destroy()办法)。

  2、servlet中利用毗连池的实例

  利用毗连池的servlet有三个阶段的典范体现是:

1.在init()中,挪用DBConnectionManager.getInstance()然后将前往的援用保留在实例变量中。


2.在sevice()中,挪用getConnection(),实行一系列数据库操纵,然后挪用freeConnection()偿还毗连。

3.在destroy()中,挪用release()来开释一切的资本,并封闭一切的毗连。

  上面的例子演示怎样利用毗连池。

importjava.io.*;

importjava.sql.*;

importjavax.servlet.*;

importjavax.servlet.http.*;

publicclassTestServletextendsHttpServlet{

privateDBConnectionManagerconnMgr;



publicvoidinit(ServletConfigconf)throwsServletException{

super.init(conf);

connMgr=DBConnectionManager.getInstance();

}


publicvoidservice(HttpServletRequestreq,HttpServletResponseres)

throwsIOException{

res.setContentType("text/html");

PrintWriterout=res.getWriter();

Connectioncon=connMgr.getConnection("idb");

if(con==null){

out.println("Cantgetconnection");

return;

}

ResultSetrs=null;

ResultSetMetaDatamd=null;

Statementstmt=null;

try{

stmt=con.createStatement();

rs=stmt.executeQuery("SELECT*FROMEMPLOYEE");

md=rs.getMetaData();

out.println("
Employeedata
");

while(rs.next()){

out.println("
");

for(inti=1;i<md.getColumnCount();i++){

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

}

}

stmt.close();

rs.close();

}

catch(SQLExceptione){

e.printStackTrace(out);

}

connMgr.freeConnection("idb",con);

}

publicvoiddestroy(){

connMgr.release();

super.destroy();

}

}


net程序员的大部门代码都靠控件拖拽完成的,虽然java也有,但是无论从美观和速度上都没发和.net比。java程序员都是代码完成的,所以java程序员常戏称.net程序员是操作员,呵呵。

若天明 发表于 2015-1-21 09:53:17

http://www.jdon.com/去下载,或到同济技术论坛的服务器ftp://nro.shtdu.edu.cn去下,安装上有什么问题,可以到论坛上去提问。

第二个灵魂 发表于 2015-1-27 23:48:25

让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。

再见西城 发表于 2015-2-2 11:25:16

是一种使用者不需花费很多时间学习的语言

再现理想 发表于 2015-2-6 16:36:22

接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。

透明 发表于 2015-2-7 12:42:24

Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。

仓酷云 发表于 2015-2-10 07:15:19

你现在最缺的是实际的工作经验,而不是书本上那些凭空想出来的程序。

乐观 发表于 2015-2-22 22:40:40

是一种为 Internet发展的计算机语言

不帅 发表于 2015-3-1 18:19:04

Jive的资料在很多网站上都有,大家可以找来研究一下。相信你读完代码后,会有脱胎换骨的感觉。遗憾的是Jive从2.5以后就不再无条件的开放源代码,同时有licence限制。不过幸好还有中国一流的Java程序员关注它,外国人不开源了,中国人就不能开源吗?这里向大家推荐一个汉化的Jive版本—J道。Jive(J道版)是由中国Java界大名 鼎鼎的banq在Jive 2.1版本基础上改编而成, 全中文,增加了一些实用功能,如贴图,用户头像和用户资料查询等,而且有一个开发团队在不断升级。你可以访问banq的网站

兰色精灵 发表于 2015-3-10 21:54:21

Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。

活着的死人 发表于 2015-3-15 21:31:40

当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢?

小魔女 发表于 2015-3-20 09:48:50

吧,现在很流行的Structs就是它的一种实现方式,不过Structs用起来实在是很繁,我们只要学习其精髓即可,我们完全可以设计自己的MVC结构。然后你再研究一下软件Refactoring (重构)和极限XP编程,相信你又会上一个台阶。 做完这些,你不如整理一下你的Java代码,把那些经典的程序和常见的应用整理出来,再精心打造一番,提高其重用性和可扩展性。你再找几个志同道合的朋友成立一个工作室吧

若相依 发表于 2015-3-25 04:20:08

设计模式是高级程序员真正掌握面向对象核心思想的必修课。设计模式并不是一种具体"技术",它讲述的是思想,它不仅仅展示了接口或抽象类在实际案例中的灵活应用和智慧

小女巫 发表于 2015-3-26 11:17:51

一直感觉JAVA很大,很杂,找不到学习方向,前两天在网上找到了这篇文章,感觉不错,给没有方向的我指了一个方向,先不管对不对,做下来再说。

谁可相欹 发表于 2015-4-6 09:03:19

如果你学过HTML,那么事情要好办的多,如果没有,那你快去补一补HTML基础吧。其实JSP中的Java语法也不多,它更象一个脚本语言,有点象ASP。

柔情似水 发表于 2015-4-16 00:08:56

是一种突破用户端机器环境和CPU

愤怒的大鸟 发表于 2015-6-5 07:31:09

不过,每次的执行编译后的字节码需要消耗一定的时间,这同时也在一定程度上降低了 Java 程序的运行效率。

admin 发表于 2015-6-12 22:22:49

Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)

精灵巫婆 发表于 2015-6-20 06:24:00

自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
页: [1]
查看完整版本: JAVA教程之Servlet中jdbc使用初级篇