posts - 189,comments - 115,trackbacks - 0
数据库连接池的原理机制
转贴  

 1、基本概念及原理 
  由上面的分析可以看出,问题的根源就在于对数据库连接资源的低效管理。我们知道, 
  对于共享资源,有一个很著名的设计模式:资源池(Resource  Pool)。该模式正是为了解决资源的频繁分配?释放所造成的问题。为解决上述问题,可以采用数据库连接池技术。数据库连接池的基本思想就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。我们可以通过设定连接池最大连接数来防止系统无尽的与数据库连接。更为重要的是我们可以通过连接池的管理机制监视数据库的连接的数量?使用情况,为系统开发?测试及性能调整提供依据。

  连接池的基本工作原理 
  2、服务器自带的连接池 
  JDBC的API中没有提供连接池的方法。一些大型的WEB应用服务器如BEA的WebLogic和IBM的WebSphere等提供了连接池的机制,但是必须有其第三方的专用类方法支持连接池的用法。 
  连接池关键问题分析 
  1、并发问题 
  为了使连接管理服务具有最大的通用性,必须考虑多线程环境,即并发问题。这个问题相对比较好解决,因为Java语言自身提供了对并发管理的支持,使用synchronized关键字即可确保线程是同步的。使用方法为直接在类方法前面加上synchronized关键字,如: 
public  synchronized  Connection  getConnection()   
  2、多数据库服务器和多用户 
  对于大型的企业级应用,常常需要同时连接不同的数据库(如连接Oracle和Sybase)。如何连接不同的数据库呢?我们采用的策略是:设计一个符合单例模式的连接池管理类,在连接池管理类的唯一实例被创建时读取一个资源文件,其中资源文件中存放着多个数据库的url地址()?用户名()?密码()等信息。如tx.url=172.21.15.123:5000/tx_it,tx.user=yang,tx.password=yang321。根据资源文件提供的信息,创建多个连接池类的实例,每一个实例都是一个特定数据库的连接池。连接池管理类实例为每个连接池实例取一个名字,通过不同的名字来管理不同的连接池。 
  对于同一个数据库有多个用户使用不同的名称和密码访问的情况,也可以通过资源文件处理,即在资源文件中设置多个具有相同url地址,但具有不同用户名和密码的数据库连接信息。 
  3、事务处理 
  我们知道,事务具有原子性,此时要求对数据库的操作符合“ALL-ALL-NOTHING”原则,即对于一组SQL语句要么全做,要么全不做。 
  在Java语言中,Connection类本身提供了对事务的支持,可以通过设置Connection的AutoCommit属性为false,然后显式的调用commit或rollback方法来实现。但要高效的进行Connection复用,就必须提供相应的事务支持机制。可采用每一个事务独占一个连接来实现,这种方法可以大大降低事务管理的复杂性。 
  4、连接池的分配与释放 
  连接池的分配与释放,对系统的性能有很大的影响。合理的分配与释放,可以提高连接的复用度,从而降低建立新连接的开销,同时还可以加快用户的访问速度。 
  对于连接的管理可使用空闲池。即把已经创建但尚未分配出去的连接按创建时间存放到一个空闲池中。每当用户请求一个连接时,系统首先检查空闲池内有没有空闲连接。如果有就把建立时间最长(通过容器的顺序存放实现)的那个连接分配给他(实际是先做连接是否有效的判断,如果可用就分配给用户,如不可用就把这个连接从空闲池删掉,重新检测空闲池是否还有连接);如果没有则检查当前所开连接池是否达到连接池所允许的最大连接数(maxConn),如果没有达到,就新建一个连接,如果已经达到,就等待一定的时间(timeout)。如果在等待的时间内有连接被释放出来就可以把这个连接分配给等待的用户,如果等待时间超过预定时间timeout,则返回空值(null)。系统对已经分配出去正在使用的连接只做计数,当使用完后再返还给空闲池。对于空闲连接的状态,可开辟专门的线程定时检测,这样会花费一定的系统开销,但可以保证较快的响应速度。也可采取不开辟专门线程,只是在分配前检测的方法。 
  5、连接池的配置与维护 
  连接池中到底应该放置多少连接,才能使系统的性能最佳?系统可采取设置最小连接数(minConn)和最大连接数(maxConn)来控制连接池中的连接。最小连接数是系统启动时连接池所创建的连接数。如果创建过多,则系统启动就慢,但创建后系统的响应速度会很快;如果创建过少,则系统启动的很快,响应起来却慢。这样,可以在开发时,设置较小的最小连接数,开发起来会快,而在系统实际使用时设置较大的,因为这样对访问客户来说速度会快些。最大连接数是连接池中允许连接的最大数目,具体设置多少,要看系统的访问量,可通过反复测试,找到最佳点。 
  如何确保连接池中的最小连接数呢?有动态和静态两种策略。动态即每隔一定时间就对连接池进行检测,如果发现连接数量小于最小连接数,则补充相应数量的新连接,以保证连接池的正常运转。静态是发现空闲连接不够时再去检查。 
   
  连接池的实现 
  1、连接池模型 
  本文讨论的连接池包括一个连接池类(DBConnectionPool)和一个连接池管理类(DBConnetionPoolManager)。连接池类是对某一数据库所有连接的“缓冲池”,主要实现以下功能:①从连接池获取或创建可用连接;②使用完毕之后,把连接返还给连接池;③在系统关闭前,断开所有连接并释放连接占用的系统资源;④还能够处理无效连接(原来登记为可用的连接,由于某种原因不再可用,如超时,通讯问题),并能够限制连接池中的连接总数不低于某个预定值和不超过某个预定值。 
  连接池管理类是连接池类的外覆类(wrapper),符合单例模式,即系统中只能有一个连接池管理类的实例。其主要用于对多个连接池对象的管理,具有以下功能:①装载并注册特定数据库的JDBC驱动程序;②根据属性文件给定的信息,创建连接池对象;③为方便管理多个连接池对象,为每一个连接池对象取一个名字,实现连接池名字与其实例之间的映射;④跟踪客户使用连接情况,以便需要是关闭连接释放资源。连接池管理类的引入主要是为了方便对多个连接池的使用和管理,如系统需要连接不同的数据库,或连接相同的数据库但由于安全性问题,需要不同的用户使用不同的名称和密码。 
  2、连接池实现 
  下面给出连接池类和连接池管理类的主要属性及所要实现的基本接口: 
public  class  DBConnectionPool  implements  TimerListener{ 
private  int  checkedOut;//已被分配出去的连接数 
private  ArrayList  freeConnections  =  new  ArrayList();//容器,空闲池,根据//创建时间顺序存放已创建但尚未分配出去的连接 
private  int  minConn;//连接池里连接的最小数量 
private  int  maxConn;//连接池里允许存在的最大连接数 
private  String  name;//为这个连接池取个名字,方便管理 
private  String  password;//连接数据库时需要的密码 
private  String  url;//所要创建连接的数据库的地址 
private  String  user;//连接数据库时需要的用户名 
public  Timer  timer;//定时器 
public  DBConnectionPool(String  name,  String  URL,  String  user,  String   
password,  int  maxConn)//公开的构造函数 
public  synchronized  void  freeConnection(Connection  con)  //使用完毕之后,//把连接返还给空闲池 
public  synchronized  Connection  getConnection(long  timeout)//得到一个连接,//timeout是等待时间 
public  synchronized  void  release()//断开所有连接,释放占用的系统资源 
private  Connection  newConnection()//新建一个数据库连接 
public  synchronized  void  TimerEvent()  //定时器事件处理函数 

public  class  DBConnectionManager  { 
static  private  DBConnectionManager  instance;//连接池管理类的唯一实例 
static  private  int  clients;//客户数量 
private  ArrayList  drivers  =  new  ArrayList();//容器,存放数据库驱动程序 
private  HashMap  pools  =  new  HashMap  ();//以name/value的形式存取连接池//对象的名字及连接池对象 
static  synchronized  public  DBConnectionManager  getInstance()//如果唯一的//实例instance已经创建,直接返回这个实例;否则,调用私有构造函数,创//建连接池管理类的唯一实例   
private  DBConnectionManager()//私有构造函数,在其中调用初始化函数init() 
public  void  freeConnection(String  name,  Connection  con)//  释放一个连接,//name是一个连接池对象的名字 
public  Connection  getConnection(String  name)//从名字为name的连接池对象//中得到一个连接 
public  Connection  getConnection(String  name,  long  time)//从名字为name 
//的连接池对象中取得一个连接,time是等待时间 
public  synchronized  void  release()//释放所有资源 
private  void  createPools(Properties  props)//根据属性文件提供的信息,创建//一个或多个连接池 
private  void  init()//初始化连接池管理类的唯一实例,由私有构造函数调用 
private  void  loadDrivers(Properties  props)//装载数据库驱动程序 
}     
  3、连接池使用 
  上面所实现的连接池在程序开发时如何应用到系统中呢?下面以Servlet为例说明连接池的使用。 
  Servlet的生命周期是:在开始建立servlet时,调用其初始化(init)方法。之后每个用户请求都导致一个调用前面建立的实例的service方法的线程。最后,当服务器决定卸载一个servlet时,它首先调用该servlet的  destroy方法。 
  根据servlet的特点,我们可以在初始化函数中生成连接池管理类的唯一实例(其中包括创建一个或多个连接池)。如: 
public  void  init()  throws  ServletException 

 connMgr  =  DBConnectionManager.getInstance();   
}     
  然后就可以在service方法中通过连接池名称使用连接池,执行数据库操作。最后在destroy方法中释放占用的系统资源,如:   
public  void  destroy()  {   
 connMgr.release();  super.destroy();   
}   
  结束语 
  在使用JDBC进行与数据库有关的应用开发中,数据库连接的管理是一个难点。很多时候,连接的混乱管理所造成的系统资源开销过大成为制约大型企业级应用效率的瓶颈。对于众多用户访问的Web应用,采用数据库连接技术的系统在效率和稳定性上比采用传统的其他方式的系统要好很多。本文阐述了使用JDBC访问数据库的技术?讨论了基于连接池技术的数据库连接管理的关键问题并给出了一个实现模型。文章所给出的是连接池管理程序的一种基本模式,为提高系统的整体性能,在此基础上还可以进行很多有意义的扩展。



crystal report for eclipse
的部署过程

 

一、 在项目的 SRC 目录下存在文件 CRConfig.xml

二、 copy 目录 crystalreportviewers115 到项目的 WEBROOT 目录下新建目录 REPORT

三、 copy 文件 crystal-tags-reportviewer.tld 到项目的 WEB-INF 目录下

四、 copy 以下文件到目录 WEB-INF----LIB 目录下

Required components

When you are developing a web application, the following JAR files must be added to your web project. These files must also be added to your web application's WEB-INF\lib directory when deploying the web application.

·              commons-beanutils.jar

·              commons-collections-3.1.jar

·              commons-configuration-1.2.jar

·              commons-digester.jar

·              commons-discovery.jar ???

·              commons-lang-2.1.jar

·              commons-logging.jar

·              Concurrent.jar

·              CrystalCharting.jar

·              CrystalCommon.jar

·              CrystalContentModels.jar

·              CrystalDatabaseConnectors.jar

·              CrystalExporters.jar

·              CrystalExportingBase.jar

·              CrystalFormulas.jar

·              CrystalQueryEngine.jar

·              CrystalReportEngine.jar

·              CrystalReportingCommon.jar

·              icu4j.jar

·              jrcadapter.jar

·              jrcerom.jar

·              jsf-api.jar ???

·              jsf-impl.jar ???

·              jstl.jar

·              keycodeDecoder.jar

·              log4j.jar

·              MetafileRenderer.jar

·              msbase.jar

·              mssqlserver.jar

·              msutil.jar

·              ojdbc14.jar ???

·              ojdbc14_g.jar ???

·              rasapp.jar

·              rascore.jar

·              ReportPrinter.jar

·              rpoifs.jar

·              serialization.jar

·              URIUtil.jar

·              xercesImpl.jar

·              xml-apis.jar

The following files are required for viewing and exporting functionality:

·              webreporting.jar

·              webreporting-jsf.jar (provides the JSF version of the DHTML report page viewer)

·              crystalreportviewers directory

·              crystal-tags-reportviewer.tld in /WEB-INF

·              CRConfig.XML in /src directory

 

五、 先用 Crystal Report 创建文件 *****.rpt

六、 打开 crystal report for eclipse 修改 *****.rpt, 同时创建 ****-viwer.jsp

copy 这些 *****.rpt, ****-viwer.jsp 到项目的 WEBROOT 目录下新建目录 REPOR



XJL:XML文件处理 [转 贴 学习]

 

XML技术是随着Java的发展而发展起来的。在XML出现之前对于简单的数据格式通常是存储在ini配置文件等文本文件中,复杂的格式则采用自定义的文件格式,因此对于每种文件格式都要有专门的解析程序。XML出现以后解决了这个问题,程序面对的是有固定格式的XML文件,只要通过标准API就可以进行XML文件的处理。

XML文件在案例系统中应用是很广泛的,比如ClientConfig.xmlServerConfig.xml文件就是使用XML文件来做配置文件的,元数据文件以及元数据加载器更是离不开XML。因此本章将系统讲解一下XML文件的处理技术。

1.1   XML处理技术比较

Java领域XML文件的技术大致分为两类:XML APIOXMappingXML APIXML处理的基础,可选技术包括JDOMDom4j等;OXMappingObject-XML Mapping的简称,这种技术隐藏了XML底层操作的细节,可以将XML文件映射成一个JavaBean对象,也可以把一个JavaBean对象保存成一个XML文件,可选技术XStreamDigesterCastor等。XML APIOXMapping的关系类似于JDBCORMaping的关系,OXMapping内部实现使用XML API来完成,两种实现技术从不同的层面实现了XML的处理。

XML API

此类XML处理技术中最流行的莫过于JDOMDom4j了,二者的使用方式非常相似。不过Dom4j的优势比JDOM更明显一些:

Dom4j大量的使用接口,这使得Dom4jDom4j更加灵活和具有可扩展性;

Dom4j的性能表现比JDOM好;

Dom4j支持XPath等高级特性;

正是由于这些优点,很多开源项目都开始使用Dom4jXML解析技术,本书也将使用Dom4j做为XML处理的首选。

OXMapping

使用XML API解析是略显烦琐的,受ORMapping技术的启发,人们发明了OXMapping技术,使用OXMapping技术,我们可以将XML文件映射成一个JavaBean对象,也可以把一个JavaBean对象保存成一个XML文件,这大大简化了我们的开发工作量,使得开发人员能更多的关注应用层面的东西。

开源世界中涌现出很多OXMapping框架,包括XStreamDigesterCastor等。XStreamDigester把映射的过程在代码中完成,而Castor则需要写一个和Hibernatecfg.xml类似的映射配置文件。与Digester比起来,XStream的主要优点就是更加小巧,使用也更加方便,不过目前使用Digester是“开源名牌”Apache下的子项目,网上可以参考的资料也比XStream多,好在XStream比较简洁,所以并不会对XStream造成太大影响。

http://www.blogjava.net/huanzhugege/

1.2   Dom4j的使用

Dom4j是一个易用的、开源的库,用于XMLXPathXSLT。它应用于Java平台,采用了Java集合框架并完全支持DOMSAXJAXPDom4jsourceforge.net上的一个开源项目,地址为http://sourceforge.net/projects/dom4j

Dom4j里基于接口编程是一个非常显著的优点,下面是其主要的接口的继承体系结构图:

5.1

这些接口大部分都是定义在包org.dom4j中,下面简单介绍各个接口的意义:

5.1Dom4j主要接口

Node

Node为是dom4j中所有的XML节点的基类型接口

Attribute

Attribute定义了XML的属性

Branch

Branch为能够包含子节点的节点如XML元素(Element)和文档(Docuemnts)定义了一个公共的行为

Document

定义了XML文档

Element

Element定义XML 元素

DocumentType

DocumentType 定义XML DOCTYPE声明

Entity

Entity定义XML entity

CharacterData

CharacterData是一个标识借口,标识基于字符的节点。如CDATAComment, Text

CDATA

CDATA 定义了XML CDATA 区域

Comment

Comment 定义了XML注释的行为

Text

Text 定义XML 文本节点

ProcessingInstruction

ProcessingInstruction 定义XML 处理指令

 

读取XML文件

XML应用中,最常用的莫过于XML文件的解析读取了,Dom4j提供了多种读取XML文档的方式,包括Dom树遍历、Visitor方式和XPath方式。

无论哪种方式,我们首先都要根据xml文件构造一个Document对象:

SAXReader reader = new SAXReader();

Document document = reader.read(new File(fileName));

这里我们选用了SAXReader做为XML读取器,我们同样也可以选择DOMReader做为XML读取器:

SAXReader reader = new DOMReader();

Document document = reader.read(new File(fileName));

其中readerread方法有多个重载方法,可以从InputStream, File, URL等多种不同的源来读取XML文档。

1Dom树遍历

这种读取方式中把Dom看成一个普通的树,要读取XML中某个节点的值,只要采用数据结构中的树遍历算法定位到需要读取的节点即可。

要便利Dom树,首先要取得树的根节点:

Element root = document.getRootElement();

取得根节点以后就可以一级一级的向下读了:

// 遍历所有子节点

for ( Iterator i = root.elementIterator(); i.hasNext(); )

{

      Element element = (Element) i.next();

      // do something

   }

   // 遍历名称为“foo”的节点

for ( Iterator i = root.elementIterator(foo); i.hasNext();)

{

      Element foo = (Element) i.next();

      // do something

   }

   // 遍历属性

for ( Iterator i = root.attributeIterator(); i.hasNext(); )

{

      Attribute attribute = (Attribute) i.next();

      // do something

}

2Visitor方式

Dom树遍历是最普通,也是最常用的XML读取方式,其他的XML解析引擎,比如JDom等,也是使用这种方式进行XML的读取。不过Dom4j提供了另外一种读取方式,那就是Visitor方式。这种方式实现了Visitor模式,调用者只要编写一个Visitor就可以了。Visitor模式使得访问者易于增加新的操作,同时使访问者集中相关的操作而分离无关的操作。

编写的Visitor必须实现org.dom4j.Visitor接口,Dom4j还提供了一个Default Adapter模式的默认适配器org.dom4j.VisitorSupport

public class DemoVisitor extends VisitorSupport

{

public void visit(Element element)

{

System.out.println(element.getName());

}

public void visit(Attribute attr)

{

System.out.println(attr.getName());

}

}

然后在要开始遍历的节点调用此Visitor即可:

root.accept(new DemoVisitor ())

此方式需要遍历所有的节点和元素,因此速度会稍慢一些。

3XPath方式

Dom4j最吸引人的特性莫过于对XPath的集成支持了,这个特性并不是所有的XML解析引擎都支持的,但是确实一个非常有用的特性。

XPath 是寻址、搜索和匹配文档的各个部分的语言。它使用路径标记法来指定和匹配文档的各个部分,该标记法与文件系统和URL 中使用的类似。例如,XPath:/x/y/z 搜索文档的根节点x,其下存在节点y,其下存在节点z。该语句返回与指定路径结构匹配的所有节点。/x/y/* 返回父节点为x y 节点下的任何节点。/x/y[@name=a] 匹配所有父节点为x y 节点,其属性称为name,属性值为a

XPath大大简化了XML的寻址操作,使用者只要通过匹配表达式告诉引擎要匹配文档的哪些部分即可,具体的匹配工作由XPath引擎来完成。这种方式更加接近于人类的自然思维方式。我们来看一个实际的例子:

有一个XML文件记录了一个部门的基本情况:

<?xml version="1.0" encoding="GB2312"?>

<department>

     <name>开发部</name>

     <level>2</level>

     <employeeList>

         <employee number="001" name="Tom" />

         <employee number="002" name="Jim" />

         <employee number="003" name="Lily" />

     </employeeList>

</department>

name代表部门名称,level为部门的级别,employeeList下是部门所有的员工列表。下面编写一个程序读取此文件并打印出部门的信息。

代码5.1XPath演示

InputStream inStream = null;

try

{

     inStream = Dom4jDemo01.class.getResourceAsStream(

"/com/cownew/Char0502/Department01.xml");

     SAXReader reader = new SAXReader();

     Document doc = reader.read(new InputStreamReader(inStream));

     Node nameNode = doc.selectSingleNode("//department/name");

     System.out.println("部门名称:" + nameNode.getText());

 

     Node levelNode = doc.selectSingleNode("//department/level");

     System.out.println("部门级别:" + levelNode.getText());

 

     List employeeNodeList = doc

                   .selectNodes("//department/employeeList/employee");

     System.out.println("部门下属雇员:");

     for (int i = 0, n = employeeNodeList.size(); i < n; i++)

     {

         DefaultElement employeeElement = (DefaultElement) employeeNodeList

                            .get(i);

         String name = employeeElement.attributeValue("name");

         String number = employeeElement.attributeValue("number");

         System.out.println(name + ",工号:" + number);

     }

} finally

{

     ResourceUtils.close(inStream);

}

运行结果

部门名称:开发部

部门级别:2

部门下属雇员:

Tom,工号:001

Jim,工号:002

Lily,工号:003

 

使用XPath以后,我们只要使用“//department/name”这种非常清晰的方式就可以直接定位到具体的节点。XPath方式中定位单个节点使用selectSingleNode方法,而定位多节点则使用selectNodes方法。

案例系统中所有的XML文件都是使用XPath方式进行解析的,包括ClientConfig.javaServerConfig.javaEntityMetaDataParser.java等。

XML文件的创建

Dom4jXML文件的创建和其他的XML引擎类似,首先以Document的根节点为基础构造出一棵节点树,然后调用相应的IO类库就可以将XML文件保存到适当的介质中了。

下面演示一下生成上文提到的那个部门信息XML文件的过程

代码5.2XML创建演示

import java.io.FileWriter;

import java.io.IOException;

 

import org.dom4j.Document;

import org.dom4j.DocumentHelper;

import org.dom4j.Element;

import org.dom4j.io.OutputFormat;

import org.dom4j.io.XMLWriter;

 

public class Dom4jDemo02

{

     public static void main(String[] args)

     {

         // 创建文档对象

         Document document = DocumentHelper.createDocument();

 

         // 添加根节点"department"

         Element departElement = document.addElement("department");

 

         // 添加"name"节点

         Element departNameElement = DocumentHelper.createElement("name");

         departNameElement.setText("开发部");

         departElement.add(departNameElement);

 

         // 添加"level"节点

         Element departLevelElement = DocumentHelper.createElement("level");

         departLevelElement.setText("2");

         departElement.add(departLevelElement);

 

         // 添加员工列表"employeeList"节点

         Element employeeElementList = DocumentHelper

                   .createElement("employeeList");

         departElement.add(employeeElementList);

 

         // 添加员工节点"employee"

         Element emp1Element = DocumentHelper.createElement("employee");

         emp1Element.addAttribute("number", "001");

         emp1Element.addAttribute("name", "Tom");

         employeeElementList.add(emp1Element);

 

         Element emp2Element = DocumentHelper.createElement("employee");

         emp2Element.addAttribute("number", "002");

         emp2Element.addAttribute("name", "Jim");

         employeeElementList.add(emp2Element);

 

         Element emp3Element = DocumentHelper.createElement("employee");

         //添加属性

         emp3Element.addAttribute("number", "003");

         emp3Element.addAttribute("name", "Lily");

         employeeElementList.add(emp3Element);

 

         try

         {

              writeToFile(document, "c:/department.xml");

         } catch (IOException e)

         {

              e.printStackTrace();

         }

     }

 

     private static void writeToFile(Document document, String file)

              throws IOException

     {

         // 美化格式

         OutputFormat format = OutputFormat.createPrettyPrint();

         format.setEncoding("GB2312");

         XMLWriter writer = null;

         try

         {

              writer = new XMLWriter(new FileWriter(file), format);

              writer.write(document);

         } finally

         {

              if (writer != null)

                   writer.close();

         }

     }

}

运行以后就可以在c:/下发现生成了和5.2.1的文件内容一样的department.xml了。

这里有两点需要注意的:

1OutputFormat format = OutputFormat.createPrettyPrint()

XML通常是需要人阅读的,Dom4j默认的生成格式是紧缩格式的,这样可以减少空间占用,但是带来的缺点就是文件格式非常难看,因此我们采用锁紧格式进行输出。

2format.setEncoding("GB2312")

Dom4j默认的编码格式是“UTF-8”,这在输出中文字符的时候会有问题,因此我们改成“GB2312”格式。

这里使用了Dom4j提供的工具类DocumentHelper提供的createElement方法来创建一个节点,这个工具类还有public static CDATA createCDATA(String text)public static Comment createComment(String text)public static Entity createEntity(String name, String text) 等方法可以帮助我们更快的创建节点。DocumentHelper还提供了parseText方法,可以直接将字符串解析成Documen对象。

http://www.blogjava.net/huanzhugege/

1.3   XStream的使用

在使用XStream之前首先到http://xstream.codehaus.org下载XStream的最新版本,然后把XSteam***.jarxpp3-***.jar导入到ClassPath下,然后就可以使用了,当然不加入xpp3-***.jar也可以,我们可以使用DomDriver做为XML解析驱动(只要在实例化XStream的时候使用new XStream(new DomDriver())即可),不过Xpp3XStream提供的一个很有效率的XML pull-parser实现,推荐使用,可以提高解析的效率。

XML的解析

我们有一个记录书籍进行的XML文件:

<book>

     <name>J2EE Guide Book</name>

     <author>

         <name>Jerry</name>

         <email>Jerry@mail.com</email>

     </author>

</book>

为了解析此XML文件,我们首先创建代表书籍和人员的两个JavaBean

代码5.3人员和书籍的JavaBean

public class BookInfo

{

     private String name;

     private PersonInfo author;

     public PersonInfo getAuthor()

     {

         return author;

     }

     public void setAuthor(PersonInfo author)

     {

         this.author = author;

     }

     public String getName()

     {

         return name;

     }

     public void setName(String name)

     {

         this.name = name;

     }

}

 

public class PersonInfo

{

     private String name;

     private String email;

     public String getEmail()

     {

         return email;

     }

     public void setEmail(String email)

     {

         this.email = email;

     }

     public String getName()

     {

         return name;

     }

     public void setName(String name)

     {

         this.name = name;

     }

}

然后我们就可以进行文件的解析了,这也是重头戏:

代码5.4XStreamXML解析

XStream xstream = new XStream();

xstream.alias("book", BookInfo.class);

xstream.alias("author", PersonInfo.class);

InputStream inStream = XStreamDemo.class

         .getResourceAsStream("/com/cownew/Char0503/Books.xml");

InputStreamReader reader = new InputStreamReader(inStream);

BookInfo book = (BookInfo) xstream.fromXML(reader);

StringBuffer sb = new StringBuffer();

sb.append(book.getName()).append("的作者");

sb.append(book.getAuthor().getName()).append("Email:");

sb.append(book.getAuthor().getEmail());

System.out.println(sb);

运行结果:

J2EE Guide Book的作者JerryEmail:Jerry@mail.com     

由于book节点和author节点对应的数据类型是我们的自定义类型,因此我们必须首先向XStream注册这两个类型

xstream.alias("book", BookInfo.class);

xstream.alias("author", PersonInfo.class);

由于我们是使用XStream解析已有的XML文件,因此我们必须让XStream知道标签对应的类型是什么,如果我们是使用XStream进行XML文件的生成,那么我们甚至无需向XStream注册别名即可进行文件解析。

注册完类型以后,调用XStream类的fromXML方法即可把XML解析成JavaBean对象,无需额外的操作。

XML文件的保存

我们不仅需要解析XML文件,有的时候还需要将数据保存到XML文件,XStream同样能很好的完成,并且能更体现出XStream的强大。

代码5.5XStreamXML的保存

List bookList = new ArrayList();

PersonInfo p1 = new PersonInfo();

p1.setName("Tom");

p1.setEmail("Tom@mail.com");

PersonInfo p2 = new PersonInfo();

p2.setName("Jerry");

p2.setEmail("Jerry@mail.com");

    

BookInfo book1 = new BookInfo();

book1.setName("About Face");

book1.setAuthor(p1);

    

BookInfo book2 = new BookInfo();

book2.setName("UI Design");

book2.setAuthor(p2);

    

bookList.add(book1);

bookList.add(book2);

    

XStream xstream = new XStream();

String xml = xstream.toXML(bookList);

System.out.println(xml);

    

List list = (List) xstream.fromXML(xml);

for(int i=0,n=list.size();i<n;i++)

{

     BookInfo book = (BookInfo) list.get(i);

     StringBuffer sb = new StringBuffer();

     sb.append(book.getName()).append("的作者");

     sb.append(book.getAuthor().getName()).append("Email:");

     sb.append(book.getAuthor().getEmail());

     System.out.println(sb);

}

运行结果:

<list>

  <com.cownew.Char0503.BookInfo>

    <name>About Face</name>

    <author>

      <name>Tom</name>

      <email>Tom@mail.com</email>

    </author>

  </com.cownew.Char0503.BookInfo>

  <com.cownew.Char0503.BookInfo>

    <name>UI Design</name>

    <author>

      <name>Jerry</name>

      <email>Jerry@mail.com</email>

    </author>

  </com.cownew.Char0503.BookInfo>

</list>

About Face的作者TomEmail:Tom@mail.com

UI Design的作者JerryEmail:Jerry@mail.com

 

不可思议吧!我们就是像在序列化一样把JavaBean“序列化”为XML格式字符串,然后又轻松的将XML格式字符串“反序列化”为JavaBean

不过美中不足的就是“<com.cownew.Char0503.BookInfo>”这个标签显得有点罗嗦。解决方式很简单,使用5.3.1一节中提到的alias方法就可以办到:

xstream.alias("book", BookInfo.class);添加到XStream xstream = new XStream();之后,然后重新运行:

<list>

  <book>

    <name>About Face</name>

    <author>

      <name>Tom</name>

      <email>Tom@mail.com</email>

    </author>

  </book>

  <book>

    <name>UI Design</name>

    <author>

      <name>Jerry</name>

      <email>Jerry@mail.com</email>

    </author>

  </book>

</list>

About Face的作者TomEmail:Tom@mail.com

UI Design的作者JerryEmail:Jerry@mail.com



学习java必看--习惯,心理篇
 转贴     

(1) 类名首字母应该大写。字段、方法以及对象(句柄)的首字母应小写。对于所有标识符,其中包含的所有单词都应紧靠在一起,而且大写中间单词的首字母。例如: 
ThisIsAClassName 
thisIsMethodOrFieldName 
若在定义中出现了常数初始化字符,则大写static final基本类型标识符中的所有字母。这样便可标志出它们属于编译期的常数。 
Java包(Package)属于一种特殊情况:它们全都是小写字母,即便中间的单词亦是如此。对于域名扩展名称,如com,org,net或者edu等,全部都应小写(这也是Java 1.1和Java 1.2的区别之一)。 

(2) 为了常规用途而创建一个类时,请采取"经典形式",并包含对下述元素的定义: 

equals() 
hashCode() 
toString() 
clone()(implement Cloneable) 
implement Serializable 

(3) 对于自己创建的每一个类,都考虑置入一个main(),其中包含了用于测试那个类的代码。为使用一个项目中的类,我们没必要删除测试代码。若进行了任何形式的改动,可方便地返回测试。这些代码也可作为如何使用类的一个示例使用。 

(4) 应将方法设计成简要的、功能性单元,用它描述和实现一个不连续的类接口部分。理想情况下,方法应简明扼要。若长度很大,可考虑通过某种方式将其分割成较短的几个方法。这样做也便于类内代码的重复使用(有些时候,方法必须非常大,但它们仍应只做同样的一件事情)。 

(5) 设计一个类时,请设身处地为客户程序员考虑一下(类的使用方法应该是非常明确的)。然后,再设身处地为管理代码的人考虑一下(预计有可能进行哪些形式的修改,想想用什么方法可把它们变得更简单)。 
(6) 使类尽可能短小精悍,而且只解决一个特定的问题。下面是对类设计的一些建议: 
■一个复杂的开关语句:考虑采用"多形"机制 
■数量众多的方法涉及到类型差别极大的操作:考虑用几个类来分别实现 
■许多成员变量在特征上有很大的差别:考虑使用几个类 

(7) 让一切东西都尽可能地"私有"--private。可使库的某一部分"公共化"(一个方法、类或者一个字段等等),就永远不能把它拿出。若强行拿出,就可能破坏其他人现有的代码,使他们不得不重新编写和设计。若只公布自己必须公布的,就可放心大胆地改变其他任何东西。在多线程环境中,隐私是特别重要的一个因素--只有private字段才能在非同步使用的情况下受到保护。 

(8) 谨惕"巨大对象综合症"。对一些习惯于顺序编程思维、且初涉OOP领域的新手,往往喜欢先写一个顺序执行的程序,再把它嵌入一个或两个巨大的对象里。根据编程原理,对象表达的应该是应用程序的概念,而非应用程序本身。 

(9) 若不得已进行一些不太雅观的编程,至少应该把那些代码置于一个类的内部。 

(10) 任何时候只要发现类与类之间结合得非常紧密,就需要考虑是否采用内部类,从而改善编码及维护工作(参见第14章14.1.2小节的"用内部类改进代码")。 

(11) 尽可能细致地加上注释,并用javadoc注释文档语法生成自己的程序文档。 

(12) 避免使用"魔术数字",这些数字很难与代码很好地配合。如以后需要修改它,无疑会成为一场噩梦,因为根本不知道"100"到底是指"数组大小"还是"其他全然不同的东西"。所以,我们应创建一个常数,并为其使用具有说服力的描述性名称,并在整个程序中都采用常数标识符。这样可使程序更易理解以及更易维护。 

(13) 涉及构建器和异常的时候,通常希望重新丢弃在构建器中捕获的任何异常--如果它造成了那个对象的创建失败。这样一来,调用者就不会以为那个对象已正确地创建,从而盲目地继续。 

(14) 当客户程序员用完对象以后,若你的类要求进行任何清除工作,可考虑将清除代码置于一个良好定义的方法里,采用类似于cleanup()这样的名字,明确表明自己的用途。除此以外,可在类内放置一个boolean(布尔)标记,指出对象是否已被清除。在类的finalize()方法里,请确定对象已被清除,并已丢弃了从RuntimeException继承的一个类(如果还没有的话),从而指出一个编程错误。在采取象这样的方案之前,请确定finalize()能够在自己的系统中工作(可能需要调用System.runFinalizersOnExit(true),从而确保这一行为)。 

(15) 在一个特定的作用域内,若一个对象必须清除(非由垃圾收集机制处理),请采用下述方法:初始化对象;若成功,则立即进入一个含有finally从句的try块,开始清除工作。 

(16) 若在初始化过程中需要覆盖(取消)finalize(),请记住调用super.finalize()(若Object属于我们的直接超类,则无此必要)。在对finalize()进行覆盖的过程中,对super.finalize()的调用应属于最后一个行动,而不应是第一个行动,这样可确保在需要基础类组件的时候它们依然有效。 

(17) 创建大小固定的对象集合时,请将它们传输至一个数组(若准备从一个方法里返回这个集合,更应如此操作)。这样一来,我们就可享受到数组在编译期进行类型检查的好处。此外,为使用它们,数组的接收者也许并不需要将对象"造型"到数组里。 

(18) 尽量使用interfaces,不要使用abstract类。若已知某样东西准备成为一个基础类,那么第一个选择应是将其变成一个interface(接口)。只有在不得不使用方法定义或者成员变量的时候,才需要将其变成一个abstract(抽象)类。接口主要描述了客户希望做什么事情,而一个类则致力于(或允许)具体的实施细节。 

(19) 在构建器内部,只进行那些将对象设为正确状态所需的工作。尽可能地避免调用其他方法,因为那些方法可能被其他人覆盖或取消,从而在构建过程中产生不可预知的结果(参见第7章的详细说明)。 

(20) 对象不应只是简单地容纳一些数据;它们的行为也应得到良好的定义。 

(21) 在现成类的基础上创建新类时,请首先选择"新建"或"创作"。只有自己的设计要求必须继承时,才应考虑这方面的问题。若在本来允许新建的场合使用了继承,则整个设计会变得没有必要地复杂。 

(22) 用继承及方法覆盖来表示行为间的差异,而用字段表示状态间的区别。一个非常极端的例子是通过对不同类的继承来表示颜色,这是绝对应该避免的:应直接使用一个"颜色"字段。 

(23) 为避免编程时遇到麻烦,请保证在自己类路径指到的任何地方,每个名字都仅对应一个类。否则,编译器可能先找到同名的另一个类,并报告出错消息。若怀疑自己碰到了类路径问题,请试试在类路径的每一个起点,搜索一下同名的.class文件。 

(24) 在Java 1.1 AWT中使用事件"适配器"时,特别容易碰到一个陷阱。若覆盖了某个适配器方法,同时拼写方法没有特别讲究,最后的结果就是新添加一个方法,而不是覆盖现成方法。然而,由于这样做是完全合法的,所以不会从编译器或运行期系统获得任何出错提示--只不过代码的工作就变得不正常了。 

(25) 用合理的设计方案消除"伪功能"。也就是说,假若只需要创建类的一个对象,就不要提前限制自己使用应用程序,并加上一条"只生成其中一个"注释。请考虑将其封装成一个"独生子"的形式。若在主程序里有大量散乱的代码,用于创建自己的对象,请考虑采纳一种创造性的方案,将些代码封装起来。 

(26) 警惕"分析瘫痪"。请记住,无论如何都要提前了解整个项目的状况,再去考察其中的细节。由于把握了全局,可快速认识自己未知的一些因素,防止在考察细节的时候陷入"死逻辑"中。 

(27) 警惕"过早优化"。首先让它运行起来,再考虑变得更快--但只有在自己必须这样做、而且经证实在某部分代码中的确存在一个性能瓶颈的时候,才应进行优化。除非用专门的工具分析瓶颈,否则很有可能是在浪费自己的时间。性能提升的隐含代价是自己的代码变得难于理解,而且难于维护。 

(28) 请记住,阅读代码的时间比写代码的时间多得多。思路清晰的设计可获得易于理解的程序,但注释、细致的解释以及一些示例往往具有不可估量的价值。无论对你自己,还是对后来的人,它们都是相当重要的。如对此仍有怀疑,那么请试想自己试图从联机Java文档里找出有用信息时碰到的挫折,这样或许能将你说服。 

(29) 如认为自己已进行了良好的分析、设计或者实施,那么请稍微更换一下思维角度。试试邀请一些外来人士--并不一定是专家,但可以是来自本公司其他部门的人。请他们用完全新鲜的眼光考察你的工作,看看是否能找出你一度熟视无睹的问题。采取这种方式,往往能在最适合修改的阶段找出一些关键性的问题,避免产品发行后再解决问题而造成的金钱及精力方面的损失。 

(30) 良好的设计能带来最大的回报。简言之,对于一个特定的问题,通常会花较长的时间才能找到一种最恰当的解决方案。但一旦找到了正确的方法,以后的工作就轻松多了,再也不用经历数小时、数天或者数月的痛苦挣扎。我们的努力工作会带来最大的回报(甚至无可估量)。而且由于自己倾注了大量心血,最终获得一个出色的设计方案,成功的快感也是令人心动的。坚持抵制草草完工的诱惑--那样做往往得不偿失


http://bbs.java.ccidnet.com/htm_data/2/0701/257868.html

基于Ajax+J2EE的MicroERP源码下载
[转贴] 

  MicroERP系统是一个运用Ajax及J2EE技术开发的专用于水厂及相关企业小型ERP系统,系统使用基于国内开源组织EasyJF的EasyJWeb及EasyDBO框架开发,包括了很多常见Ajax的应用示例。为了支持国产开源事业,重庆金麦草科技有限公司特将本系统初期的部分代码捐献给EasyJF开源组织,尽供学习、交流EasyJF开源相关框架及技术使用。
 
  系统演示地址:http://microerp.easyjf.com/ 用户名:test 密码:test
  源码下载地址:http://www.easyjf.com/download/microerp-0.1.zip


谈JSP与XML的交互
转贴   



   使用JavaServer Pages有三种不同的方法用于处理XML文档,每种方法都有利于提高分离页面代码与XML数据的水平,有利于简化开发网页的复杂度并且改善提高组件与页面代码的可重用性。

   JavaServer Pages ( JSP)和XML是Sun的J2EE的两个至关紧要的组件。 JSP是用于创建应用程序服务器端程序的有效工具,而客户可以是一个浏览器,一个设备或其它的应用程序。 你可以使用XML描述数据并在联系服务器与系统的其余部分之间传递。 如果你仔细考虑Web服务的抽象概念的话,JSP可以被认为是实现技术而XML则是数据封装和消息传送技术。 JSP页面可以通过三种方式使用XML:直接使用XML文件,使用JavaBeans来执行XML处理或者通过标记库使用XML。

   一、直接使用XML

   我们可以在JSP页面中直接使用XML,这要分为三类:

   1. JSP可以读取XML文件并且基于这些数据执行动作。例如:一应用程序可以读取具有某些特定结构的数据的XML文件。

   2. JSP可以创建XML文件以发送数据到客户程序或其它的应用程序。 JSP可以转换XML文件,这个变换可以是交给XSLT处理,由JSP作为控制器,或者通过非XSLT解决方案来完成。 在这两种情况下,JSP的作用都是读取XML文件,转换它并生成一个输出。

   因为JSP包含内嵌的Java程序,所以它可以直接地调用一个分析程序来读/写xml数据。 这是非常不合理的方法,因为数据和代码逻辑并不能很好的被分离开。 另外,这样的程序也很难读得懂。 所以,下面我将介绍第二方法:使用JavaBeans。

   二、使用JavaBeans

   JSP可以通过<jsp:usebean>标记与JavaBeans紧密的整合起来。 下面的程序片段示范了如何使用在JSP页面中的一个JavaBean来设置并获取属性。

<jsp:useBean id="cb" scope="session" class="xmlrep.Customer" />

<jsp:setProperty name="cb" property="id" value="45" />

<B> First Name is: </B>

<%=cb.getFname() %>

<p>

<B> Last Name is: .</B>

<%= cb.getLname() %>

   JSP与JavaBeans整合的特征就是可以自动把超文本标志语言的表单元素翻译成JavaBean属性。 如果有一个HTML表单并且想让它向JavaBean提交表单内容,你可以写下面的代码:

<jsp:setProperty name="cb" property="*" />

   name属性包含JSP页面已经引用Bean的值。 前面<jsp:useBean>标记设置名称为" cb "。 与设置单独的Bean属性不同,你可以使用星号来标志"全部的"属性。 JSP页面自动地映射HTML表单值为同名的Bean属性。 如果你读取每个HTML表单元素,然后调用相应属性的Bean设置方法,那么结果也将是相同的。

   可以看到,类XML的标记允许JSP页面访问JavaBeans。 我们通过尽可能多的把封装的代码转变成可重用组件(JavaBeans),就可以把JSP页面中代码优化到最小的程度。 你可以使用通用的语法分析程序,像Xerces或者JAXPI,在单独的JavaBeans里与XML文件交互作用--并且你可以在不改动JSP页面的情况下改变分析程序。 此外,Beans还可以使用XSLT来执行XML文件的转换。

   使用JSP和JavaBeans来完成的这些抽象的动作比直接在JSP页面中插入原始的Java程序要好得多,但是你仍然需要熟悉Java程序,以便随时改变JSP页面。 应用程序的一致性与条理性依靠JavaBeans合作创建一个统一的输出结果的好坏程度。 例如,Bean中的缺陷可能会造成整个XML输出无效。 依靠Beans指定资源的方法,可能同时带来执行性能的问题。

  三、通过标记库JSP与XML交互

   这也就是在前文中重点提到的,但是因为它实在太重要了,所以在本文中我必须也要提到。标记库可以定义出现在JSP页面中的作为类XML元素的自定义标签,可以把特定的Java代码与每个标记都关联起来。 例如,假定你可以访问一个天气情况数据库,而且你需要输出现在的天气状况。 那么,你可以在JSP中插入JDBC程序代码直接查询数据库(虽然这并不是一个好的选择),把这些代码封装到一个JavaBean内,或者把它包装成一个标记库。 使用最后一个选择,你的JSP页面内的程序代码看上去就像:

<%@taglib uri="the TLD file" prefix="foo" %>

Current weather is <foo:Weather/>

   注意在上述程序代码中看不到任何Java代码的踪迹。 作为一个页面设计人员,你使用一种熟悉的语法就像<foo:weather/>,这些与其它的任何标记看起来非常相似。 在页面中包含现在的天气状况的HTML字符串的地方插入它。

   标记库有一个关联的XML格式的描述符文件,名叫Tag Library Descriptor(标记库描述符,TLD)。 在TLD文件中的每个标记都有一个条目,包括它的名称,版本和其它的任选信息。 在JSP页面内,你可以用" <%@_taglib prefix = " foo " %> "指令指定TLD文件。 属性" prefix "用来指定一个前缀,用来在JSP页面内使用特定的库来引用任何标记。 那为什么我们要使用标记<foo:Weather/>而不仅仅是<Weather/>。 TLD文件的精确位置依赖于正在使用的应用程序服务器。

   一个标记库标记可以代替为了完成这段程序逻辑的相应的Java程序代码。 每个标记都相当于一个相同名称的Java类。 这个类必须实现TagSupport接口,包含捕获事件触发器方法作为处理这个页面的JSP引擎。 当它第一次遇到这个标记的时候,引擎就会调用doStartTag ()方法。 可以使这个方法为空或者当需要的时候才执行应用程序逻辑。 当该方法返回SKIP_BODY时,那么引擎跳过这个标记体。 当它返回EVAL_BODY_INCLUDE时,引擎将会处理这个标记以及它的子标记。 类似地,JSP引擎在分析了结束标记之后就会调用doEndTag ()方法。 doAfterBody ()方法让你可以在引擎处理元素体之后执行动作,但是必须在doEndTag ()方法作用之前。 下面就是实现天气状况的Weather类的一个样本程序代码:

import javax.servlet.jsp.*;

import javax.servlet.jsp.tagext.*;

import java.io.*;

public class Weather extends TagSupport {

public int doStartTag() {

try {

JspWriter out = pageContext.getOut();

out.print(" sunny and cloudy mixed with " +

"rain and sunshine. ");

} catch (IOException e) {

System.out.println("Error " + e);

}

return (SKIP_BODY);

}

}  

   当引擎遇到" <somePrefix:Weather/> "标记的时候,它会在标记库内搜索一个同名的类。 如果doStartTag ()方法被实现的话(在本例中是这样的),它就会被调用。 这就使字符串包含适应显示的天气情况。 因为方法返回了SKIP_BODY,JSP读取器移动到标记的末尾。

   最简单的使用JSP和标记库的方法就是使用Apache Tomcat引擎。 这个引擎也充当Servlet和JSP应用程序接口的引用实现。

   当使用标记库时,JSP页面看上去就非常像XML文件了。 当JSP页面被处理时,引擎执行与标记相关联的程序代码(实际上,首先调用JSP引擎把JSP页面翻译成一个servlet,然后再编译servlet。 与标记库相关联的方法都被包含在servlet中。),一个熟悉XML的人就可以设计并使用各种各样的页面布局进行试验,而不必改变任何Java程序代码。当然,代码与数据的分离的程度还是主要依赖标记库元素设计的好坏程度。

http://www.easyjf.com/




Java FAQ(新手必看) 发表时间: 2005-04-04 08:36
回复


目录:
Q1.1 什么是Java、Java2、JDK?JDK后面的1.3、1.4版本号又是怎么回事?
Q1.2 什么是JRE/J2RE?
Q1.3 学习Java用什么工具比较好?
Q1.4  学习Java有哪些好的参考书?
Q1.5  Java和C++哪个更好?
Q1.6  什么是J2SE/J2EE/J2ME?
Q2.1  我写了第一个Java程序,应该如何编译/运行?
Q2.2  我照你说的做了,但是出现什么“'javac' 不是内部或外部命令,也不是可运行

程序或批处理文件。”。
Q2.3  环境变量怎么设置?
Q2.4  我在javac xxx.java的时候显示什么“unreported exception 
java.io.IOExcepti
on;”。
Q2.5  javac xxx.java顺利通过了,但是java xxx的时候显示什么
“NoClassDefFoundErr
or”。
Q2.6  我在java xxx的时候显示“Exception in thread "main" 
java.lang.NoSuchMetho
dError: main”。
Q2.7  在java xxx的时候显示“Exception in thread "main" 
java.lang.NullPointerEx
ception”。
Q2.8 package是什么意思?怎么用?
Q2.9 我没有声明任何package会怎么样?
Q2.10 在一个类中怎么使用其他类?
Q2.11 我用了package的时候显示"NoClassDefFoundError",但是我把所有package去掉

时候能正常运行。
Q2.12 我想把java编译成exe文件,该怎么做?
Q2.13 我在编译的时候遇到什么"deprecated API",是什么意思?
Q3.1 我怎么给java程序加启动参数,就像dir /p/w那样?
Q3.2 我怎么从键盘输入一个int/double/字符串?
Q3.3 我怎么输出一个int/double/字符串?
Q3.4 我发现有些书上直接用System.in输入,比你要简单得多。
Q3.5 我怎么从文件输入一个int/double/字符串?
Q3.6 我想读写文件的指定位置,该怎么办?
Q3.7 怎么判断要读的文件已经到了尽头?
Q4.1  java里面怎么定义宏?
Q4.2  java里面没法用const。
Q4.3  java里面也不能用goto。
Q4.4  java里面能不能重载操作符?
Q4.5  我new了一个对象,但是没法delete掉它。
Q4.6  我想知道为什么main方法必须被声明为public static?为什么在main方法中不能

用非static成员?
Q4.7  throw和throws有什么不同?
Q4.8  什么是异常?
Q4.9  final和finally有什么不同?
Q5.1  extends和implements有什么不同?
Q5.2  java怎么实现多继承?
Q5.3 abstract是什么?
Q5.4 public,protected,private有什么不同?
Q5.5 Override和Overload有什么不同?
Q5.6 我继承了一个方法,但现在我想调用在父类中定义的方法。
Q5.7 我想在子类的构造方法中调用父类的构造方法,该怎么办?
Q5.8 我在同一个类中定义了好几个构造方法并且想在一个构造方法中调用另一个。
Q5.9 我没有定义构造方法会怎么样?
Q5.10 我调用无参数的构造方法失败了。
Q5.11 我该怎么定义类似于C++中的析构方法(destructor)?
Q5.12 我想将一个父类对象转换成一个子类对象该怎么做?
Q5.13 其实我不确定a是不是B的实例,能不能分情况处理?
Q5.14 我在方法里修改了一个对象的值,但是退出方法后我发现这个对象的值没变!
Q6.1 java能动态分配数组吗?
Q6.2 我怎么知道数组的长度?
Q6.3 我还想让数组的长度能自动改变,能够增加/删除元素。
Q6.4 什么是链表?为什么要有ArrayList和LinkedList两种List?
Q6.5 我想用队列/栈。
Q6.6 我希望不要有重复的元素。
Q6.7 我想遍历集合/Map。
Q6.8 我还要能够排序。
Q6.9 但是我想给数组排序。
Q6.10 我想按不同方式排序。
Q6.11 Map有什么用?
Q6.12 set方法没问题,但是get方法返回的是Object。
Q6.13 ArrayList和Vector有什么不同?HashMap和Hashtable有什么不同?
Q6.14 我要获得一个随机数。
Q6.15 我比较两个String总是false,但是它们明明都是"abc" !
Q6.16 我想修改一个String但是在String类中没找到编辑方法。
Q6.17 我想处理日期/时间。

一、准备篇

Q1.1 什么是Java、Java2、JDK?JDK后面的1.3、1.4版本号又是怎么回事?
答:Java是一种通用的,并发的,强类型的,面向对象的编程语言(摘自Java规范第二

)。
JDK是Sun公司分发的免费Java开发工具包,正式名称为J2SDK(Java2 Software Develop 
K
it)。
包括基本的java工具包和标准类库。
到目前(2003年7月)为止,Java有3个主要版本,即1.0,1.1,2.0;
JDK有1.0,1.1,1.2,1.3,1.4五个版本。
从JDK1.2起,Sun公司觉得Java改变足够大而将java语言版本号提升为2.0。
不同的JDK主要在于提供的类库不同。作为学习你可以下载最新的JDK1.4.2。
真正开发时则应考虑向前兼容,比如1.3。下载请去http://java.sun.com
JDK1.5预计将在2004年推出,届时其中将包含若干崭新的特性。

Q1.2 什么是JRE/J2RE?
答:J2RE是Java2 Runtime Environment,即Java运行环境,有时简称JRE。
如果你只需要运行Java程序或Applet,下载并安装它即可。
如果你要自行开发Java软件,请下载JDK。在JDK中附带有JRE。
注意由于Microsoft对Java的支持不完全,请不要使用IE自带的虚拟机来运行Applet,务

安装一个JRE或JDK。

Q1.3 学习Java用什么工具比较好?
答:作者建议首先使用JDK+文本编辑器,这有助你理解下列几个基础概念:path,
classp
ath,package 
并熟悉基本命令:javac和java。并且下载和你的JDK版本一致的API帮助。
如果你不确定类或函数的用法,请先查阅API而不是发贴求助。
当你熟悉Java之后,你可以考虑开始使用一个IDE。
作者推荐eclipse,下载网址http://www.eclipse.org。因为eclispe是免费的,插件化


eclispe的主要缺点是缺乏一个可视化的桌面程序开发工具,
幸运的是IBM在2003年11月已经将部分代码捐给eclipse组织,可以预计这个缺点很快就

得到弥补。
无论如何,请不要使用Microsoft的VJ++!众所周知Microsoft从来就没有认真支持过
Java

最后但并非最不重要,要有一本好的参考书,并且英文要过关。

Q1.4  学习Java有哪些好的参考书?
答:作者首先推荐Thinking in Java,中文名《Java编程思想》,有中文版。
目前的最新版本是第三版。
http://64.78.49.204可以免费下载英文版。
该书第一章介绍了很多面向对象的编程思想,作为新手应当认真阅读。
除此以外,O'relly出版社和Wrox出版社的书也不错。作者本人不喜欢大陆作者的书。
也许你觉得英文太难,但是网上大多数资料都是英文的。另外,你需要经常查阅API,而

也是英文的。

Q1.5  Java和C++哪个更好?
答:这个问题是一个很不恰当的问题。你应该问:Java和C++哪个更适用于我的项目?
Java的优点和缺点一样明显。
跨平台是Java的主要优点,但代价是运行速度的下降。
VC和Windows平台有良好的集成和足够快的速度,但是也只能局限在Windows平台上。
和C++相比,Java学起来更快,开发人员不会碰到很多容易出错的特性。
但是VB程序员甚至只需要拼装模块就可以了。

Q1.6  什么是J2SE/J2EE/J2ME?
答:J2SE就是一般的Java。
J2ME是针对嵌入式设备的,比如支持Java的手机,它有自己的JRE和SDK。
J2EE是一组用于企业级程序开发的规范和类库,它使用J2SE的JRE。

二、命令篇

Q2.1  我写了第一个Java程序,应该如何编译/运行?
答:首先请将程序保存为xxx.java文件,注意你可能需要修改文件后缀名。
然后在dos窗口下使用javac xxx.java命令,你会发现该目录下多了一个xxx.class文
件,

再使用java xxx命令,你的java程序就开始运行了。

Q2.2  我照你说的做了,但是出现什么“'javac' 不是内部或外部命令,也不是可运行

程序或批处理文件。”。
答:你遇到了path问题。操作系统在一定的范围(path)内搜索javac.exe,但是没能找
到。

请编辑你的操作系统环境变量,新增一个JAVA_HOME变量,设为你JDK的安装目录,
再编辑Path变量,加上一项 %JAVA_HOME%\bin。
然后保存并新开一个dos窗口,你就可以使用javac和java命令了。

Q2.3  环境变量怎么设置?
答:请向身边会设的人咨询。

Q2.4  我在javac xxx.java的时候显示什么“unreported exception 
java.io.IOExcepti
on;”。
答:参见Q4.8以了解java中的异常机制。

Q2.5  javac xxx.java顺利通过了,但是java xxx的时候显示什么
“NoClassDefFoundErr
or”。
答:1. 你遇到了classpath问题。java命令在一定的范围(classpath)内搜索你直接或间

使用的class文件,但是未能找到。
首先请确认你没有错敲成java xxx.class,
其次,检查你的CLASSPATH环境变量,其实你并不需要设置该变量,
但如果你设置了该变量又没有包含.(代表当前目录)的项,
你就会遇到这个问题。请在你的CLASSPATH环境变量中加入一项. 或干脆删掉这个变量。

2. 如果你使用了并非JDK自带的标准包,比如javax.servlet.*包,也会遇到这个问题,

将相应的jar文件加入classpath。
3. 如果你在java源文件中定义了package,请参见Q2.11。


Q2.6  我在java xxx的时候显示“Exception in thread "main" 
java.lang.NoSuchMetho
dError: main”。
答:首先,在你的程序中每个java文件有且只能有一个public类,
这个类的类名必须和文件名的大小写完全一样。
其次,在你要运行的类中有且只能有一个public static void main(String[] args)方


这个方法就是你的主程序。


Q2.7  在java xxx的时候显示“Exception in thread "main" 
java.lang.NullPointerEx
ception”。
答:在程序中你试图在值为null的对象变量上调用方法,请检查你的程序确保你的对象
被恰当的初始化。
参见Q4.8以了解java中的异常机制。


Q2.8 package是什么意思?怎么用?
答:为了唯一标识每个类并分组,java使用了package的概念。
每个类都有一个全名,例如String的全名是java.lang.String,其中java.lang是包名,
S
tring是短名。按照java命名惯例,包名是全部小写的,而类名的第一个字母是大写的。
这样,如果你自行定义了同样名字的类String,你可以把它放在mypackage中,
通过使用全名mypackage.String和java.lang.String来区分这两个类。
同时,将逻辑上相关的类放在同一个包中,可以使程序结构更为清楚。
为了定义包,你要做的就是在java文件开头加一行“package mypackage;”。
注意包没有嵌套或包含关系,mypackage包和mypackage.mysubpackage包对JRE来说是并
列的两个包(虽然开发者可
能暗示包含关系)。

Q2.9 我没有声明任何package会怎么样?
答:你的类被认为放在默认包中。这时全名和短名是一致的。

Q2.10 在一个类中怎么使用其他类?
答:如果你使用java.lang包或者默认包中的类,不用做任何事。
如果你的类位于mypackage包中,并且要调用同一包中的其他类,也不用做任何事。
如果你使用其他包中的类,在package声明之后,类声明之前使用import 
otherpackage1.Class
1; 或 import otherpackage2.*;  
这里.*表示引入这个包中的所有类。然后在程序中你可以使用其他类的短名。
如果短名间有重名冲突,必须使用全名来区分。
注意在使用其他包中的类时,你只能使用public的类和接口,参见Q5.4。

Q2.11 我用了package的时候显示"NoClassDefFoundError",但是我把所有package去掉

时候能正常运行。
答:将你的java文件按包名组织存放。
比如你的工作目录是/work,你的类是package1.Class1,那么将它存放
为/work/package1
/Class1.java。
如果没有声明包,那么直接放在/work下。
在/work下执行javac package1/class1.java,再执行java package1.class1,你会发现

切正常。
另外,如果你的类的个数已经多到了你需要使用包来组织的话,你可以考虑开始使用
IDE。

Q2.12 我想把java编译成exe文件,该怎么做?
答:JDK只能将java源文件编译为class文件。
class文件是一种跨平台的字节码,必须依赖平台相关的JRE来运行。Java以此来实现跨

台性。
有些开发工具可以将java文件编译为exe文件。作者反对这种做法,因为这样就取消了跨

台性。
如果你确信你的软件只在Windows平台上运行,你可以考虑使用C++/C#来编程。

Q2.13 我在编译的时候遇到什么"deprecated API",是什么意思?
答:所谓deprecated是指已经过时,但是为了向前兼容起见仍然保留的方法。
这些方法可能会在以后取消支持。你应当改用较新的方法。
在API里面会说明你应当用什么方法来代替之。

三、I/O篇

Q3.1 我怎么给java程序加启动参数,就像dir /p/w那样?
答:还记得public static void main(String[] args)吗?这里的args就是你的启动参


在运行时你输入java package1.class1 arg1 arg2,args中就会有两个String,第一个

arg1,第二个是arg2。

Q3.2 我怎么从键盘输入一个int/double/字符串?
答:java的I/O操作比C++要复杂一点。如果要从键盘输入,样例代码如下:
BufferedReader cin = new BufferedReader( new InputStreamReader( 
System.in ) );

String s = cin.readLine();
这样你就获得了一个字符串,如果你需要数字的话再使用:
int n = Integer.parseInt( s ); 或者 double d = Double.parseDouble( s );
来将字符串"534"转换成int或double。

Q3.3 我怎么输出一个int/double/字符串?
答:使用System.out.println(n)或者System.out.println("Hello")等等。

Q3.4 我发现有些书上直接用System.in输入,比你要简单得多。
答:java使用unicode,是双字节。而System.in是单字节的stream。
如果你要输入双字节文字比如中文,请使用作者的做法。

Q3.5 我怎么从文件输入/输出一个int/double/字符串?
答:类似于从键盘输入,只不过换成
BufferedReader fin = new BufferedReader( new FileReader(" myFileName " ) );
PrintWriter fout = new PrintWriter( new FileWriter(" myFileName " ) );
另外如果你还没下载API,请开始下载并阅读java.io包中的内容。

Q3.6 我想读写文件的指定位置,该怎么办?
答:java.io.RandomAccessFile可以满足你的需要。

Q3.7 怎么判断要读的文件已经到了尽头?
答:在Reader的read方法中明确说明返回-1表示流的结尾。

四、 关键字篇

Q4.1  java里面怎么定义宏?
答:java不支持宏,因为宏代换不能保证类型安全。
如果你需要定义常量,可以将它定义为某个类的static final成员。参见Q4.2和Q4.6。


Q4.2  java里面没法用const。
答:你可以用final关键字。例如 final int m = 9。被声明为final的变量不能被再次

值。唯一的例外是所谓blank final,如下例所示:
public class MyClass1 {
    private final int a = 3;
    private final int b; // blank final

    public MyClass1() {
        a = 5; // 不合法,final变量不能被再次赋值。
        b = 4; // 合法,这是b第一次被赋值。
        b = 6; // 不合法,b不能被再次赋值。
    }
}
final也可以用于声明方法或类,被声明为final的方法或类不能被继承。
注意const是java的保留字以备扩充。

Q4.3  java里面也不能用goto。
答:甚至在面向过程的语言中你也可以完全不用goto。请检查你的程序流程是否合理。

如果你需要从多层循环中迅速跳出,java增强了(和C++相比)break和continue的功
能,
支持label。
例如:
outer : 
while( ... )
{
    inner :
    for( ... )
    {
           ...   break inner; ...
           ... continue outer; ...
    }
}
和const一样,goto也是java的保留字以备扩充。

Q4.4  java里面能不能重载操作符?
答:不能。String的+号是唯一一个内置的重载操作符。你可以通过定义接口和方法来实

类似功能。

Q4.5  我new了一个对象,但是没法delete掉它。
答:java有自动内存回收机制,即所谓Garbarge Collection。你不需要删除对象。你再

不用担心指针错误,内存溢出了。

Q4.6  我想知道为什么main方法必须被声明为public static?为什么在main方法中不能

用非static成员?
答:声明为public是为了这个方法可以被外部调用,详情见Q5.4。
static是为了将某个成员变量/方法关联到类(class)而非实例(instance)。
你不需要创建一个对象就可以直接使用这个类的static成员,因而在static成员中不能

用非static成员,因为后者是关联到对象实例(instance)的。
在A类中调用B类的static成员可以使用B.staticMember的写法。
注意一个类的static成员变量是唯一的,被所有该类对象所共享的,在多线程程序设计
中尤其要谨慎小心。
类的static成员是在类第一次被JRE装载的时候初始化的。
你可以使用如下方法来使用非static成员:
public class A
{
    private void someMethod() //非static成员
    {}
    public static void main(String args)
    {
         A a = new A();  //创建一个对象实例
         a.someMethod();  //现在你可以使用非static方法了
    }
}


Q4.7  throw和throws有什么不同?
答:throws用于方法声明中,声明一个方法会抛出哪些异常。而throw是在方法体中实际
执行抛出异常的
动作。
如果你在方法中throw一个异常,却没有在方法声明中声明之,编译器会报错。
注意Error和RuntimeException的子类是例外,无需特别声明。

Q4.8  什么是异常?
答:异常最早在Ada语言中引入,用于在程序中动态处理错误并恢复。
你可以在方法中拦截底层异常并处理之,也可以抛给更高层的模块去处理。
你也可以抛出自己的异常指示发生了某些不正常情况。常见的拦截处理代码如下:
try
{
    ......//以下是可能发生异常的代码
        ...... //异常被你或低层API抛出,执行流程中断并转向拦截代码。
        ...... 
}
catch(Exception1 e) //如果Exception1是Exception2的子类并要做特别处理,应排在


{
  //发生Exception1时被该段拦截
}
catch(Exception2 e)
{
  //发生Exception2时被该段拦截
}
finally //这是可选的
{
   //无论异常是否发生,均执行此段代码
   //即使在catch段中又向外抛出了新的exception,finally段也会得到执行。
}

Q4.9  final和finally有什么不同?
答:final请见Q4.2。finally用于异常机制,参见Q4.8。

五、 面向对象篇

Q5.1  extends和implements有什么不同?
答:对于class而言,extends用于(单)继承一个类(class),而implements用于实现
一个接口(interf
ace)。
interface的引入是为了部分地提供多继承的功能。
在interface中只需声明方法头,而将方法体留给实现的class来做。
这些实现的class的实例完全可以当作interface的实例来对待。
在interface之间也可以声明为extends(多继承)的关系。
注意一个interface可以extends多个其他interface。

Q5.2  java怎么实现多继承?
答:java不支持显式的多继承。
因为在显式多继承的语言例如c++中,会出现子类被迫声明祖先虚基类构造函数的问题,

而这是违反面向对象的封装性原则的。
java提供了interface和implements关键字来部分地实现多继承。参见Q5.1。

Q5.3 abstract是什么?
答:被声明为abstract的方法无需给出方法体,留给子类来实现。
而如果一个类中有abstract方法,那么这个类也必须声明为abstract。
被声明为abstract的类无法实例化,尽管它可以定义构造方法供子类使用。

Q5.4 public,protected,private有什么不同?
答:这些关键字用于声明类和成员的可见性。
public成员可以被任何类访问,
protected成员限于自己和子类访问,
private成员限于自己访问。
Java还提供了第四种的默认可见性,一般称为package private,当没有任何
public,protected,private修饰符时,成员
是同一包内可见。
类可以用public或默认来修饰。

Q5.5 Override和Overload有什么不同?
答:Override是指父类和子类之间方法的继承关系,这些方法有着相同的名称和参数类


Overload是指同一个类中不同方法(可以在子类也可以在父类中定义)间的关系,
这些方法有着相同的名称和不同的参数类型。


Q5.6 我继承了一个方法,但现在我想调用在父类中定义的方法。
答:用super.xxx()可以在子类中调用父类方法。

Q5.7 我想在子类的构造方法中调用父类的构造方法,该怎么办?
答:在子类构造方法的第一行调用super(...)即可。

Q5.8 我在同一个类中定义了好几个构造方法并且想在一个构造方法中调用另一个。
答:在构造方法第一行调用this(...)。

Q5.9 我没有定义构造方法会怎么样?
答:自动获得一个无参数的构造方法。

Q5.10 我调用无参数的构造方法失败了。
答:如果你至少定义了一个构造方法,就不再有自动提供的无参数的构造方法了。
你需要另外显式定义一个无参数的构造方法。
另外一种可能是你的构造方法或者类不是public的,参见Q5.4了解java中的可见性。

Q5.11 我该怎么定义类似于C++中的析构方法(destructor)?
答:提供一个void finalize()方法。在Garbarge Collector回收该对象时会调用该方
法。

注意实际上你很难判断一个对象会在什么时候被回收。作者从未感到需要用到该方法。


Q5.12 我想将一个父类对象转换成一个子类对象该怎么做?
答:强制类型转换。如
public void meth(A a)
{
    B b = (B)a;
}
如果a实际上并不是B的实例,会抛出ClassCastException。所以请确保a确实是B的实
例。


Q5.13 其实我不确定a是不是B的实例,能不能分情况处理?
答:可以使用instanceof操作符。例如
if( a instanceof B )
{
    B b = (B)a;
}
else
{
    ...
}

Q5.14 我在方法里修改了一个对象的值,但是退出方法后我发现这个对象的值没变!
答:很可能你把传入参数重赋了一个新对象,例如下列代码就会造成这种错误:
public void fun1(A a) //a是局部参数,指向了一个外在对象。
{
    a = new A(); //a指向了一个新对象,和外在对象脱钩了。如果你要让a作为
传出变量,
不要写这一句。
        a.setAttr(attr);//修改了新对象的值,外在对象没有被修改。
}
基本类型也会出现这种情况。例如:
public void fun2(int a)
{
    a = 10;//只作用于本方法,外面的变量不会变化。
}

六、java.util篇

Q6.1 java能动态分配数组吗?
答:可以。例如int n = 3; Language[] myLanguages = new Language[n];

Q6.2 我怎么知道数组的长度?
答:用length属性。如上例中的  myLanguages.length 就为 3。

Q6.3 我还想让数组的长度能自动改变,能够增加/删除元素。
答:用顺序表--java.util.List接口。
你可以选择用ArrayList或是LinkedList,前者是数组实现,后者是链表实现。
例如:  List list = new ArrayList(); 或是 List list = new LinkedList();  。

Q6.4 什么是链表?为什么要有ArrayList和LinkedList两种List?
答:请补习数据结构。

Q6.5 我想用队列/栈。
答:用java.util.LinkedList。

Q6.6 我希望不要有重复的元素。
答:用集合--java.util.Set接口。例如:Set set = new HashSet()。

Q6.7 我想遍历集合/Map。
答:用java.util.Iterator。参见API。

Q6.8 我还要能够排序。
答:用java.util.TreeSet。例如:Set set = new TreeSet()。放进去的元素会自动排


你需要为元素实现Comparable接口,还可能需要提供equals()方法,compareTo()方法,
h
ashCode()方法。

Q6.9 但是我想给数组排序。
答:java.util.Arrays类包含了sort等实用方法。

Q6.10 我想按不同方式排序。
答:为每种方式定义一个实现了接口Comparator的排序类并和Arrays或TreeSet综合运
用。


Q6.11 Map有什么用?
答:存储key-value的关键字-值对,你可以通过关键字来快速存取相应的值。

Q6.12 set方法没问题,但是get方法返回的是Object。
答:强制类型转换成你需要的类型。参见Q5.12。

Q6.13 ArrayList和Vector有什么不同?HashMap和Hashtable有什么不同?
答:ArrayList和HashMap是多线程不安全的,在多个线程中访问同一个ArrayList对象可

会引起冲突并导致错误。
而Vector和Hashtable是多线程安全的,即使在多个线程中同时访问同一个Vector对象也

会引起差错。
看起来我们更应该使用Vector和Hashtable,但是实际上Vector和Hashtable的性能太
差,
所以如果你不在多线程中使用的话,还是应该用ArrayList和HashMap。

Q6.14 我要获得一个随机数。
答:使用java.util.Random类。

Q6.15 我比较两个String总是false,但是它们明明都是"abc" !
答:比较String一定要使用equals或equalsIgnoreCase方法,不要使用 == !
==比较的是两个引用(变量)是否指向了同一个对象,而不是比较其内容。

Q6.16 我想修改一个String但是在String类中没找到编辑方法。
答:使用StringBuffer类。
String str = "......."; //待处理的字符串
StringBuffer buffer = new StringBuffer(str); //使用该字符串初始化一个
StringBuf
fer
buffer.append("..."); //调用StringBuffer的相关API来编辑字符串
String str2 = buffer.toString(); //获得编辑后的字符串。
另外,如果你需要将多个字符串连接起来,请尽量避免使用+号直接连接,而是使用
Strin
gBuffer.append()方法。

Q6.17 我想处理日期/时间。
答:使用java.util.Date类。你可以使用java.text.SimpleDateFormat类来在String和
Da
te间互相转换。
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //

定日期格式
Date date = formatter.parse("2003-07-26 18:30:35"); //将符合格式的String转换

Date
String s = formatter.format(date); //将Date转换为符合格式的String
关于定义日期格式的详细信息请参见API。


我的Transact_SQL小手册
转贴     

--语 句 功 能
--数据操作
SELECT --从数据库表中检索数据行和列
INSERT --向数据库表添加新数据行
DELETE --从数据库表中删除数据行
UPDATE --更新数据库表中的数据
--数据定义
CREATE TABLE --创建一个数据库表
DROP TABLE --从数据库中删除表
ALTER TABLE --修改数据库表结构
CREATE VIEW --创建一个视图
DROP VIEW --从数据库中删除视图
CREATE INDEX --为数据库表创建一个索引
DROP INDEX --从数据库中删除索引
CREATE PROCEDURE --创建一个存储过程
DROP PROCEDURE --从数据库中删除存储过程
CREATE TRIGGER --创建一个触发器
DROP TRIGGER --从数据库中删除触发器
CREATE SCHEMA --向数据库添加一个新模式
DROP SCHEMA --从数据库中删除一个模式
CREATE DOMAIN --创建一个数据值域
ALTER DOMAIN --改变域定义
DROP DOMAIN --从数据库中删除一个域
--数据控制
GRANT --授予用户访问权限
DENY --拒绝用户访问
REVOKE --解除用户访问权限
--事务控制
COMMIT --结束当前事务
ROLLBACK --中止当前事务
SET TRANSACTION --定义当前事务数据访问特征
--程序化SQL
DECLARE --为查询设定游标
EXPLAN --为查询描述数据访问计划
OPEN --检索查询结果打开一个游标
FETCH --检索一行查询结果
CLOSE --关闭游标
PREPARE --为动态执行准备SQL 语句
EXECUTE --动态地执行SQL 语句
DESCRIBE --描述准备好的查询
---局部变量
declare @id char(10)
--set @id = ´10010001´
select @id = ´10010001´
---全局变量
---必须以@@开头
--IF ELSE
declare @x int @y int @z int
select @x = 1 @y = 2 @z=3
if @x > @y
print ´x > y´ --打印字符串´x > y´
else if @y > @z
print ´y > z´
else print ´z > y´
--CASE
use pangu
update employee
set e_wage =
case
when job_level = ’1’ then e_wage*1.08
when job_level = ’2’ then e_wage*1.07
when job_level = ’3’ then e_wage*1.06
else e_wage*1.05
end
--WHILE CONTINUE BREAK
declare @x int @y int @c int
select @x = 1 @y=1
while @x < 3
begin
print @x --打印变量x 的值
while @y < 3
begin
select @c = 100*@x + @y
print @c --打印变量c 的值
select @y = @y + 1
end
select @x = @x + 1
select @y = 1
end
--WAITFOR
--例 等待1 小时2 分零3 秒后才执行SELECT 语句
waitfor delay ’01:02:03’
select * from employee
--例 等到晚上11 点零8 分后才执行SELECT 语句
waitfor time ’23:08:00’
select * from employee 
***SELECT***
select *(列名) from table_name(表名) where column_name operator value
ex宿主)
select * from stock_information where stockid = str(nid)
stockname = ´str_name´ 
stockname like ´% find this %´ 
stockname like ´[a-zA-Z]%´ --------- ([]指定值的范围)
stockname like ´[^F-M]%´ --------- (^排除指定范围)
--------- 只能在使用like关键字的where子句中使用通配符)
or stockpath = ´stock_path´
or stocknumber < 1000
and stockindex = 24
not stocksex = ´man´
stocknumber between 20 and 100
stocknumber in(10,20,30)
order by stockid desc(asc) --------- 排序,desc-降序,asc-升序
order by 1,2 --------- by列号
stockname = (select stockname from stock_information where stockid = 4)
--------- 子查询
--------- 除非能确保内层select只返回一个行的值,
--------- 否则应在外层where子句中用一个in限定符
select distinct column_name form table_name --------- distinct指定检索独有的列值,不重复
select stocknumber ,"stocknumber + 10" = stocknumber + 10 from table_name
select stockname , "stocknumber" = count(*) from table_name group by stockname
--------- group by 将表按行分组,指定列中有相同的值
having count(*) = 2 --------- having选定指定的组
select * 
from table1, table2 
where table1.id *= table2.id -------- 左外部连接,table1中有的而table2中没有得以null表示
table1.id =* table2.id -------- 右外部连接 
select stockname from table1
union [all] ----- union合并查询结果集,all-保留重复行
select stockname from table2
***insert***
insert into table_name (Stock_name,Stock_number) value ("xxx","xxxx")
value (select Stockname , Stocknumber from Stock_table2)---value为select语句
***update***
update table_name set Stockname = "xxx" [where Stockid = 3]
Stockname = default
Stockname = null
Stocknumber = Stockname + 4
***delete***
delete from table_name where Stockid = 3
truncate table_name ----------- 删除表中所有行,仍保持表的完整性
drop table table_name --------------- 完全删除表
***alter table*** --- 修改数据库表结构
alter table database.owner.table_name add column_name char(2) null .....
sp_help table_name ---- 显示表已有特征
create table table_name (name char(20), age smallint, lname varchar(30))
insert into table_name select ......... ----- 实现删除列的方法(创建新表)
alter table table_name drop constraint Stockname_default ---- 删除Stockname的default约束
***function(/*常用函数*/)***
----统计函数----
AVG --求平均值
COUNT --统计数目
MAX --求最大值
MIN --求最小值
SUM --求和
--AVG
use pangu
select avg(e_wage) as dept_avgWage
from employee
group by dept_id
--MAX
--求工资最高的员工姓名
use pangu
select e_name
from employee
where e_wage =
(select max(e_wage)
from employee)
--STDEV()
--STDEV()函数返回表达式中所有数据的标准差
--STDEVP()
--STDEVP()函数返回总体标准差
--VAR()
--VAR()函数返回表达式中所有值的统计变异数
--VARP()
--VARP()函数返回总体变异数
----算术函数----
/***三角函数***/
SIN(float_expression) --返回以弧度表示的角的正弦
COS(float_expression) --返回以弧度表示的角的余弦
TAN(float_expression) --返回以弧度表示的角的正切
COT(float_expression) --返回以弧度表示的角的余切
/***反三角函数***/
ASIN(float_expression) --返回正弦是FLOAT 值的以弧度表示的角
ACOS(float_expression) --返回余弦是FLOAT 值的以弧度表示的角
ATAN(float_expression) --返回正切是FLOAT 值的以弧度表示的角
ATAN2(float_expression1,float_expression2) 
--返回正切是float_expression1 /float_expres-sion2的以弧度表示的角
DEGREES(numeric_expression)
--把弧度转换为角度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT 类型
RADIANS(numeric_expression) --把角度转换为弧度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT 类型
EXP(float_expression) --返回表达式的指数值
LOG(float_expression) --返回表达式的自然对数值
LOG10(float_expression)--返回表达式的以10 为底的对数值
SQRT(float_expression) --返回表达式的平方根
/***取近似值函数***/
CEILING(numeric_expression) --返回>=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
FLOOR(numeric_expression) --返回<=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
ROUND(numeric_expression) --返回以integer_expression 为精度的四舍五入值返回的数据
--类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
ABS(numeric_expression) --返回表达式的绝对值返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT 类型
SIGN(numeric_expression) --测试参数的正负号返回0 零值1 正数或-1 负数返回的数据类型
--与表达式相同可为INTEGER/MONEY/REAL/FLOAT 类型
PI() --返回值为π 即3.1415926535897936
RAND([integer_expression]) --用任选的[integer_expression]做种子值得出0-1 间的随机浮点数
----字符串函数----
ASCII() --函数返回字符表达式最左端字符的ASCII 码值
CHAR() --函数用于将ASCII 码转换为字符
--如果没有输入0 ~ 255 之间的ASCII 码值CHAR 函数会返回一个NULL 值
LOWER() --函数把字符串全部转换为小写
UPPER() --函数把字符串全部转换为大写
STR() --函数把数值型数据转换为字符型数据
LTRIM() --函数把字符串头部的空格去掉
RTRIM() --函数把字符串尾部的空格去掉
LEFT(),RIGHT(),SUBSTRING() --函数返回部分字符串
CHARINDEX(),PATINDEX() --函数返回字符串中某个指定的子串出现的开始位置
SOUNDEX() --函数返回一个四位字符码 
--SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0 值 
DIFFERENCE() --函数返回由SOUNDEX 函数返回的两个字符表达式的值的差异
--0 两个SOUNDEX 函数返回值的第一个字符不同
--1 两个SOUNDEX 函数返回值的第一个字符相同
--2 两个SOUNDEX 函数返回值的第一二个字符相同
--3 两个SOUNDEX 函数返回值的第一二三个字符相同
--4 两个SOUNDEX 函数返回值完全相同
QUOTENAME() --函数返回被特定字符括起来的字符串
/*select quotename(´abc´, ´{´) quotename(´abc´)
运行结果如下
----------------------------------{
{abc} [abc]*/
REPLICATE() --函数返回一个重复character_expression 指定次数的字符串
/*select replicate(´abc´, 3) replicate( ´abc´, -2)
运行结果如下
----------- -----------
abcabcabc NULL*/
REVERSE() --函数将指定的字符串的字符排列顺序颠倒
REPLACE() --函数返回被替换了指定子串的字符串
/*select replace(´abc123g´, ´123´, ´def´)
运行结果如下
----------- -----------
abcdefg*/
SPACE() --函数返回一个有指定长度的空白字符串
STUFF() --函数用另一子串替换字符串指定位置长度的子串
----数据类型转换函数----
CAST() 函数语法如下
CAST() (<expression> AS <data_ type>[ length ])
CONVERT() 函数语法如下
CONVERT() (<data_ type>[ length ], <expression> [, style])
select cast(100+99 as char) convert(varchar(12), getdate())
运行结果如下
------------------------------ ------------
199 Jan 15 2000
----日期函数----
DAY() --函数返回date_expression 中的日期值
MONTH() --函数返回date_expression 中的月份值
YEAR() --函数返回date_expression 中的年份值
DATEADD(<datepart> ,<number> ,<date> ) 
--函数返回指定日期date 加上指定的额外日期间隔number 产生的新日期
DATEDIFF(<datepart> ,<number> ,<date> )
--函数返回两个指定日期在datepart 方面的不同之处
DATENAME(<datepart> , <date> ) --函数以字符串的形式返回日期的指定部分
DATEPART(<datepart> , <date> ) --函数以整数值的形式返回日期的指定部分
GETDATE() --函数以DATETIME 的缺省格式返回系统当前的日期和时间
----系统函数----
APP_NAME() --函数返回当前执行的应用程序的名称
COALESCE() --函数返回众多表达式中第一个非NULL 表达式的值
COL_LENGTH(<´table_name´>, <´column_name´> ) --函数返回表中指定字段的长度值
COL_NAME(<table_id>, <column_id> ) --函数返回表中指定字段的名称即列名
DATALENGTH() --函数返回数据表达式的数据的实际长度
DB_ID([´database_name´]) --函数返回数据库的编号
DB_NAME(database_id) --函数返回数据库的名称
HOST_ID() --函数返回服务器端计算机的名称
HOST_NAME() --函数返回服务器端计算机的名称
IDENTITY(<data_type>[, seed increment]) [AS column_name])
--IDENTITY() 函数只在SELECT INTO 语句中使用用于插入一个identity column列到新表中
/*select identity(int, 1, 1) as column_name
into newtable
from oldtable*/
ISDATE() --函数判断所给定的表达式是否为合理日期
ISNULL(<check_expression>, <replacement_value> ) --函数将表达式中的NULL 值用指定值替换
ISNUMERIC() --函数判断所给定的表达式是否为合理的数值
NEWID() --函数返回一个UNIQUEIDENTIFIER 类型的数值
NULLIF(<expression1>, <expression2> )
--NULLIF 函数在expression1 与expression2 相等时返回NULL 值若不相等时则返回expression1 的值



ajax、Struts、spring的无缝结合
zhipingch 原创   更新:2006-12-17 01:27:22  版本: 1.0   

    [color=blue]转贴请保留作者--简单就好,和出处。谢谢![/color]
    去年初,正好负责一个医药信息系统的设计开发,架构设计时,采用Struts+JDBC(自定义采用适配器模式封装了HashMap动态VO实现的持久层)。后来ajax热潮兴起,正好系统中有很多地方需要和服务器端交互数据,如采购销售系统中的订单头/订单明细等主从表结构的维护。
    [color=blue]数据交互过程[/color],我们考虑采用xml来组织数据结构,更新/保存:前台封装需要的xml,通过ajax提交---〉action解析xml ---〉改造原有的持久层实现xml持久化;
    查询时:持久层根据实际需要返回xml,document对象,---〉action 处理 --〉前台自己封装js库来解析xml,并刷新部分页面。

    ajax:已经有很多方法实现跨浏览器的方式,这里只介绍最简单的方式,同步模式下提交xmlStr给action(*.do)。
  1. /**
  2.  * 将数据同步传递给后台请求url
  3.  *  @return 返回xmlhttp 响应的信息
  4.  *  @param-url = '/web/module/xxx.do?p1=YY&p2=RR';
  5.  *  @param-xmlStr:xml格式的字符串 <data><xpath><![CDATA[数据信息]]></xpath></data>
  6.  * @author zhipingch
  7.  * @date 2005-03-17
  8.  */
  9. function sendData(urlStr, xmlStr) {
  10.     var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
  11.     xmlhttp.open("POST", urlStr, false);
  12.     xmlhttp.setRequestHeader("Content-Type""application/x-www-form-urlencoded");
  13.     if (xmlStr) {
  14.         xmlhttp.send(xmlStr);
  15.     } else {
  16.         xmlhttp.send();
  17.     }
  18.     return xmlhttp.responseXml;
  19. }


    struts中我们扩展了Action,实现了xmlStr转化成document对象(dom4j),并且完善了转发方式。如
[quote]
1.DispatchAction
     以一个Controller响应一组动作绝对是Controller界的真理,Struts的DispatchAction同样可以做到这点。

[list]
<action path="/admin/user" name="userForm" scope="request" parameter="method" validate="false">
    <forward name="list" path="/admin/userList.jsp"/>
</action>
[/list]
    其中parameter="method" 设置了用来指定响应方法名的url参数名为method,即/admin/user.do?method=list 将调用UserAction的public ActionForward list(....) 函数。   

    public ActionForward unspecified(....) 函数可以指定不带method方法时的默认方法。[/quote]
    但是这样需要在url后多传递参数[size=18][color=red]method=list [/color][/size];并且action节点配置中的[color=red]parameter="method" [/color]
也没有被充分利用,反而觉得是累赘!

    因此我们直接在BaseDispatchAction中增加xml字符串解析,并充分利用action节点配置中的[color=red]parameter="targetMethod" [/color],使得转发的时候,action能够直接转发到子类的相应方法中,减少了url参数传递,增强了配置信息可读性,方便团队开发。
    同样以上述为例,扩展后的配置方式如下:
[quote]
<action path="/admin/user" scope="request" [color=red]parameter="list"[/color] validate="false">
    <forward name="list" path="/admin/userList.jsp"/>
</action>  
 [/quote]
    其中[color=red]parameter="list"[/color] 设置了用来指定响应url=/admin/user.do的方法名,它将调用UserAction的public ActionForward list(....) 函数。 
     BaseDispatchDocumentAction 的代码如下,它做了三件重要的事情:
     1、采用dom4j直接解析xml字符串,并返回document,如果没有提交xml数据,或者采用form形式提交的话,返回null;
     2、采用模版方法处理系统异常,减少了子类中无尽的try{...}catch(){...};其中异常处理部分另作描述(你可以暂时去掉异常处理,实现xml提交和解析,如果你有兴趣,我们可以进一步交流);
     3、提供了Spring配置Bean的直接调用,虽然她没有注入那么优雅,但是实现了ajax、struts、spring的结合。
BaseDispatchDocumentAction 的源码如下:
  1. package com.ufida.haisheng.struts;
  2. import java.io.IOException;
  3. import java.io.PrintWriter;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. import java.math.BigDecimal;
  7. import java.sql.Timestamp;
  8. import java.util.Date;
  9. import java.util.HashMap;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import javax.servlet.http.HttpSession;
  13. import org.apache.commons.beanutils.ConvertUtils;
  14. import org.apache.commons.beanutils.converters.BigDecimalConverter;
  15. import org.apache.commons.beanutils.converters.ClassConverter;
  16. import org.apache.commons.beanutils.converters.IntegerConverter;
  17. import org.apache.commons.beanutils.converters.LongConverter;
  18. import org.apache.log4j.Logger;
  19. import org.apache.struts.action.Action;
  20. import org.apache.struts.action.ActionForm;
  21. import org.apache.struts.action.ActionForward;
  22. import org.apache.struts.action.ActionMapping;
  23. import org.apache.struts.util.MessageResources;
  24. import org.dom4j.Document;
  25. import org.dom4j.io.SAXReader;
  26. import org.hibernate.HibernateException;
  27. import org.springframework.beans.BeansException;
  28. import org.springframework.context.ApplicationContext;
  29. import org.springframework.dao.DataAccessException;
  30. import org.springframework.web.context.support.WebApplicationContextUtils;
  31. import com.ufida.haisheng.constants.Globals;
  32. import com.ufida.haisheng.converter.DateConverter;
  33. import com.ufida.haisheng.converter.TimestampConverter;
  34. import com.ufida.haisheng.exp.ExceptionDTO;
  35. import com.ufida.haisheng.exp.ExceptionDisplayDTO;
  36. import com.ufida.haisheng.exp.exceptionhandler.ExceptionHandlerFactory;
  37. import com.ufida.haisheng.exp.exceptionhandler.ExceptionUtil;
  38. import com.ufida.haisheng.exp.exceptionhandler.IExceptionHandler;
  39. import com.ufida.haisheng.exp.exceptions.BaseAppException;
  40. import com.ufida.haisheng.exp.exceptions.MappingConfigException;
  41. import com.ufida.haisheng.exp.exceptions.NoSuchBeanConfigException;
  42. /**
  43.  * 系统的Ajax转发基类。增加模版处理异常信息。
  44.  * 
  45.  * @author 陈志平 chenzp
  46.  * @desc BaseDispatchDocumentAction.java
  47.  * 
  48.  * @说明: web 应用基础平台
  49.  * @date 2005-03-02 11:18:01 AM
  50.  * @版权所有: All Right Reserved 2006-2008
  51.  */
  52. public abstract class BaseDispatchDocumentAction extends Action {
  53.     protected Class clazz = this.getClass();
  54.     protected static Logger log = Logger.getLogger(BaseDispatchDocumentAction.class);
  55.     /**
  56.      * 异常信息
  57.      */
  58.     protected static ThreadLocal<ExceptionDisplayDTO> expDisplayDetails = new ThreadLocal<ExceptionDisplayDTO>();
  59.     
  60.     private static final Long defaultLong = null;
  61.     private static ApplicationContext ctx = null;
  62.     /**
  63.      * 注册转换的工具类 使得From中的string --
  64.      * Model中的对应的类型(Date,BigDecimal,Timestamp,Double...)
  65.      */
  66.     static {
  67.         ConvertUtils.register(new ClassConverter(), Double.class);
  68.         ConvertUtils.register(new DateConverter(), Date.class);
  69.         ConvertUtils.register(new DateConverter(), String.class);
  70.         ConvertUtils.register(new LongConverter(defaultLong), Long.class);
  71.         ConvertUtils.register(new IntegerConverter(defaultLong), Integer.class);
  72.         ConvertUtils.register(new TimestampConverter(), Timestamp.class);
  73.         ConvertUtils.register(new BigDecimalConverter(defaultLong), BigDecimal.class);
  74.     }
  75.     /**
  76.      * The message resources for this package.
  77.      */
  78.     protected static MessageResources messages = MessageResources.getMessageResources("org.apache.struts.actions.LocalStrings");
  79.     /**
  80.      * The set of Method objects we have introspected for this class, keyed by
  81.      * method name. This collection is populated as different methods are
  82.      * called, so that introspection needs to occur only once per method name.
  83.      */
  84.     protected HashMap<StringMethod> methods = new HashMap<StringMethod>();
  85.     /**
  86.      * The set of argument type classes for the reflected method call. These are
  87.      * the same for all calls, so calculate them only once.
  88.      */
  89.     protected Class[] types = { ActionMapping.class, ActionForm.classDocument.classHttpServletRequest.class,
  90.             HttpServletResponse.class };
  91.     /**
  92.      * Process the specified HTTP request, and create the corresponding HTTP
  93.      * response (or forward to another web component that will create it).
  94.      * Return an <code>ActionForward</code> instance describing where and how
  95.      * control should be forwarded, or <code>null</code> if the response has
  96.      * already been completed.
  97.      * 
  98.      * @param mapping
  99.      *            The ActionMapping used to select this instance
  100.      * @param form
  101.      *            The optional ActionForm bean for this request (if any)
  102.      * @param request
  103.      *            The HTTP request we are processing
  104.      * @param response
  105.      *            The HTTP response we are creating
  106.      * 
  107.      * @exception Exception
  108.      *                if an exception occurs
  109.      */
  110.     public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request,
  111.             HttpServletResponse response) throws Exception {
  112.         response.setContentType("text/html; charset=UTF-8");
  113.         ExceptionDisplayDTO expDTO = null;
  114.         try {
  115.             Document doc = createDocumentFromRequest(request);
  116.             /*
  117.              * 这里直接调用mapping的parameter配置
  118.              */
  119.             String actionMethod = mapping.getParameter();
  120.             /*
  121.              * 校验配置的方法是否正确、有效
  122.              */
  123.             isValidMethod(actionMethod);
  124.             return dispatchMethod(mapping, form, doc, request, response, actionMethod);
  125.         } catch (BaseAppException ex) {
  126.             expDTO = handlerException(request, response, ex);
  127.         } catch (Exception ex) {
  128.             ExceptionUtil.logException(this.getClass(), ex);
  129.             renderText(response,"[Error :对不起,系统出现错误了,请向管理员报告以下异常信息.\n" + ex.getMessage() + "]");
  130.             request.setAttribute(Globals.ERRORMSG, "对不起,系统出现错误了,请向管理员报告以下异常信息.\n" + ex.getMessage());
  131.             expDTO = handlerException(request,response, ex);
  132.         } finally {
  133.             expDisplayDetails.set(null);
  134.         }
  135.         return null == expDTO ? null : (expDTO.getActionForwardName() == null ? null : mapping.findForward(expDTO.getActionForwardName()));
  136.     }
  137.     /**
  138.      * 直接输出纯字符串
  139.      */
  140.     public void renderText(HttpServletResponse response, String text) {
  141.         PrintWriter out = null;
  142.         try {
  143.             out = response.getWriter();
  144.             response.setContentType("text/plain;charset=UTF-8");
  145.             out.write(text);
  146.         } catch (IOException e) {
  147.             log.error(e);
  148.         } finally {
  149.             if (out != null) {
  150.                 out.flush();
  151.                 out.close();
  152.                 out = null;
  153.             }
  154.         }
  155.     }
  156.     
  157.     /**
  158.      * 直接输出纯HTML
  159.      */
  160.     public void renderHtml(HttpServletResponse response, String text) {
  161.         PrintWriter out = null;
  162.         try {
  163.             out = response.getWriter();
  164.             response.setContentType("text/html;charset=UTF-8");
  165.             out.write(text);
  166.         } catch (IOException e) {
  167.             log.error(e);
  168.         } finally {
  169.             if (out != null) {
  170.                 out.flush();
  171.                 out.close();
  172.                 out = null;
  173.             }
  174.         }
  175.     }
  176.     /**
  177.      * 直接输出纯XML
  178.      */
  179.     public void renderXML(HttpServletResponse response, String text) {
  180.         PrintWriter out = null;
  181.         try {
  182.             out = response.getWriter();
  183.             response.setContentType("text/xml;charset=UTF-8");
  184.             out.write(text);
  185.         } catch (IOException e) {
  186.             log.error(e);
  187.         } finally {
  188.             if (out != null) {
  189.                 out.flush();
  190.                 out.close();
  191.                 out = null;
  192.             }
  193.         }
  194.     }
  195.     /**
  196.      * 异常处理
  197.      * @param request
  198.      * @param out
  199.      * @param ex
  200.      * @return ExceptionDisplayDTO异常描述对象
  201.      */
  202.     private ExceptionDisplayDTO handlerException(HttpServletRequest request,HttpServletResponse response, Exception ex) {
  203.         ExceptionDisplayDTO expDTO = (ExceptionDisplayDTO) expDisplayDetails.get();
  204.         if (null == expDTO) {            
  205.             expDTO = new ExceptionDisplayDTO(null,this.getClass().getName());
  206.         }
  207.         IExceptionHandler expHandler = ExceptionHandlerFactory.getInstance().create();
  208.         ExceptionDTO exDto = expHandler.handleException(expDTO.getContext(), ex);
  209.         request.setAttribute("ExceptionDTO", exDto);
  210.         renderText(response,"[Error:" + (exDto == null ? "ExceptionDTO is null,请检查expinfo.xml配置文件." : exDto.getMessageCode())
  211.                 + "]");
  212.         return expDTO;
  213.     }
  214.     private void isValidMethod(String actionMethod) throws MappingConfigException {
  215.         if (actionMethod == null || "execute".equals(actionMethod) || "perform".equals(actionMethod)) {
  216.             log.error("[BaseDispatchAction->error] parameter = " + actionMethod);
  217.             expDisplayDetails.set(new ExceptionDisplayDTO(null"MappingConfigException"));
  218.             throw new MappingConfigException("对不起,配置的方法名不能为 " + actionMethod);
  219.         }
  220.     }
  221.   /**
  222.      * 解析xml流
  223.      * @param request
  224.      * @return Document对象
  225.      */
  226.     protected static Document createDocumentFromRequest(HttpServletRequest request) throws Exception {
  227.         try {
  228.             request.setCharacterEncoding("UTF-8");
  229.             Document document = null;
  230.             SAXReader reader = new SAXReader();
  231.             document = reader.read(request.getInputStream());
  232.             return document;
  233.         } catch (Exception ex) {
  234.             log.warn("TIPS:没有提交获取XML格式数据流! ");
  235.             return null;
  236.         }
  237.     }
  238.     /**
  239.      * Dispatch to the specified method.
  240.      * 
  241.      * @since Struts 1.1
  242.      */
  243.     protected ActionForward dispatchMethod(ActionMapping mapping, ActionForm form, Document doc,HttpServletRequest request, HttpServletResponse response, String name) throws Exception {
  244.         Method method = null;
  245.         try {
  246.             method = getMethod(name);
  247.         } catch (NoSuchMethodException e) {
  248.             String message = messages.getMessage("dispatch.method", mapping.getPath(), name);
  249.             log.error(message, e);
  250.             expDisplayDetails.set(new ExceptionDisplayDTO(null"MappingConfigException"));
  251.             throw new MappingConfigException(message, e);
  252.         }
  253.         ActionForward forward = null;
  254.         try {
  255.             Object args[] = { mapping, form, doc, request, response };
  256.             log.debug("[execute-begin] -> " + mapping.getPath() + "->[" + clazz.getName() + "->" + name + "]");
  257.             forward = (ActionForward) method.invoke(this, args);
  258.             log.debug(" [execute-end] -> " + (null == forward ? "use ajax send to html/htm" : forward.getPath()));
  259.         } catch (ClassCastException e) {
  260.             String message = messages.getMessage("dispatch.return", mapping.getPath(), name);
  261.             log.error(message, e);
  262.             throw new BaseAppException(message, e);
  263.         } catch (IllegalAccessException e) {
  264.             String message = messages.getMessage("dispatch.error", mapping.getPath(), name);
  265.             log.error(message, e);
  266.             throw new BaseAppException(message, e);
  267.         } catch (InvocationTargetException e) {
  268.             Throwable t = e.getTargetException();
  269.             String message = messages.getMessage("dispatch.error", mapping.getPath(), name);
  270.             throw new BaseAppException(message, t);
  271.         }
  272.         return (forward);
  273.     }
  274.     /**
  275.      * Introspect the current class to identify a method of the specified name
  276.      * that accepts the same parameter types as the <code>execute</code>
  277.      * method does.
  278.      * 
  279.      * @param name
  280.      *            Name of the method to be introspected
  281.      * 
  282.      * @exception NoSuchMethodException
  283.      *                if no such method can be found
  284.      */
  285.     protected Method getMethod(String name) throws NoSuchMethodException {
  286.         synchronized (methods) {
  287.             Method method = (Method) methods.get(name);
  288.             if (method == null) {
  289.                 method = clazz.getMethod(name, types);
  290.                 methods.put(name, method);
  291.             }
  292.             return (method);
  293.         }
  294.     }
  295.   /**
  296.    * 返回spring bean对象
  297.    * @param name Spring Bean的名称
  298.    * @exception BaseAppException
  299.    */
  300.     protected Object getSpringBean(String name) throws BaseAppException {
  301.         if (ctx == null) {
  302.             ctx = WebApplicationContextUtils.getWebApplicationContext(this.getServlet().getServletContext());
  303.         }
  304.         Object bean = null;
  305.         try {
  306.             bean = ctx.getBean(name);
  307.         } catch (BeansException ex) {
  308.             throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!", ex.getRootCause());
  309.         }
  310.         if (null == bean) {
  311.             throw new NoSuchBeanConfigException("对不起,您没有配置名为:" + name + "的bean。请检查配置文件!");
  312.         }
  313.         return bean;
  314.     }
  315. }

开发人员只需要继承它就可以了,我们写个简单的示例action,如下:
  1. /**
  2.  * 带Ajax提交xml数据的action类模版
  3.  * 
  4.  * @author 陈志平 chenzp
  5.  * 
  6.  * @说明: web 应用基础平台
  7.  * @date Aug 1, 2006 10:52:13 AM
  8.  * @版权所有: All Right Reserved 2006-2008
  9.  */
  10. public class UserAction extends BaseDispatchDocumentAction {
  11.          /**
  12.           * 这里 actionForm 和 doc 参数必有一个为空,请聪明的你分析一下
  13.           * @param mapping --转发的映射对象
  14.           [color=blue]* @param actionForm --仍然支持表单提交,此时doc == null
  15.           * @param doc document对象,解析xml后的文档对象[/color]
  16.           * @param request --请求
  17.           * @param response --响应
  18.           */
  19.     public ActionForward list(ActionMapping mapping, ActionForm actionForm, [color=red]Document doc[/color],HttpServletRequest request, HttpServletResponse response) throws BaseAppException {
  20.         /**
  21.          * 转发的名称 userAction.search: 系统上下文 用于异常处理
  22.          */
  23.         expDisplayDetails.set(new ExceptionDisplayDTO(null"userAction.search"));
  24.         /**
  25.          * 处理业务逻辑部分:
  26.          * 
  27.          * 获取各种类型的参数 RequestUtil.getStrParameter(request,"ParameterName");
  28.          * 
  29.          * 调用父类的 getSpringBean("serviceID")方法获取spring的配置bean
  30.          * 
  31.          */
  32.         UserManager userManager = (LogManager) getSpringBean("userManager");
  33.         //返回xml对象到前台
  34.         renderXML(response, userManager.findUsersByDoc(doc));        
  35.                      return null;
  36.     }


至此,我们成功实现了ajax--struts--spring的无缝结合,下次介绍spring的开发应用。欢迎大家拍砖!


JBuilder 2007 企业版Trial提供下载
zhipingch 转贴   更新:2006-12-25 09:03:20  版本: 1.0   

   JBuilder 2007 企业版Trial提供下载 
   网路冷眼@BlogJava
   越接近年关,Java IDE世界真是好戏连连,先是Sun在11月发布NetBeans英文版,在12月发布多国语言版。后是BEA发布workshop studio 3.3。Borland那边不见其影,先闻其声。
   话说一月之前,李维先生分别在大陆的北京,上海,大连和深圳为JBuilder 2007举办产品发布会。尔后,又在台湾台北和高雄再造声势。我未参加这样的产品发布会。。
李维先生在JBuilder2007 打通任督二脉的崭新Java开发工具 的文章里说道:
“目前EJB 3和Java Persistence API(JPA)正如潮水般席卷Java开发社群,Hibernate 3.x和Oracle的TopLink都开始支持JPA,JBoss 4.x和GlassFish/AppSever 9也都支持EJB 3.0的开发,因此JBuilder 2007的成功运算式就是:完整建模能力 + 主流Java框架 + 强大EJB3/JPA开发能力 + 高生产力开发者功能。
   JBuilder 2007将充分而且完美地结合第一名的Java商业开发工具和Java开源框架/程序码成为第一个打通任督二脉的崭新Java开发工具”。
  现在,JBuilder 2007年终于掀开面纱,以示众人。终于在当地时间本月22日提供     JBuilder 2007 Enterpise Edition trial下载。
JBuilder 2007 企业版下载地址:ftp://ftpd.borland.com/download/jbuilder/JBuilder_2007/Enterprise/JBuilder2007_enttrial.zip主要特性,参见:http://www.codegear.com/Products/JBuilder/tabid/102/Default.aspx
   在JBuilder 9和JBuilder 2005,2006版本之后逐渐失去王位的Borland,能否以CodeGear 新面孔借助JBuilder 2007 在如日中天的Eclipse之上演出王者归来的当世神话。我们将拭目以待。


FCKeditor中使用JSP版本上传图片、flash以及文件
zhipingch 原创   更新:2006-12-15 00:30:58  版本: 1.0   

FCKeditor中使用JSP版本上传图片、flash以及文件



          简单就好

         由于网站的图片上传出点小问题,决定试用在线编辑的利器FCKeditor,查了些资料,大都讲述php\asp环境下的应用,所以决定自己测试一下,没想到2小时就搞定咯。当然相信看了文档的你,将更加轻松完成。本文仅仅描述如何修改配置,不涉及相关服务器配置等等。如有疑问请与我联系。

(一) 准备工作

1、下载FCKeditor2.1.1最新版本;

2、下载FCKeditor2.3,java版本;

3、Tomcat或者weblogic作为服务器(都测试过)

(二)新建web工程??FCKeditor

1、解压上述FCKeditor2.3 for java,并copy src和web两个文件夹到web工程??FCKeditor下,覆盖

src和web;并将_samples下的jsp 文件copy到web目录下

2、解压FCKeditor2.1.1 ,并copy到web工程的web文件夹中,将一些不需要的文件夹,比如_samples和_testcases以及editor\_source 删除,节约空间,另外如果仅仅使用JSP环境的话,也可以将其他环境下的配置信息或者测试用例删除。

3、在你的工程的web目录下创建UserFile目录,以及Image、Flash、File三个子目录。

您的工程目录如下所示:

 

(三)、修改相关配置

现在开始修改代码咯,从\FCKeditor\fckconfig.js以及\FCKeditor\fckeditor.js开始。

fckconfig.js

FCKConfig.LinkBrowser = true ;
FCKConfig.LinkBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Connector=connectors/jsp/connector' ;
FCKConfig.LinkBrowserWindowWidth = FCKConfig.ScreenWidth * 0.7 ; // 70%
FCKConfig.LinkBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ;// 70%

FCKConfig.ImageBrowser = true ;
FCKConfig.ImageBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Image&Connector=connectors/jsp/connector' ;
FCKConfig.ImageBrowserWindowWidth  = FCKConfig.ScreenWidth * 0.7 ; // 70% ;
FCKConfig.ImageBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; // 70% ;

FCKConfig.FlashBrowser = true ;
FCKConfig.FlashBrowserURL = FCKConfig.BasePath + 'filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/jsp/connector' ;
FCKConfig.FlashBrowserWindowWidth  = FCKConfig.ScreenWidth * 0.7 ; //70% ;
FCKConfig.FlashBrowserWindowHeight = FCKConfig.ScreenHeight * 0.7 ; //70% ;

FCKConfig.LinkUpload = true ;
FCKConfig.LinkUploadURL = FCKConfig.BasePath + '/editor/filemanager/upload/simpleuploader?Type=File';
FCKConfig.LinkUploadAllowedExtensions = "" ;   // empty for all
FCKConfig.LinkUploadDeniedExtensions = ".(php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi)$" ; // empty for no one

FCKConfig.ImageUpload = true ;
FCKConfig.ImageUploadURL = FCKConfig.BasePath + '/editor/filemanager/upload/simpleuploader?Type=Image';
FCKConfig.ImageUploadAllowedExtensions = ".(jpg|gif|jpeg|png)$" ;  // empty for all
FCKConfig.ImageUploadDeniedExtensions = "" ;       // empty for no one

FCKConfig.FlashUpload = true ;
FCKConfig.FlashUploadURL = FCKConfig.BasePath + '/editor/filemanager/upload/simpleuploader?Type=Flash';
FCKConfig.FlashUploadAllowedExtensions = ".(swf|fla)$" ;  // empty for all
FCKConfig.FlashUploadDeniedExtensions = "" ;     // empty for no one


主要是上述URL配置。另外修改fckeditor.js:

var FCKeditor = function( instanceName, width, height, toolbarSet, value )
{
 // Properties
 this.InstanceName = instanceName ;
 this.Width   = width   || '100%' ;
 this.Height   = height  || '400' ;
 this.ToolbarSet  = toolbarSet || 'Custom' ;//Custom是自定义的工具栏,根据需要自由更改
 this.Value   = value   || '   ' ;
 this.BasePath  = '/FCKeditor/editor/' ;//取自己工程的相对路径
 this.CheckBrowser = true ;
 this.DisplayErrors = true ;
 this.EnableSafari = false ;  // This is a temporary property, while Safari support is under development.

 this.Config   = new Object() ;

 // Events
 this.OnError  = null ; // function( source, errorNumber, errorDescription )错误处理函数
}

3、找到\FCKeditor\editor\dialog\fck_image\fck_image.js和\FCKeditor\editor\dialog\fck_flash\fck_flash.js中下述片断

if ( oEditor.FCKBrowserInfo.IsIE ){
    // The following change has been made otherwise IE will open the file 
    // browser on a different server session (on some cases):
    // http://support.microsoft.com/default.aspx?scid=kb;en-us;831678
    // by Simone Chiaretta.
    var oWindow = oEditor.window.open( url, "FCKBrowseWindow", sOptions ) ;
    oWindow.opener = window ;
}else{

         window.open( url, "FCKBrowseWindow", sOptions ) ;

}

修改为:

if ( oEditor.FCKBrowserInfo.IsIE ){
    // The following change has been made otherwise IE will open the file 
    // browser on a different server session (on some cases):
    // http://support.microsoft.com/default.aspx?scid=kb;en-us;831678
    // by Simone Chiaretta.

             window.open( url, "FCKBrowseWindow", sOptions ) ;
   }else{

          var oWindow = oEditor.window.open( url, "FCKBrowseWindow", sOptions ) ;
        oWindow.opener = window ;
}
  

这样在IE在浏览服务器的文件,才可以选择,否则逻辑相反的话,打开的服务器文件浏览页面在对话框下面,无法选择文件或图片等。

4、配置JSP所需的标签库

将FCKeditor.tld  copy到/WEB-INF/下,并修改web.xml文件,结果如下所示:
 <servlet>
        <servlet-name>Connector</servlet-name>
        <servlet-class>com.fredck.FCKeditor.connector.ConnectorServlet</servlet-class>
        <init-param>
            <param-name>baseDir</param-name>
            <param-value>/UserFiles/</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet>
        <servlet-name>SimpleUploader</servlet-name>
        <servlet-class>com.fredck.FCKeditor.uploader.SimpleUploaderServlet</servlet-class>
        <init-param>
            <param-name>baseDir</param-name>
            <param-value>/UserFiles/</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>false</param-value>
        </init-param>
        <init-param>
            <param-name>enabled</param-name>
            <param-value>true</param-value>
        </init-param>
        <init-param>
            <param-name>AllowedExtensionsFile</param-name>
            <param-value/>
        </init-param>
        <init-param>
            <param-name>DeniedExtensionsFile</param-name>
            <param-value>php|php3|php5|phtml|asp|aspx|ascx|jsp|cfm|cfc|pl|bat|exe|dll|reg|cgi|htm|html</param-value>
        </init-param>
        <init-param>
            <param-name>AllowedExtensionsImage</param-name>
            <param-value>jpg|gif|jpeg|png|bmp</param-value>
        </init-param>
        <init-param>
            <param-name>DeniedExtensionsImage</param-name>
            <param-value/>
        </init-param>
        <init-param>
            <param-name>AllowedExtensionsFlash</param-name>
            <param-value>swf|fla</param-value>
        </init-param>
        <init-param>
            <param-name>DeniedExtensionsFlash</param-name>
            <param-value/>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

此外可以根据需要修改\src\com\fredck\FCKeditor\tags\FCKeditorTag.java以及\src\com\fredck\FCKeditor\FCKeditor.java文件

自定义默认的配置信息。

public class FCKeditor {
 
 private FCKeditorConfigurations oConfig;
 private String instanceName;
 private String value = "  ";//这样标签体可以置空
 private String basePath;
 private String toolbarSet = "Custom";//默认为自定义
 private String width = "100%";
 private String height = "300";//默认为300px
 
 HttpServletRequest request;

……

 public FCKeditor(HttpServletRequest req, String parInstanceName){
  request=req;

/**

  *这里 /FCKeditor/ 必须和工程web目录下的FCKeditor目录同名,大小写敏感

 */ 
  basePath = request.getContextPath() + "/FCKeditor/";
  instanceName=parInstanceName;
  oConfig = new FCKeditorConfigurations() ;
 }

此时,可以在JSP中使用如下标签咯(参见sample2.jsp)
imageBrowserURL="/web/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Image&Connector=connectors/jsp/connector"
    linkBrowserURL="/web/FCKeditor/editor/filemanager/browser/default/browser.html?Connector=connectors/jsp/connector"
    flashBrowserURL="/web/FCKeditor/editor/filemanager/browser/default/browser.html?Type=Flash&Connector=connectors/jsp/connector"
    imageUploadURL="/web/FCKeditor/editor/filemanager/upload/simpleuploader?Type=Image"
    linkUploadURL="/web/FCKeditor/editor/filemanager/upload/simpleuploader?Type=File"
    flashUploadURL="/web/FCKeditor/editor/filemanager/upload/simpleuploader?Type=Flash">

并且可以上传图片、flash、文件等等。

将工程部署到tomcat或者weblogic下,可以直接指向工程路径,散布。关于如何配置tomcat、weblogic请

参考相关网站。

打开 http://localhost:8080/web/index.jsp(tomcat)  或者 http://localhost:7001/web/index.jsp(weblogic)后可以试用咯!

祝您成功,如果有描述不清楚的地方,请与我联系。

以上已经测试成功。

tomcat5.0下配置ssl
zhipingch 原创   更新:2006-12-06 11:55:10  版本: 1.0   

1、使用java1.4版本 
2、设置环境变量: 
PATH=/usr/j2sdk1.4.1/bin 
JAVA_HOME=/usr/j2sdk1.4.1/ 
CLASSPATH=/usr/j2sdk1.4.1/lib/tools.jar 
3、生成key文件 
keytool -genkey -alias tomcat-sv -dname "CN=Ritchie Lee, OU=Software department, O=Sutian, L=Nanjing, S=Jiangsu, C=CN" -keyalg RSA -keypass changeit -storepass changeit -keystore server.keystore 
4、修改server.xml文件,将ssl部分的注释去掉,注意clientAuth="false",否则必须要有客户端key,keystoreFile="key的实际路径",keystorePass="上面使用的密码" 
5、重起tomcat,使用https://IP:8443/,可以看到安全提示?..步骤3中的信息。 



posted on 2007-03-27 22:01 MEYE 阅读(7382) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: