﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-见酒就晕-文章分类-J2EE文章</title><link>http://www.blogjava.net/franlk/category/9114.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 11 Mar 2008 14:10:34 GMT</lastBuildDate><pubDate>Tue, 11 Mar 2008 14:10:34 GMT</pubDate><ttl>60</ttl><item><title>[摘录]Log4j配置</title><link>http://www.blogjava.net/franlk/articles/184288.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 06 Mar 2008 08:24:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/184288.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/184288.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/184288.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/184288.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/184288.html</trackback:ping><description><![CDATA[摘录地址：http://blog.csdn.net/djhyoo/archive/2007/06/09/1645525.aspx<br />
<br />
在强调可重用组件开发的今天，除了自己从头到尾开发一个可重用的日志操作类外，Apache为我们提供了一个强有力的日志操作包-Log4j。 <br />
<br />
Log4j是Apache的一个开放源代码项目，通过使用Log4j，我们可以控制日志信息输送的目的地是控制台、文件、GUI组件、甚至是套接口服务器、NT的事件记录器、UNIX Syslog守护进程等；我们也可以控制每一条日志的输出格式；通过定义每一条日志信息的级别，我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是，这些可以通过一个配置文件来灵活地进行配置，而不需要修改应用的代码。 <br />
<br />
此外，通过Log4j其他语言接口，您可以在C、C++、.Net、PL/SQL程序中使用Log4j，其语法和用法与在Java程序中一样，使得多语言分布式系统得到一个统一一致的日志组件模块。而且，通过使用各种第三方扩展，您可以很方便地将Log4j集成到J2EE、JINI甚至是SNMP应用中。<br />
<br />
说明：下面分为三部分，第一部分讲解如何配置log4j，第二部分为对log4j.properties配置文件中的各个属性的讲解，第三部分为对log4j的详细讲解，如果只想配置上log4j，那么只需要看前两个部分就可以，如果想对log4j深入了解，则还需看第三部分。<br />
<br />
一、Log4j配置<br />
<br />
第一步：加入log4j-1.2.8.jar到lib下。<br />
<br />
第二步：在CLASSPATH下建立log4j.properties。内容如下：<br />
<br />
1 log4j.rootCategory=INFO, stdout , R<br />
<br />
2 <br />
<br />
3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />
<br />
4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br />
<br />
5 log4j.appender.stdout.layout.ConversionPattern=[QC] %p [%t] %C.%M(%L) | %m%n<br />
<br />
6 <br />
<br />
7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender<br />
<br />
8 log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log<br />
<br />
9 log4j.appender.R.layout=org.apache.log4j.PatternLayout<br />
<br />
10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n<br />
<br />
11 <br />
<br />
12 log4j.logger.com.neusoft=DEBUG<br />
<br />
13 log4j.logger.com.opensymphony.oscache=ERROR<br />
<br />
14 log4j.logger.net.sf.navigator=ERROR<br />
<br />
15 log4j.logger.org.apache.commons=ERROR<br />
<br />
16 log4j.logger.org.apache.struts=WARN<br />
<br />
17 log4j.logger.org.displaytag=ERROR<br />
<br />
18 log4j.logger.org.springframework=DEBUG<br />
<br />
19 log4j.logger.com.ibatis.db=WARN<br />
<br />
20 log4j.logger.org.apache.velocity=FATAL<br />
<br />
21 <br />
<br />
22 log4j.logger.com.canoo.webtest=WARN<br />
<br />
23 <br />
<br />
24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN<br />
<br />
25 log4j.logger.org.hibernate=DEBUG<br />
<br />
26 log4j.logger.org.logicalcobwebs=WARN<br />
<br />
第三步：相应的修改其中属性，修改之前就必须知道这些都是干什么的，在第二部分讲解。<br />
<br />
第四步：在要输出日志的类中加入相关语句：<br />
<br />
定义属性：protected final Log log = LogFactory.getLog(getClass());<br />
<br />
在相应的方法中：<br />
<br />
if (log.isDebugEnabled())<br />
<br />
{<br />
<br />
log.debug(&#8220;System &#8230;..&#8221;);<br />
<br />
}<br />
<br />
二、Log4j说明<br />
<br />
1 log4j.rootCategory=INFO, stdout , R<br />
<br />
此句为将等级为INFO的日志信息输出到stdout和R这两个目的地，stdout和R的定义在下面的代码，可以任意起名。等级可分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL，如果配置OFF则不打出任何信息，如果配置为INFO这样只显示INFO, WARN, ERROR的log信息，而DEBUG信息不会被显示，具体讲解可参照第三部分定义配置文件中的logger。<br />
<br />
3 log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />
<br />
此句为定义名为stdout的输出端是哪种类型，可以是<br />
<br />
org.apache.log4j.ConsoleAppender（控制台）， <br />
<br />
org.apache.log4j.FileAppender（文件）， <br />
<br />
org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br />
<br />
org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）<br />
<br />
org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br />
<br />
具体讲解可参照第三部分定义配置文件中的Appender。<br />
<br />
4 log4j.appender.stdout.layout=org.apache.log4j.PatternLayout<br />
<br />
此句为定义名为stdout的输出端的layout是哪种类型，可以是<br />
<br />
org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br />
<br />
org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br />
<br />
org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br />
<br />
org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br />
<br />
具体讲解可参照第三部分定义配置文件中的Layout。<br />
<br />
5 log4j.appender.stdout.layout.ConversionPattern= [QC] %p [%t] %C.%M(%L) | %m%n<br />
<br />
如果使用pattern布局就要指定的打印信息的具体格式ConversionPattern，打印参数如下：<br />
<br />
%m 输出代码中指定的消息<br />
<br />
%p 输出优先级，即DEBUG，INFO，WARN，ERRO*，**TAL <br />
<br />
%r 输出自应用启动到输出该log信息耗费的毫秒数 <br />
<br />
%c 输出所属的类目，通常就是所在类的全名 <br />
<br />
%t 输出产生该日志事件的线程名 <br />
<br />
%n 输出一个回车换行符，Windows平台为&#8220;rn&#8221;，Unix平台为&#8220;n&#8221; <br />
<br />
%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 <br />
<br />
%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。<br />
<br />
%C: Outputs the fully-qualified class name of the caller issuing the logging request. Example: For the class name "org.apache.xyz.SomeClass", the pattern %C{1} will output "SomeClass". {1} means "output last one component of the fully-qualified class name". If no {n} is there, full class name is output by default. <br />
%M: Outputs the method name where the logging request was issued. <br />
%F: Outputs the file name where the logging request was issued. <br />
%L: Outputs the line number from where the logging request was issued. <br />
<br />
[QC]是log信息的开头，可以为任意字符，一般为项目简称。<br />
<br />
输出的信息<br />
<br />
[TS] DEBUG [main] AbstractBeanFactory.getBean(189) | Returning cached instance of singleton bean 'MyAutoProxy'<br />
<br />
具体讲解可参照第三部分定义配置文件中的格式化日志信息。<br />
<br />
7 log4j.appender.R=org.apache.log4j.DailyRollingFileAppender<br />
<br />
此句与第3行一样。定义名为R的输出端的类型为每天产生一个日志文件。<br />
<br />
8 log4j.appender.R.File=D:\Tomcat 5.5\logs\qc.log<br />
<br />
此句为定义名为R的输出端的文件名为D:\Tomcat 5.5\logs\qc.log<br />
<br />
可以自行修改。<br />
<br />
9 log4j.appender.R.layout=org.apache.log4j.PatternLayout<br />
<br />
与第4行相同。<br />
<br />
10 log4j.appender.R.layout.ConversionPattern=%d-[TS] %p %t %c - %m%n<br />
<br />
与第5行相同。<br />
<br />
12 log4j.logger.com. neusoft =DEBUG<br />
<br />
指定com.neusoft包下的所有类的等级为DEBUG。<br />
<br />
可以把com.neusoft改为自己项目所用的包名。<br />
<br />
13 log4j.logger.com.opensymphony.oscache=ERROR<br />
<br />
14 log4j.logger.net.sf.navigator=ERROR<br />
<br />
这两句是把这两个包下出现的错误的等级设为ERROR，如果项目中没有配置EHCache，则不需要这两句。<br />
<br />
15 log4j.logger.org.apache.commons=ERROR<br />
<br />
16 log4j.logger.org.apache.struts=WARN<br />
<br />
这两句是struts的包。<br />
<br />
17 log4j.logger.org.displaytag=ERROR<br />
<br />
这句是displaytag的包。（QC问题列表页面所用）<br />
<br />
18 log4j.logger.org.springframework=DEBUG<br />
<br />
此句为Spring的包。<br />
<br />
24 log4j.logger.org.hibernate.ps.PreparedStatementCache=WARN<br />
<br />
25 log4j.logger.org.hibernate=DEBUG<br />
<br />
此两句是hibernate的包。<br />
<br />
以上这些包的设置可根据项目的实际情况而自行定制。<br />
<br />
三、log4j详解<br />
<br />
1、定义配置文件<br />
<br />
Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件log4j.properties（键=值）。下面将介绍使用log4j.properties文件作为配置文件的方法:<br />
<br />
①、配置根Logger<br />
<br />
Logger 负责处理日志记录的大部分操作。 <br />
<br />
其语法为：<br />
<br />
log4j.rootLogger = [ level ] , appenderName, appenderName, &#8230;<br />
<br />
其中，level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者自定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，只有等于及高于这个级别的才进行处理，则应用程序中所有DEBUG级别的日志信息将不被打印出来。ALL:打印所有的日志，OFF：关闭所有的日志输出。 appenderName就是指定日志信息输出到哪个地方。可同时指定多个输出目的地。<br />
<br />
②、配置日志信息输出目的地 Appender<br />
<br />
Appender 负责控制日志记录操作的输出。 <br />
<br />
其语法为：<br />
<br />
log4j.appender.appenderName = fully.qualified.name.of.appender.class <br />
<br />
log4j.appender.appenderName.option1 = value1 <br />
<br />
&#8230; <br />
<br />
log4j.appender.appenderName.optionN = valueN <br />
<br />
这里的appenderName为在①里定义的，可任意起名。<br />
<br />
其中，Log4j提供的appender有以下几种： <br />
<br />
org.apache.log4j.ConsoleAppender（控制台）， <br />
<br />
org.apache.log4j.FileAppender（文件）， <br />
<br />
org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br />
<br />
org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件），可通过log4j.appender.R.MaxFileSize=100KB设置文件大小，还可通过log4j.appender.R.MaxBackupIndex=1设置为保存一个备份文件。 <br />
<br />
org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方）<br />
<br />
例如：log4j.appender.stdout=org.apache.log4j.ConsoleAppender<br />
<br />
定义一个名为stdout的输出目的地，ConsoleAppender为控制台。<br />
<br />
③、配置日志信息的格式（布局）Layout<br />
<br />
Layout 负责格式化Appender的输出。<br />
<br />
其语法为：<br />
<br />
log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class <br />
<br />
log4j.appender.appenderName.layout.option1 = value1 <br />
<br />
&#8230; <br />
<br />
log4j.appender.appenderName.layout.optionN = valueN <br />
<br />
其中，Log4j提供的layout有以下几种： <br />
<br />
org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br />
<br />
org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br />
<br />
org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br />
<br />
org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息）<br />
<br />
2、格式化日志信息<br />
<br />
Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下： <br />
<br />
%m 输出代码中指定的消息<br />
<br />
%p 输出优先级，即DEBUG，INFO，WARN，ERRO*，**TAL <br />
<br />
%r 输出自应用启动到输出该log信息耗费的毫秒数 <br />
<br />
%c 输出所属的类目，通常就是所在类的全名 <br />
<br />
%t 输出产生该日志事件的线程名 <br />
<br />
%n 输出一个回车换行符，Windows平台为&#8220;rn&#8221;，Unix平台为&#8220;n&#8221; <br />
<br />
%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 <br />
<br />
%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。<br />
<br />
3、在代码中使用Log4j<br />
<br />
我们在需要输出日志信息的类中做如下的三个工作：<br />
<br />
1、导入所有需的commongs-logging类：<br />
<br />
import org.apache.commons.logging.Log;<br />
<br />
import org.apache.commons.logging.LogFactory;<br />
<br />
2、在自己的类中定义一个org.apache.commons.logging.Log类的私有静态类成员：<br />
<br />
private final Log log = LogFactory.getLog(getClass());<br />
<br />
LogFactory.getLog()方法的参数使用的是当前类的class。
<img src ="http://www.blogjava.net/franlk/aggbug/184288.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2008-03-06 16:24 <a href="http://www.blogjava.net/franlk/articles/184288.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]各种排序算法java实现</title><link>http://www.blogjava.net/franlk/articles/184164.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 06 Mar 2008 02:24:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/184164.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/184164.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/184164.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/184164.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/184164.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://wendy.reallydo.com/article.asp?id=63">http://wendy.reallydo.com/article.asp?id=63</a><br />
<br />
<span style="color: #042792">插入排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class InsertSort implements SortUtil.Sort{<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=1;i&lt;data.length;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int j=i;(j&gt;0)&amp;&amp;(data[j]&lt;data[j-1]);j--){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,j,j-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
冒泡排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class BubbleSort implements SortUtil.Sort{<br />
/* (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=0;i&lt;data.length;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int j=data.length-1;j&gt;i;j--){<br />
if(data[j]&lt;data[j-1]){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,j,j-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
选择排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class SelectionSort implements SortUtil.Sort {<br />
&nbsp;&nbsp;&nbsp;&nbsp;/*<br />
&nbsp;&nbsp;&nbsp;&nbsp; * (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int i = 0; i &lt; data.length; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int lowIndex = i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (int j = data.length - 1; j &gt; i; j--) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (data[j] &lt; data[lowIndex]) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lowIndex = j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,i,lowIndex);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
Shell排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class ShellSort implements SortUtil.Sort{<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=data.length/2;i&gt;2;i/=2){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int j=0;j&lt;i;j++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertSort(data,j,i);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertSort(data,0,1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;private void insertSort(int[] data, int start, int inc) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=start+inc;i&lt;data.length;i+=inc){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int j=i;(j&gt;=inc)&amp;&amp;(data[j]&lt;data[j-inc]);j-=inc){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,j,j-inc);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
快速排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class QuickSort implements SortUtil.Sort{<br />
/* (non-Javadoc)<br />
* @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;quickSort(data,0,data.length-1);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;private void quickSort(int[] data,int i,int j){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int pivotIndex=(i+j)/2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//swap<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,pivotIndex,j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int k=partition(data,i-1,j,data[j]);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,k,j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((k-i)&gt;1) quickSort(data,i,k-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((j-k)&gt;1) quickSort(data,k+1,j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param data<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param i<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param j<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @return<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;private int partition(int[] data, int l, int r,int pivot) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(data[++l]&lt;pivot);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while((r!=0)&amp;&amp;data[--r]&gt;pivot);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SortUtil.swap(data,l,r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(l&lt;r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,l,r);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return l;<br />
}<br />
}<br />
改进后的快速排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class ImprovedQuickSort implements SortUtil.Sort {<br />
private static int MAX_STACK_SIZE=4096;<br />
&nbsp;&nbsp;&nbsp;&nbsp;private static int THRESHOLD=10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int[] stack=new int[MAX_STACK_SIZE];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int top=-1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int pivot;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int pivotIndex,l,r;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[++top]=0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[++top]=data.length-1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(top&gt;0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int j=stack[top--];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i=stack[top--];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pivotIndex=(i+j)/2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pivot=data[pivotIndex];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,pivotIndex,j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//partition<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;l=i-1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;r=j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;do{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(data[++l]&lt;pivot);<br />
while((r!=0)&amp;&amp;(data[--r]&gt;pivot));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,l,r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(l&lt;r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,l,r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,l,j);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((l-i)&gt;THRESHOLD){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[++top]=i;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[++top]=l-1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if((j-l)&gt;THRESHOLD){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[++top]=l+1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;stack[++top]=j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//new InsertSort().sort(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertSort(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param data<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;private void insertSort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=1;i&lt;data.length;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int j=i;(j&gt;0)&amp;&amp;(data[j]&lt;data[j-1]);j--){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(data,j,j-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
归并排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class MergeSort implements SortUtil.Sort{<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int[] temp=new int[data.length];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mergeSort(data,temp,0,data.length-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void mergeSort(int[] data,int[] temp,int l,int r){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int mid=(l+r)/2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(l==r) return ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mergeSort(data,temp,l,mid);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mergeSort(data,temp,mid+1,r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=l;i&lt;=r;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[i]=data[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i1=l;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i2=mid+1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int cur=l;cur&lt;=r;cur++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(i1==mid+1)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[cur]=temp[i2++];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if(i2&gt;r)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[cur]=temp[i1++];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else if(temp[i1]&lt;temp[i2])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[cur]=temp[i1++];<br />
else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[cur]=temp[i2++];&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
改进后的归并排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class ImprovedMergeSort implements SortUtil.Sort {<br />
&nbsp;&nbsp;&nbsp;&nbsp;private static final int THRESHOLD = 10;<br />
&nbsp;&nbsp;&nbsp;&nbsp;/*<br />
&nbsp;&nbsp;&nbsp;&nbsp; * (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int[] temp=new int[data.length];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mergeSort(data,temp,0,data.length-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;private void mergeSort(int[] data, int[] temp, int l, int r) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int i, j, k;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int mid = (l + r) / 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (l == r)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((mid - l) &gt;= THRESHOLD)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mergeSort(data, temp, l, mid);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertSort(data, l, mid - l + 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if ((r - mid) &gt; THRESHOLD)<br />
mergeSort(data, temp, mid + 1, r);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertSort(data, mid + 1, r - mid);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (i = l; i &lt;= mid; i++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[i] = data[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (j = 1; j &lt;= r - mid; j++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp[r - j + 1] = data[j + mid];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int a = temp[l];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int b = temp[r];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for (i = l, j = r, k = l; k &lt;= r; k++) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (a &lt; b) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[k] = temp[i++];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a = temp[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[k] = temp[j--];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b = temp[j];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;/**<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param data<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param l<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @param i<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;private void insertSort(int[] data, int start, int len) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=start+1;i&lt;start+len;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int j=i;(j&gt;start) &amp;&amp; data[j]&lt;data[j-1];j--){<br />
SortUtil.swap(data,j,j-1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
堆排序:<br />
package org.rut.util.algorithm.support;<br />
import org.rut.util.algorithm.SortUtil;<br />
public class HeapSort implements SortUtil.Sort{<br />
&nbsp;&nbsp;&nbsp;&nbsp;/* (non-Javadoc)<br />
&nbsp;&nbsp;&nbsp;&nbsp; * @see org.rut.util.algorithm.SortUtil.Sort#sort(int[])<br />
&nbsp;&nbsp;&nbsp;&nbsp; */<br />
&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MaxHeap h=new MaxHeap();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h.init(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=0;i&lt;data.length;i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;h.remove();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.arraycopy(h.queue,1,data,0,data.length);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp; private static class MaxHeap{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;void init(int[] data){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this.queue=new int[data.length+1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for(int i=0;i&lt;data.length;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;queue[++size]=data[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixUp(size);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private int size=0;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private int[] queue;<br />
public int get() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return queue[1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void remove() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(queue,1,size--);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fixDown(1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//fixdown<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private void fixDown(int k) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while ((j = k &lt;&lt; 1) &lt;= size) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (j &lt; size &amp;&amp; queue[j]&lt;queue[j+1])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j++; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (queue[k]&gt;queue[j]) //不用交换<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(queue,j,k);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k = j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private void fixUp(int k) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while (k &gt; 1) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int j = k &gt;&gt; 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (queue[j]&gt;queue[k])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SortUtil.swap(queue,j,k);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k = j;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}<br />
SortUtil:<br />
package org.rut.util.algorithm;<br />
import org.rut.util.algorithm.support.BubbleSort;<br />
import org.rut.util.algorithm.support.HeapSort;<br />
import org.rut.util.algorithm.support.ImprovedMergeSort;<br />
import org.rut.util.algorithm.support.ImprovedQuickSort;<br />
import org.rut.util.algorithm.support.InsertSort;<br />
import org.rut.util.algorithm.support.MergeSort;<br />
import org.rut.util.algorithm.support.QuickSort;<br />
import org.rut.util.algorithm.support.SelectionSort;<br />
import org.rut.util.algorithm.support.ShellSort;<br />
public class SortUtil {<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int Insert = 1;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int BUBBLE = 2;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int SelectION = 3;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int SHELL = 4;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int QUICK = 5;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int IMPROVED_QUICK = 6;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int MERGE = 7;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int IMPROVED_MERGE = 8;<br />
&nbsp;&nbsp;&nbsp;&nbsp;public final static int HEAP = 9;<br />
public static void sort(int[] data) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sort(data, IMPROVED_QUICK);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;private static String[] name={<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"insert","bubble","selection","shell","quick","improved_quick","merge","improved_merge","heap"<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
private static Sort[] impl=new Sort[]{<br />
new InsertSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new BubbleSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new SelectionSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new ShellSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new QuickSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new ImprovedQuickSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new MergeSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new ImprovedMergeSort(),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;new HeapSort()<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static String toString(int algorithm){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return name[algorithm-1];<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static void sort(int[] data, int algorithm) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;impl[algorithm-1].sort(data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static interface Sort {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public void sort(int[] data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;public static void swap(int[] data, int i, int j) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int temp = data[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[i] = data[j];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;data[j] = temp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
} <br />
</span>
<img src ="http://www.blogjava.net/franlk/aggbug/184164.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2008-03-06 10:24 <a href="http://www.blogjava.net/franlk/articles/184164.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]java抽取word,pdf的四种武器</title><link>http://www.blogjava.net/franlk/articles/184160.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 06 Mar 2008 02:18:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/184160.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/184160.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/184160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/184160.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/184160.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://wendy.reallydo.com/article.asp?id=64">http://wendy.reallydo.com/article.asp?id=64</a><br />
<br />
1。用jacob.<br />
其实jacob是一个bridage，连接java和com或者win32函数的一个中间件，jacob并不能直接抽取word,excel等文件，需要自己写dll哦，不过已经有为你写好的了，就是jacob的作者一并提供了。<br />
jacob下载：<a href="http://www.matrix.org.cn/down_view.asp?id=13" target="_blank">http://www.matrix.org.cn/down_view.asp?id=13</a><br />
下载了jacob并放到指定的路径之后(dll放到path,jar文件放到classpath)，就可以写你自己的抽取程序了，下面是一个例子：<br />
import java.io.File;<br />
import com.jacob.com.*;<br />
import com.jacob.activeX.*;<br />
public class FileExtracter{<br />
public static void main(String[] args) {<br />
&nbsp;&nbsp;ActiveXComponent app = new ActiveXComponent("Word.Application");<br />
&nbsp;&nbsp;String inFile = "c:\test.doc";<br />
String tpFile = "c:\temp.htm";<br />
&nbsp;&nbsp;String otFile = "c:\temp.xml";<br />
&nbsp;&nbsp;boolean flag = false;<br />
&nbsp;&nbsp;try {<br />
&nbsp;&nbsp; app.setProperty("Visible", new Variant(false));<br />
&nbsp;&nbsp; Object docs = app.getProperty("document．").toDispatch();<br />
&nbsp;&nbsp; Object doc = Dispatch.invoke(docs,"Open", Dispatch.Method, new Object[]{inFile,new Variant(false), new Variant(true)}, new int[1]).toDispatch();<br />
&nbsp;&nbsp; Dispatch.invoke(doc,"SaveAs", Dispatch.Method, new Object[]{tpFile,new Variant(8)}, new int[1]);<br />
&nbsp;&nbsp; Variant f = new Variant(false);<br />
&nbsp;&nbsp; Dispatch.call(doc, "Close", f);<br />
&nbsp;&nbsp; flag = true;<br />
&nbsp;&nbsp;} catch (Exception e) {<br />
&nbsp;&nbsp; e.printStackTrace();<br />
&nbsp;&nbsp;} finally {<br />
&nbsp;&nbsp; app.invoke("Quit", new Variant[] {});<br />
&nbsp;&nbsp;}<br />
}<br />
}<br />
2。用apache的poi来抽取word，excel。<br />
poi是apache的一个项目，不过就算用poi你可能都觉得很烦，不过不要紧，这里提供了更加简单的一个接口给你：下载经过封装后的poi包：<a href="http://www.matrix.org.cn/down_view.asp?id=14" target="_blank">http://www.matrix.org.cn/down_view.asp?id=14</a><br />
下载之后，放到你的classpath就可以了，下面是如何使用它的一个例子：<br />
import java.io.*;<br />
import&nbsp;&nbsp;org.textmining.text.extraction.WordExtractor;<br />
public class PdfExtractor {<br />
&nbsp;&nbsp;public PdfExtractor() {<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public static void main(String args[]) throws Exception<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;FileInputStream in = new FileInputStream ("c:\a.doc");<br />
&nbsp;&nbsp;WordExtractor extractor = new WordExtractor();<br />
&nbsp;&nbsp;String str = extractor.extractText(in);<br />
&nbsp;&nbsp;System.out.println("the result length is"+str.length());<br />
&nbsp;&nbsp; System.out.println("the result is"+str);<br />
}<br />
}<br />
3。pdfbox-用来抽取pdf文件<br />
但是pdfbox对中文支持还不好，先下载pdfbox：<a href="http://www.matrix.org.cn/down_view.asp?id=12" target="_blank">http://www.matrix.org.cn/down_view.asp?id=12</a><br />
下面是一个如何使用pdfbox抽取pdf文件的例子：<br />
import org.pdfbox.pdmodel.PDdocument．<br />
import org.pdfbox.pdfparser.PDFParser;<br />
import java.io.*;<br />
import org.pdfbox.util.PDFTextStripper;<br />
import java.util.Date;<br />
public class PdfExtracter{<br />
public PdfExtracter(){<br />
&nbsp;&nbsp;}<br />
public String GetTextFromPdf(String filename) throws Exception<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;String temp=null;<br />
&nbsp;&nbsp;PDdocument．nbsp;pdfdocument．null;<br />
&nbsp;&nbsp;FileInputStream is=new FileInputStream(filename);<br />
&nbsp;&nbsp;PDFParser parser = new PDFParser( is );<br />
&nbsp;&nbsp;parser.parse();<br />
&nbsp;&nbsp;pdfdocument．nbsp;= parser.getPDdocument．);<br />
&nbsp;&nbsp;ByteArrayOutputStream out = new ByteArrayOutputStream();<br />
&nbsp;&nbsp;OutputStreamWriter writer = new OutputStreamWriter( out );<br />
&nbsp;&nbsp;PDFTextStripper stripper = new PDFTextStripper();<br />
&nbsp;&nbsp;stripper.writeText(pdfdocument．getdocument．), writer );<br />
&nbsp;&nbsp;writer.close();<br />
&nbsp;&nbsp;byte[] contents = out.toByteArray();<br />
&nbsp;&nbsp;String ts=new String(contents);<br />
&nbsp;&nbsp;System.out.println("the string length is"+contents.length+" ");<br />
&nbsp;&nbsp;return ts;<br />
}<br />
public static void main(String args[])<br />
{<br />
PdfExtracter pf=new PdfExtracter();<br />
PDdocument．nbsp;pdfdocument．nbsp;= null;<br />
try{<br />
String ts=pf.GetTextFromPdf("c:\a.pdf");<br />
System.out.println(ts);<br />
}<br />
catch(Exception e)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;}<br />
}<br />
}<br />
4.抽取支持中文的pdf文件－xpdf<br />
xpdf是一个开源项目，我们可以调用他的本地方法来实现抽取中文pdf文件。<br />
下载xpdf函数包：<a href="http://www.matrix.org.cn/down_view.asp?id=15" target="_blank">http://www.matrix.org.cn/down_view.asp?id=15</a><br />
同时需要下载支持中文的补丁包：<a href="http://www.matrix.org.cn/down_view.asp?id=16" target="_blank">http://www.matrix.org.cn/down_view.asp?id=16</a><br />
按照readme放好中文的patch，就可以开始写调用本地方法的java程序了<br />
下面是一个如何调用的例子：<br />
import java.io.*;<br />
public class PdfWin {<br />
&nbsp;&nbsp;public PdfWin() {<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;public static void main(String args[]) throws Exception<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;String PATH_TO_XPDF="C:\Program Files\xpdf\pdftotext.exe";<br />
&nbsp;&nbsp;&nbsp;&nbsp;String filename="c:\a.pdf";<br />
&nbsp;&nbsp;&nbsp;&nbsp;String[] cmd = new String[] { PATH_TO_XPDF, "-enc", "UTF-8", "-q", filename, "-"};<br />
&nbsp;&nbsp;&nbsp;&nbsp;Process p = Runtime.getRuntime().exec(cmd);<br />
&nbsp;&nbsp;&nbsp;&nbsp;BufferedInputStream bis = new BufferedInputStream(p.getInputStream());<br />
&nbsp;&nbsp;&nbsp;&nbsp;InputStreamReader reader = new InputStreamReader(bis, "UTF-8");<br />
&nbsp;&nbsp;&nbsp;&nbsp;StringWriter out = new StringWriter();<br />
&nbsp;&nbsp;&nbsp;&nbsp;char [] buf = new char[10000];<br />
&nbsp;&nbsp;&nbsp;&nbsp;int len;<br />
&nbsp;&nbsp;&nbsp;&nbsp;while((len = reader.read(buf))&gt;= 0) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;//out.write(buf, 0, len);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("the length is"+len);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;reader.close();<br />
&nbsp;&nbsp;&nbsp;&nbsp;String ts=new String(buf);<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("the str is"+ts);<br />
&nbsp;&nbsp;}<br />
} <br />
<br />
<img src ="http://www.blogjava.net/franlk/aggbug/184160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2008-03-06 10:18 <a href="http://www.blogjava.net/franlk/articles/184160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]struts 批量上传文件</title><link>http://www.blogjava.net/franlk/articles/167536.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 13 Dec 2007 08:35:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/167536.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/167536.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/167536.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/167536.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/167536.html</trackback:ping><description><![CDATA[<br />
摘录地址：<a href="http://blog.linuxmine.com/13259/viewspace-2576">http://blog.linuxmine.com/13259/viewspace-2576<br />
</a><br />
1.html的form要设定：<br />
enctype="multipart/form-data"<br />
<br />
<br />
2.<br />
&lt;form-bean name="lazyForm" type="org.apache.struts.validator.LazyValidatorForm"&gt; <br />
&lt;form-property name="file" type="org.apache.struts.upload.FormFile[]"/&gt; <br />
&lt;/form-bean&gt;<br />
<br />
<br />
3.<br />
String dirPath = getServlet().getServletContext().getRealPath("/") <br />
+ "/upload"; <br />
Hashtable fileh = actionForm.getMultipartRequestHandler(). <br />
getFileElements(); <br />
for (Enumeration e = fileh.keys(); e.hasMoreElements(); ) { <br />
String key = (String) e.nextElement(); <br />
try { <br />
FormFile formfile = (FormFile) fileh.get(key); <br />
String filename = formfile.getFileName().trim(); //文件名 <br />
if (!"".equals(filename)) { <br />
//不同的浏览器传上的文件名可能有区别，有的是全路径的 <br />
//在这里保存文件 <br />
InputStream ins = formfile.getInputStream(); <br />
OutputStream ōs = new FileOutputStream(dirPath + <br />
File.separatorChar <br />
+ filename); <br />
int bytesRead = 0; <br />
byte[] buffer = new byte[8192]; <br />
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { <br />
os.write(buffer, 0, bytesRead); <br />
} <br />
os.close(); <br />
ins.close(); <br />
<br />
} <br />
} catch (Exception ex) { <br />
logger.debug("出错了", ex); <br />
} <br />
}<br />
 <img src ="http://www.blogjava.net/franlk/aggbug/167536.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-12-13 16:35 <a href="http://www.blogjava.net/franlk/articles/167536.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>struts 批量提交</title><link>http://www.blogjava.net/franlk/articles/167509.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 13 Dec 2007 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/167509.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/167509.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/167509.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/167509.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/167509.html</trackback:ping><description><![CDATA[<p>&nbsp;</p>
<p>public class ShowValueForm extends ActionForm {<br />
&nbsp;/** 上次示数(SCSS)，对应的对象属性 */<br />
&nbsp;private double bcss = 0.0D;<br />
&nbsp;//定义一个放n个ShowValueForm的ArrayList<br />
&nbsp;private ArrayList formlst = new ArrayList();<br />
&nbsp;/**<br />
&nbsp; * 上次示数(SCSS)，对应的对象属性<br />
&nbsp; * @param scss<br />
&nbsp; */<br />
&nbsp;public void setBcss(double bcss) {<br />
&nbsp;&nbsp;this.bcss = bcss;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 上次示数(SCSS)，对应的对象属性<br />
&nbsp; * @return <br />
&nbsp; */<br />
&nbsp;public double getBcss() {<br />
&nbsp;&nbsp;return this.sbss;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 返回页面封装的FORM集合。 <br />
&nbsp; */<br />
&nbsp;public ArrayList <span style="color: red">getFormlst() </span>{<br />
&nbsp;&nbsp;return this.formlst;<br />
&nbsp;}<br />
&nbsp;/**<br />
&nbsp; * 在页面中得到多个form<br />
&nbsp; * @param i：对应页面中的相应的form<br />
&nbsp; * @return<br />
&nbsp; */<br />
<span style="color: #ff0000">&nbsp;public ShowValueForm getComp(int i) {<br />
&nbsp;&nbsp;if (formlst == null)<br />
&nbsp;&nbsp;&nbsp;formlst = new ArrayList();<br />
&nbsp;&nbsp;&nbsp;if (formlst.size() &lt;= i) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;for (int j = formlst.size(); j &lt;= i; j++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;formlst.add(new ShowValueForm());<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return (ShowValueForm) formlst.get(i);<br />
&nbsp;&nbsp;}</span><br />
}<br />
</p>
<p>public class ShowValueAction extends DispatchAction{<br />
&nbsp;public ShowValueAction() {<br />
&nbsp;&nbsp;super();<br />
&nbsp;&nbsp;<br />
&nbsp;}</p>
<p>&nbsp;/**更新要修改的记录，将返回的结果显示到页面。<br />
&nbsp; * @param mapping<br />
&nbsp; * @param form<br />
&nbsp; * @param request<br />
&nbsp; * @param response<br />
&nbsp; * @return<br />
&nbsp; */<br />
&nbsp;public ActionForward saveForms(ActionMapping mapping, ActionForm form,<br />
&nbsp;&nbsp;HttpServletRequest request, HttpServletResponse response)<br />
&nbsp;{<br />
&nbsp;&nbsp;ActionForward forward = new ActionForward();&nbsp;&nbsp;<br />
&nbsp;&nbsp;ShowValueForm frm = (ShowValueForm) form;<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;List valuelst = new ArrayList();<br />
&nbsp;&nbsp;String load = request.getParameter("load");<br />
<br />
&nbsp;&nbsp;ArrayList updatelst = <span style="color: red">frm.getFormlst();</span><br />
&nbsp;&nbsp;//更新并得到更新后的结果<br />
&nbsp;&nbsp;............<br />
&nbsp;&nbsp;return&nbsp; mapping.findForward("savelist");<br />
&nbsp;}</p>
<p><br />
=========================================================================<br />
页面<br />
&lt;html:form action="/showValueInputAction" method="post"&gt;<br />
&lt;input type="hidden" name="method" id="method" value="saveForms"&gt;<br />
&lt;TABLE&nbsp; cellpadding="0" cellspacing="1"&gt;<br />
&lt;TR &gt;<br />
&lt;TH&nbsp; width="80" nowrap&gt;本次示数&lt;/TH&gt;<br />
&lt;/TR&gt;<br />
&lt;logic:iterate id="item" name="valuelst" scope="request" type="java.util.HashMap" indexId="index"&gt;<br />
&lt;TR id="&lt;%=index%&gt;" class="&lt;%=index.intValue() % 2 == 0 ? "dataTable_rowNormal" : "dataTable_rowShadow"%&gt;"&gt;<br />
&lt;TD nowrap&gt;&lt;input type="text" size="10" <span style="color: #ff0000">name="comp[&lt;%=index%&gt;].bcss"</span> value="&lt;bean:write name="item" property="BCSS" /&gt;"&gt;&lt;/TD&gt;<br />
&lt;/TR&gt;<br />
&lt;/logic:iterate&gt;<br />
&lt;/TABLE&gt;</p>
<img src ="http://www.blogjava.net/franlk/aggbug/167509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-12-13 15:33 <a href="http://www.blogjava.net/franlk/articles/167509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]Forward与Redirect区别 </title><link>http://www.blogjava.net/franlk/articles/166601.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Mon, 10 Dec 2007 03:05:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/166601.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/166601.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/166601.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/166601.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/166601.html</trackback:ping><description><![CDATA[摘录地址：http://blog.csdn.net/gauss2008/archive/2006/06/18/809765.aspx<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <strong>Forward</strong><strong>与Redirect</strong>
<div><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>在做前台开发过程中你可能经常遇到关于转发页面得操作，很显然的就想到了forward和redirect，但是到底用哪一个呢，他们之间有什么区别呢，现在我将我自己的理解以及开发的时候怎么应用写出来供大家参考一下：</div>
<div style="margin: 0cm 0cm 0pt 57pt; text-indent: -36pt"><span>（1）<span style="font: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>共同点：</div>
<div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp; </span>都实现了根据自己的条件实现的页面得跳转。</div>
<div style="margin: 0cm 0cm 0pt 57pt; text-indent: -36pt"><span>（2）<span style="font: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>区别 <span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></div>
<table style="border-right: medium none; border-top: medium none; margin: auto auto auto 41.4pt; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 54pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="72">
            <div>类别</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 108pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="144">
            <div>概念</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 108pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="144">
            <div>共享数据</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 114.7pt; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="153">
            <div>应用</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 54pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="72">
            <div>Redirect</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 108pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="144">
            <div>URL重新定向：可以是任意的URL</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 108pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="144">
            <div>不能共享request里面的数据</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 114.7pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="153">
            <div>一般用于用户注销登录时返回主页面和跳转到其它的网站等等</div>
            </td>
        </tr>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; padding-bottom: 0cm; border-left: windowtext 1pt solid; width: 54pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="72">
            <div>Forward</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 108pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="144">
            <div>页面的转发：只能是同一个Web应用程序的其他Web组件</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 108pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="144">
            <div>转发页面和转发到的页面可以共性request里面的数据</div>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; padding-left: 5.4pt; border-left-color: #d4d0c8; padding-bottom: 0cm; width: 114.7pt; border-top-color: #d4d0c8; padding-top: 0cm; border-bottom: windowtext 1pt solid; background-color: transparent" valign="top" width="153">
            <div>一般用于用户登录的时候根据角色转发到相应的模块等等</div>
            </td>
        </tr>
    </tbody>
</table>
<div style="margin: 0cm 0cm 0pt 57pt; text-indent: -36pt"><span>（3）<span style="font: 7pt 'Times New Roman'"><font size="3">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </font></span></span>例子：</div>
<div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>譬如：client 通过XXX\index.jsp?name=gauss&amp;pwd=123访问index.jsp,而index.jsp中有&lt;jsp:forward page="login.jsp"/&gt;,则在login.jsp中可以通过request.getParameter()得到name和pwd，而&lt;%response.sendRedirect("login.jsp");%&gt;得不到。</div>
<div style="margin: 0cm 0cm 0pt 21pt">（4） 注意</div>
<div style="margin: 0cm 0cm 0pt 21pt"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>一般在index.jsp页面之前有个提交数据的页面default.jsp，则defautl.jsp页面提交的数据就可以在login.jsp页面得到，而不是得到index.jsp页面提交的数据，index.jsp页面只是执行的都是一个转发操作当然在里面可以增加也写业务操作，他可以得到request的数据，用XXX\index.jsp?name=gauss&amp;pwd=123这种方式登录就是省略了index.jsp前面的一个页面提交数据而已<br />
</div>
<br />
<br />
摘录补充：<br />
<p>效率: <br />
Forward高, Redirect低, 因为Redirect的流程是这样的, request 1 sent to server, server return back to client, request 2 then sent to server. But Forward 仅在server side处理, 对client side 是透明的. 由于Redirect 有两次传输, 所以效率低.</p>
<p>范围: <br />
由于对request.setAttribute() 来说, 它携带的对象生存范围只在request内, 所以Redirect方式会导致request携带的对象丢失.</p>
<p>总结: 一般还是用Forward比较合适.</p>
<br />
<img src ="http://www.blogjava.net/franlk/aggbug/166601.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-12-10 11:05 <a href="http://www.blogjava.net/franlk/articles/166601.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]web服务器与应用服务器的区别</title><link>http://www.blogjava.net/franlk/articles/166593.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Mon, 10 Dec 2007 02:47:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/166593.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/166593.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/166593.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/166593.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/166593.html</trackback:ping><description><![CDATA[<br />
&nbsp;
<p><strong><span style="font-size: 9pt; font-family: 宋体">通俗的讲，</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">Web</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">服务器传送</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">(serves)</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">页面使浏览器可以浏览，然而应用程序服务器提供的是客户端应用程序可以调用</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">(call)</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">的方法</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥"> (methods)</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">。确切一点，你可以说：</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">Web</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">服务器专门处理</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">HTTP</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">请求</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">(request)</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">，但是应用程序服务器是通过很多协议来为应用程序提供</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥"> (serves)</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">商业逻辑</span></strong><strong><span style="font-size: 9pt; font-family: ˎ̥">(business logic)</span></strong><strong><span style="font-size: 9pt; font-family: 宋体">。</span></strong><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">下面让我们来细细道来：</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
Web</span><span style="font-size: 9pt; font-family: 宋体">服务器</span><span style="font-size: 9pt; font-family: ˎ̥">(Web Server)<br />
Web</span><span style="font-size: 9pt; font-family: 宋体">服务器可以解析</span><span style="font-size: 9pt; font-family: ˎ̥">(handles)HTTP</span><span style="font-size: 9pt; font-family: 宋体">协议。当</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器接收到一个</span><span style="font-size: 9pt; font-family: ˎ̥">HTTP</span><span style="font-size: 9pt; font-family: 宋体">请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">，会返回一个</span><span style="font-size: 9pt; font-family: ˎ̥">HTTP</span><span style="font-size: 9pt; font-family: 宋体">响应</span><span style="font-size: 9pt; font-family: ˎ̥"> (response)</span><span style="font-size: 9pt; font-family: 宋体">，例如送回一个</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">页面。为了处理一个请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">，</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器可以响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">一个静态页面或图片，进行页面跳转</span><span style="font-size: 9pt; font-family: ˎ̥">(redirect)</span><span style="font-size: 9pt; font-family: 宋体">，或者把动态响应</span><span style="font-size: 9pt; font-family: ˎ̥">(dynamic response)</span><span style="font-size: 9pt; font-family: 宋体">的产生委托</span><span style="font-size: 9pt; font-family: ˎ̥">(delegate)</span><span style="font-size: 9pt; font-family: 宋体">给一些其它的程序例如</span><span style="font-size: 9pt; font-family: ˎ̥">CGI</span><span style="font-size: 9pt; font-family: 宋体">脚本，</span><span style="font-size: 9pt; font-family: ˎ̥">JSP(JavaServer Pages)</span><span style="font-size: 9pt; font-family: 宋体">脚本，</span><span style="font-size: 9pt; font-family: ˎ̥">servlets</span><span style="font-size: 9pt; font-family: 宋体">，</span><span style="font-size: 9pt; font-family: ˎ̥">ASP(Active Server Pages)</span><span style="font-size: 9pt; font-family: 宋体">脚本，服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)JavaScript</span><span style="font-size: 9pt; font-family: 宋体">，或者一些其它的服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)</span><span style="font-size: 9pt; font-family: 宋体">技术。无论它们</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">译者注：脚本</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">的目的如何，这些服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)</span><span style="font-size: 9pt; font-family: 宋体">的程序通常产生一个</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">的响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">来让浏览器可以浏览。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">要知道，</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器的代理模型</span><span style="font-size: 9pt; font-family: ˎ̥">(delegation model)</span><span style="font-size: 9pt; font-family: 宋体">非常简单。当一个请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">被送到</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器里来时，它只单纯的把请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">传递给可以很好的处理请求</span><span style="font-size: 9pt; font-family: ˎ̥"> (request)</span><span style="font-size: 9pt; font-family: 宋体">的程序</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">译者注：服务器端脚本</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">。</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器仅仅提供一个可以执行服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)</span><span style="font-size: 9pt; font-family: 宋体">程序和返回</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">程序所产生的</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">的环境，而不会超出职能范围。服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)</span><span style="font-size: 9pt; font-family: 宋体">程序通常具有事务处理</span><span style="font-size: 9pt; font-family: ˎ̥">(transaction processing)</span><span style="font-size: 9pt; font-family: 宋体">，数据库连接</span><span style="font-size: 9pt; font-family: ˎ̥">(database connectivity)</span><span style="font-size: 9pt; font-family: 宋体">和消息</span><span style="font-size: 9pt; font-family: ˎ̥">(messaging)</span><span style="font-size: 9pt; font-family: 宋体">等功能。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">虽然</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器不支持事务处理或数据库连接池，但它可以配置</span><span style="font-size: 9pt; font-family: ˎ̥">(employ)</span><span style="font-size: 9pt; font-family: 宋体">各种策略</span><span style="font-size: 9pt; font-family: ˎ̥">(strategies)</span><span style="font-size: 9pt; font-family: 宋体">来实现容错性</span><span style="font-size: 9pt; font-family: ˎ̥">(fault tolerance)</span><span style="font-size: 9pt; font-family: 宋体">和可扩展性</span><span style="font-size: 9pt; font-family: ˎ̥">(scalability)</span><span style="font-size: 9pt; font-family: 宋体">，例如负载平衡</span><span style="font-size: 9pt; font-family: ˎ̥">(load balancing)</span><span style="font-size: 9pt; font-family: 宋体">，缓冲</span><span style="font-size: 9pt; font-family: ˎ̥">(caching)</span><span style="font-size: 9pt; font-family: 宋体">。集群特征</span><span style="font-size: 9pt; font-family: ˎ̥">(clustering—features)</span><span style="font-size: 9pt; font-family: 宋体">经常被误认为仅仅是应用程序服务器专有的特征。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">应用程序服务器</span><span style="font-size: 9pt; font-family: ˎ̥">(The Application Server)<br />
</span><span style="font-size: 9pt; font-family: 宋体">根据我们的定义，作为应用程序服务器，它通过各种协议，可以包括</span><span style="font-size: 9pt; font-family: ˎ̥">HTTP</span><span style="font-size: 9pt; font-family: 宋体">，把商业逻辑暴露给</span><span style="font-size: 9pt; font-family: ˎ̥">(expose)</span><span style="font-size: 9pt; font-family: 宋体">客户端应用程序。</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器主要是处理向浏览器发送</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">以供浏览，而应用程序服务器提供访问商业逻辑的途径以供客户端应用程序使用。应用程序使用此商业逻辑就象你调用对象的一个方法</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">或过程语言中的一个函数</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">一样。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">应用程序服务器的客户端</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">包含有图形用户界面</span><span style="font-size: 9pt; font-family: ˎ̥">(GUI)</span><span style="font-size: 9pt; font-family: 宋体">的</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">可能会运行在一台</span><span style="font-size: 9pt; font-family: ˎ̥">PC</span><span style="font-size: 9pt; font-family: 宋体">、一个</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器或者甚至是其它的应用程序服务器上。在应用程序服务器与其客户端之间来回穿梭</span><span style="font-size: 9pt; font-family: ˎ̥">(traveling)</span><span style="font-size: 9pt; font-family: 宋体">的信息不仅仅局限于简单的显示标记。相反，这种信息就是程序逻辑</span><span style="font-size: 9pt; font-family: ˎ̥">(program logic)</span><span style="font-size: 9pt; font-family: 宋体">。正是由于这种逻辑取得了</span><span style="font-size: 9pt; font-family: ˎ̥">(takes)</span><span style="font-size: 9pt; font-family: 宋体">数据和方法调用</span><span style="font-size: 9pt; font-family: ˎ̥">(calls)</span><span style="font-size: 9pt; font-family: 宋体">的形式而不是静态</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">，所以客户端才可以随心所欲的使用这种被暴露的商业逻辑。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">在大多数情形下，应用程序服务器是通过组件</span><span style="font-size: 9pt; font-family: ˎ̥">(component)</span><span style="font-size: 9pt; font-family: 宋体">的应用程序接口</span><span style="font-size: 9pt; font-family: ˎ̥">(API)</span><span style="font-size: 9pt; font-family: 宋体">把商业逻辑暴露</span><span style="font-size: 9pt; font-family: ˎ̥">(expose)(</span><span style="font-size: 9pt; font-family: 宋体">给客户端应用程序</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">的，例如基于</span><span style="font-size: 9pt; font-family: ˎ̥">J2EE(Java 2 Platform, Enterprise Edition)</span><span style="font-size: 9pt; font-family: 宋体">应用程序服务器的</span><span style="font-size: 9pt; font-family: ˎ̥">EJB(Enterprise JavaBean)</span><span style="font-size: 9pt; font-family: 宋体">组件模型。此外，应用程序服务器可以管理自己的资源，例如看大门的工作</span><span style="font-size: 9pt; font-family: ˎ̥">(gate-keeping duties)</span><span style="font-size: 9pt; font-family: 宋体">包括安全</span><span style="font-size: 9pt; font-family: ˎ̥">(security)</span><span style="font-size: 9pt; font-family: 宋体">，事务处理</span><span style="font-size: 9pt; font-family: ˎ̥">(transaction processing)</span><span style="font-size: 9pt; font-family: 宋体">，资源池</span><span style="font-size: 9pt; font-family: ˎ̥">(resource pooling)</span><span style="font-size: 9pt; font-family: 宋体">，和消息</span><span style="font-size: 9pt; font-family: ˎ̥">(messaging)</span><span style="font-size: 9pt; font-family: 宋体">。就象</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器一样，应用程序服务器配置了多种可扩展</span><span style="font-size: 9pt; font-family: ˎ̥">(scalability)</span><span style="font-size: 9pt; font-family: 宋体">和容错</span><span style="font-size: 9pt; font-family: ˎ̥">(fault tolerance)</span><span style="font-size: 9pt; font-family: 宋体">技术。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">一个例子</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
</span><span style="font-size: 9pt; font-family: 宋体">例如，设想一个在线商店</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">网站</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">提供实时定价</span><span style="font-size: 9pt; font-family: ˎ̥">(real-time pricing)</span><span style="font-size: 9pt; font-family: 宋体">和有效性</span><span style="font-size: 9pt; font-family: ˎ̥">(availability)</span><span style="font-size: 9pt; font-family: 宋体">信息。这个站点</span><span style="font-size: 9pt; font-family: ˎ̥">(site)</span><span style="font-size: 9pt; font-family: 宋体">很可能会提供一个表单</span><span style="font-size: 9pt; font-family: ˎ̥">(form)</span><span style="font-size: 9pt; font-family: 宋体">让你来选择产品。当你提交查询</span><span style="font-size: 9pt; font-family: ˎ̥"> (query)</span><span style="font-size: 9pt; font-family: 宋体">后，网站会进行查找</span><span style="font-size: 9pt; font-family: ˎ̥">(lookup)</span><span style="font-size: 9pt; font-family: 宋体">并把结果内嵌在</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">页面中返回。网站可以有很多种方式来实现这种功能。我要介绍一个不使用应用程序服务器的情景和一个使用应用程序服务器的情景。观察一下这两中情景的不同会有助于你了解应用程序服务器的功能。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">情景</span><span style="font-size: 9pt; font-family: ˎ̥">1</span><span style="font-size: 9pt; font-family: 宋体">：不带应用程序服务器的</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">在此种情景下，一个</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器独立提供在线商店的功能。</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器获得你的请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">，然后发送给服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)</span><span style="font-size: 9pt; font-family: 宋体">可以处理请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">的程序。此程序从数据库或文本文件</span><span style="font-size: 9pt; font-family: ˎ̥">(flat file</span><span style="font-size: 9pt; font-family: 宋体">，译者注：</span><span style="font-size: 9pt; font-family: ˎ̥">flat file</span><span style="font-size: 9pt; font-family: 宋体">是指没有特殊格式的非二进制的文件，如</span><span style="font-size: 9pt; font-family: ˎ̥">properties</span><span style="font-size: 9pt; font-family: 宋体">和</span><span style="font-size: 9pt; font-family: ˎ̥">XML</span><span style="font-size: 9pt; font-family: 宋体">文件等</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">中查找定价信息。一旦找到，服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server-side)</span><span style="font-size: 9pt; font-family: 宋体">程序把结果信息表示成</span><span style="font-size: 9pt; font-family: ˎ̥">(formulate)HTML</span><span style="font-size: 9pt; font-family: 宋体">形式，最后</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器把会它发送到你的</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">浏览器。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">简而言之，</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器只是简单的通过响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)HTML</span><span style="font-size: 9pt; font-family: 宋体">页面来处理</span><span style="font-size: 9pt; font-family: ˎ̥">HTTP</span><span style="font-size: 9pt; font-family: 宋体">请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">情景</span><span style="font-size: 9pt; font-family: ˎ̥">2</span><span style="font-size: 9pt; font-family: 宋体">：带应用程序服务器的</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">情景</span><span style="font-size: 9pt; font-family: ˎ̥">2</span><span style="font-size: 9pt; font-family: 宋体">和情景</span><span style="font-size: 9pt; font-family: ˎ̥">1</span><span style="font-size: 9pt; font-family: 宋体">相同的是</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器还是把响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">的产生委托</span><span style="font-size: 9pt; font-family: ˎ̥">(delegates)</span><span style="font-size: 9pt; font-family: 宋体">给脚本</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">译者注：服务器端</span><span style="font-size: 9pt; font-family: ˎ̥">(server- side)</span><span style="font-size: 9pt; font-family: 宋体">程序</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">。然而，你可以把查找定价的商业逻辑</span><span style="font-size: 9pt; font-family: ˎ̥">(business logic)</span><span style="font-size: 9pt; font-family: 宋体">放到应用程序服务器上。由于这种变化，此脚本只是简单的调用应用程序服务器的查找服务</span><span style="font-size: 9pt; font-family: ˎ̥">(lookup service)</span><span style="font-size: 9pt; font-family: 宋体">，而不是已经知道如何查找数据然后表示为</span><span style="font-size: 9pt; font-family: ˎ̥">(formulate)</span><span style="font-size: 9pt; font-family: 宋体">一个响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">。这时当该脚本程序产生</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">时就可以使用该服务的返回结果了。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">在此情景中，应用程序服务器提供</span><span style="font-size: 9pt; font-family: ˎ̥">(serves)</span><span style="font-size: 9pt; font-family: 宋体">了用于查询产品的定价信息的商业逻辑。</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">服务器的</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">这种功能</span><span style="font-size: 9pt; font-family: ˎ̥">(functionality)</span><span style="font-size: 9pt; font-family: 宋体">没有指出有关显示和客户端如何使用此信息的细节，相反客户端和应用程序服务器只是来回传送数据。当有客户端调用应用程序服务器的查找服务</span><span style="font-size: 9pt; font-family: ˎ̥">(lookup service)</span><span style="font-size: 9pt; font-family: 宋体">时，此服务只是简单的查找并返回结果给客户端。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">通过从响应产生</span><span style="font-size: 9pt; font-family: ˎ̥">(response-generating)HTML</span><span style="font-size: 9pt; font-family: 宋体">的代码中分离出来，在应用程序之中该定价</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">查找</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">逻辑的可重用性更强了。其他的客户端，例如收款机，也可以调用同样的服务</span><span style="font-size: 9pt; font-family: ˎ̥">(service)</span><span style="font-size: 9pt; font-family: 宋体">来作为一个店员给客户结帐。相反，在情景</span><span style="font-size: 9pt; font-family: ˎ̥">1</span><span style="font-size: 9pt; font-family: 宋体">中的定价查找服务是不可重用的因为信息内嵌在</span><span style="font-size: 9pt; font-family: ˎ̥">HTML </span><span style="font-size: 9pt; font-family: 宋体">页中了。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">总而言之，在情景</span><span style="font-size: 9pt; font-family: ˎ̥">2</span><span style="font-size: 9pt; font-family: 宋体">的模型中，在</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器通过回应</span><span style="font-size: 9pt; font-family: ˎ̥">HTML</span><span style="font-size: 9pt; font-family: 宋体">页面来处理</span><span style="font-size: 9pt; font-family: ˎ̥">HTTP</span><span style="font-size: 9pt; font-family: 宋体">请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">，而应用程序服务器则是通过处理定价和有效性</span><span style="font-size: 9pt; font-family: ˎ̥">(availability)</span><span style="font-size: 9pt; font-family: 宋体">请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">来提供应用程序逻辑的。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">警告</span><span style="font-size: 9pt; font-family: ˎ̥">(Caveats)<br />
</span><span style="font-size: 9pt; font-family: 宋体">现在，</span><span style="font-size: 9pt; font-family: ˎ̥">XML Web Services</span><span style="font-size: 9pt; font-family: 宋体">已经使应用程序服务器和</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器的界线混淆了。通过传送一个</span><span style="font-size: 9pt; font-family: ˎ̥">XML</span><span style="font-size: 9pt; font-family: 宋体">有效载荷</span><span style="font-size: 9pt; font-family: ˎ̥">(payload)</span><span style="font-size: 9pt; font-family: 宋体">给服务器，</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器现在可以处理数据和响应</span><span style="font-size: 9pt; font-family: ˎ̥">(response)</span><span style="font-size: 9pt; font-family: 宋体">的能力与以前的应用程序服务器同样多了。</span><span style="font-size: 9pt; font-family: ˎ̥"><br />
<br />
</span><span style="font-size: 9pt; font-family: 宋体">另外，现在大多数应用程序服务器也包含了</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器，这就意味着可以把</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器当作是应用程序服务器的一个子集</span><span style="font-size: 9pt; font-family: ˎ̥">(subset)</span><span style="font-size: 9pt; font-family: 宋体">。虽然应用程序服务器包含了</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器的功能，但是开发者很少把应用程序服务器部署</span><span style="font-size: 9pt; font-family: ˎ̥">(deploy)</span><span style="font-size: 9pt; font-family: 宋体">成这种功能</span><span style="font-size: 9pt; font-family: ˎ̥">(capacity)(</span><span style="font-size: 9pt; font-family: 宋体">译者注：这种功能是指既有应用程序服务器的功能又有</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器的功能</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">。相反，如果需要，他们通常会把</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器独立配置，和应用程序服务器一前一后。这种功能的分离有助于提高性能</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">简单的</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">请求</span><span style="font-size: 9pt; font-family: ˎ̥">(request)</span><span style="font-size: 9pt; font-family: 宋体">就不会影响应用程序服务器了</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">，分开配置</span><span style="font-size: 9pt; font-family: ˎ̥">(</span><span style="font-size: 9pt; font-family: 宋体">专门的</span><span style="font-size: 9pt; font-family: ˎ̥">Web</span><span style="font-size: 9pt; font-family: 宋体">服务器，集群</span><span style="font-size: 9pt; font-family: ˎ̥">(clustering)</span><span style="font-size: 9pt; font-family: 宋体">等等</span><span style="font-size: 9pt; font-family: ˎ̥">)</span><span style="font-size: 9pt; font-family: 宋体">，而且给最佳产品的选取留有余地。</span></p>
<img src ="http://www.blogjava.net/franlk/aggbug/166593.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-12-10 10:47 <a href="http://www.blogjava.net/franlk/articles/166593.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]UML类图关系全面剖析 </title><link>http://www.blogjava.net/franlk/articles/156133.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Fri, 26 Oct 2007 06:14:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/156133.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/156133.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/156133.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/156133.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/156133.html</trackback:ping><description><![CDATA[摘录地址:http://blog.csdn.net/dylgsy/archive/2006/08/16/1076044.aspx<br />
<br />
<p><font size="1">UML的类图关系分为：&nbsp;关联、聚合/组合、依赖、泛化（继承）。而其中关联又分为双向关联、单向关联、自身关联；下面就让我们一起来看看这些关系究竟是什么，以及它们的区别在哪里。</font><br />
<br />
<strong>1、关联</strong><br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/doubleAssoc.JPG" /><br />
<br />
<font size="1">双向关联：<br />
C1-C2：指双方都知道对方的存在，都可以调用对方的公共属性和方法。<br />
<br />
在GOF的设计模式书上是这样描述的：虽然在分析阶段这种关系是适用的，但我们觉得它对于描述设计模式内的类关系来说显得太抽象了，因为在设计阶段关联关系必须被映射为对象引用或指针。对象引用本身就是有向的，更适合表达我们所讨论的那种关系。所以这种关系在设计的时候比较少用到，关联一般都是有向的。<br />
<br />
使用ROSE 生成的代码是这样的：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C1&nbsp;<br />
<img id="_10_33_Open_Image" onclick="this.style.display='none'; document.getElementById('_10_33_Open_Text').style.display='none'; document.getElementById('_10_33_Closed_Image').style.display='inline'; document.getElementById('_10_33_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_10_33_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_10_33_Closed_Text').style.display='none'; document.getElementById('_10_33_Open_Image').style.display='inline'; document.getElementById('_10_33_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_10_33_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_10_33_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;C2</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;theC2;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C2&nbsp;<br />
<img id="_47_70_Open_Image" onclick="this.style.display='none'; document.getElementById('_47_70_Open_Text').style.display='none'; document.getElementById('_47_70_Closed_Image').style.display='inline'; document.getElementById('_47_70_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_47_70_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_47_70_Closed_Text').style.display='none'; document.getElementById('_47_70_Open_Image').style.display='inline'; document.getElementById('_47_70_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_47_70_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_47_70_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;C1</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;theC1;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;</span></div>
</div>
<p><font size="1">双向关联在代码的表现为双方都拥有对方的一个指针，当然也可以是引用或者是值。</font><br />
<br />
<br />
<br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/uniAssoc.JPG" /><br />
<br />
<font size="1">单向关联:<br />
C3-&gt;C4：表示相识关系，指C3知道C4，C3可以调用C4的公共属性和方法。没有生命期的依赖。一般是表示为一种引用。<br />
<br />
生成代码如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C3&nbsp;<br />
<img id="_10_33_Open_Image" onclick="this.style.display='none'; document.getElementById('_10_33_Open_Text').style.display='none'; document.getElementById('_10_33_Closed_Image').style.display='inline'; document.getElementById('_10_33_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_10_33_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_10_33_Closed_Text').style.display='none'; document.getElementById('_10_33_Open_Image').style.display='inline'; document.getElementById('_10_33_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_10_33_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_10_33_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;C4</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;theC4;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C4&nbsp;<br />
<img id="_47_50_Open_Image" onclick="this.style.display='none'; document.getElementById('_47_50_Open_Text').style.display='none'; document.getElementById('_47_50_Closed_Image').style.display='inline'; document.getElementById('_47_50_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_47_50_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_47_50_Closed_Text').style.display='none'; document.getElementById('_47_50_Open_Image').style.display='inline'; document.getElementById('_47_50_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_47_50_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_47_50_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;</span></div>
</div>
<p><font size="1">单向关联的代码就表现为C3有C4的指针，而C4对C3一无所知。</font><br />
<br />
<br />
</p>
<p><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/selfAssoc.JPG" /><br />
<br />
<img height="114" alt="图 14：一个反射关联关系的实例" src="http://www.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig14.gif" width="193" border="0" /><br />
<br />
<font size="1">自身关联（反身关联）：<br />
自己引用自己，带着一个自己的引用。<br />
<br />
代码如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C14&nbsp;<br />
<img id="_11_36_Open_Image" onclick="this.style.display='none'; document.getElementById('_11_36_Open_Text').style.display='none'; document.getElementById('_11_36_Closed_Image').style.display='inline'; document.getElementById('_11_36_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_11_36_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_11_36_Closed_Text').style.display='none'; document.getElementById('_11_36_Open_Image').style.display='inline'; document.getElementById('_11_36_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_11_36_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_11_36_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;C14</span><span style="color: #000000">*</span><span style="color: #000000">&nbsp;theC14;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;</span></div>
</div>
<p><font size="1">就是在自己的内部有着一个自身的引用。<br />
<br />
</font><font size="1"><strong>2、聚合/组合<br />
</strong><br />
当类之间有整体-部分关系的时候，我们就可以使用组合或者聚合。</font><br />
<br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/Aggregation.JPG" /><br />
<br />
<img height="49" alt="图 12: 一个聚合关联的例子" src="http://www.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig12.jpg" width="291" border="0" /><br />
<br />
<font size="1">聚合：表示C9聚合C10，但是C10可以离开C9而独立存在（独立存在的意思是在某个应用的问题域中这个类的存在有意义。这句话怎么解，请看下面组合里的解释）。<br />
<br />
代码如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C9&nbsp;<br />
<img id="_10_34_Open_Image" onclick="this.style.display='none'; document.getElementById('_10_34_Open_Text').style.display='none'; document.getElementById('_10_34_Closed_Image').style.display='inline'; document.getElementById('_10_34_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_10_34_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_10_34_Closed_Text').style.display='none'; document.getElementById('_10_34_Open_Image').style.display='inline'; document.getElementById('_10_34_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_10_34_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_10_34_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;C10&nbsp;theC10;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C10&nbsp;<br />
<img id="_49_52_Open_Image" onclick="this.style.display='none'; document.getElementById('_49_52_Open_Text').style.display='none'; document.getElementById('_49_52_Closed_Image').style.display='inline'; document.getElementById('_49_52_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_49_52_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_49_52_Closed_Text').style.display='none'; document.getElementById('_49_52_Open_Image').style.display='inline'; document.getElementById('_49_52_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_49_52_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_49_52_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span></div>
</div>
<p>&nbsp;</p>
<p><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/Composition.JPG" /><br />
<br />
<img height="47" alt="图 13: 一个组合关系的例子" src="http://www.ibm.com/developerworks/cn/rational/rationaledge/content/feb05/bell/bell_fig13.jpg" width="341" border="0" /><br />
<br />
<font size="1">组合（也有人称为包容）：一般是实心菱形加实线箭头表示，如上图所示，表示的是C8被C7包容，而且C8不能离开C7而独立存在。但这是视问题域而定的，例如在关心汽车的领域里，轮胎是一定要组合在汽车类中的，因为它离开了汽车就没有意义了。但是在卖轮胎的店铺业务里，就算轮胎离开了汽车，它也是有意义的，这就可以用聚合了。在《敏捷开发》中还说到，A组合B，则A需要知道B的生存周期，即可能A负责生成或者释放B，或者A通过某种途径知道B的生成和释放。<br />
<br />
他们的代码如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C7&nbsp;<br />
<img id="_10_32_Open_Image" onclick="this.style.display='none'; document.getElementById('_10_32_Open_Text').style.display='none'; document.getElementById('_10_32_Closed_Image').style.display='inline'; document.getElementById('_10_32_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_10_32_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_10_32_Closed_Text').style.display='none'; document.getElementById('_10_32_Open_Image').style.display='inline'; document.getElementById('_10_32_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_10_32_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_10_32_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: #0000ff">public</span><span style="color: #000000">:<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;C8&nbsp;theC8;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C8&nbsp;<br />
<img id="_46_48_Open_Image" onclick="this.style.display='none'; document.getElementById('_46_48_Open_Text').style.display='none'; document.getElementById('_46_48_Closed_Image').style.display='inline'; document.getElementById('_46_48_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_46_48_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_46_48_Closed_Text').style.display='none'; document.getElementById('_46_48_Open_Image').style.display='inline'; document.getElementById('_46_48_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_46_48_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_46_48_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;</span></div>
</div>
<p><font size="1">可以看到，代码和聚合是一样的。具体如何区别，可能就只能用语义来区分了。<br />
<br />
<strong>3、依赖</strong></font><br />
<br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/Dependancy.JPG" /><br />
<br />
<font size="1">依赖:<br />
指C5可能要用到C6的一些方法，也可以这样说，要完成C5里的所有功能，一定要有C6的方法协助才行。C5依赖于C6的定义，一般是在C5类的头文件中包含了C6的头文件。ROSE对依赖关系不产生属性。<br />
<br />
注意，要避免双向依赖。一般来说，不应该存在双向依赖。<br />
<br />
ROSE生成的代码如下：</font><br />
</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #008000">//</span><span style="color: #008000">&nbsp;C5.h</span><span style="color: #008000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">C6.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C5&nbsp;<br />
<img id="_35_38_Open_Image" onclick="this.style.display='none'; document.getElementById('_35_38_Open_Text').style.display='none'; document.getElementById('_35_38_Closed_Image').style.display='inline'; document.getElementById('_35_38_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_35_38_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_35_38_Closed_Text').style.display='none'; document.getElementById('_35_38_Open_Image').style.display='inline'; document.getElementById('_35_38_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_35_38_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_35_38_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #008000">//</span><span style="color: #008000">&nbsp;C6.h</span><span style="color: #008000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">C5.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C6<br />
<img id="_76_79_Open_Image" onclick="this.style.display='none'; document.getElementById('_76_79_Open_Text').style.display='none'; document.getElementById('_76_79_Closed_Image').style.display='inline'; document.getElementById('_76_79_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_76_79_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_76_79_Closed_Text').style.display='none'; document.getElementById('_76_79_Open_Image').style.display='inline'; document.getElementById('_76_79_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_76_79_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_76_79_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span></div>
</div>
<p><font size="1">虽然ROSE不生成属性，但在形式上一般是A中的某个方法把B的对象作为参数使用(假设A依赖于B)。如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">B.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;A<br />
<img id="_23_52_Open_Image" onclick="this.style.display='none'; document.getElementById('_23_52_Open_Text').style.display='none'; document.getElementById('_23_52_Closed_Image').style.display='inline'; document.getElementById('_23_52_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_23_52_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_23_52_Closed_Text').style.display='none'; document.getElementById('_23_52_Open_Image').style.display='inline'; document.getElementById('_23_52_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_23_52_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_23_52_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">void</span><span style="color: #000000">&nbsp;Func(B&nbsp;</span><span style="color: #000000">&amp;</span><span style="color: #000000">b);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
</div>
<p><font size="1"><strong><font color="#ff0000">那依赖和聚合\组合、关联等有什么不同呢？</font></strong><br />
<br />
关联是类之间的一种关系，例如老师教学生，老公和老婆，水壶装水等就是一种关系。这种关系是非常明显的，在问题领域中通过分析直接就能得出。<br />
<br />
依赖是一种弱关联，只要一个类用到另一个类，但是和另一个类的关系不是太明显的时候（可以说是&#8220;uses&#8221;了那个类），就可以把这种关系看成是依赖，依赖也可说是一种偶然的关系，而不是必然的关系，就是&#8220;我在某个方法中偶然用到了它，但在现实中我和它并没多大关系&#8221;。例如我和锤子，我和锤子本来是没关系的，但在有一次要钉钉子的时候，我用到了它，这就是一种依赖，依赖锤子完成钉钉子这件事情。</font></p>
<p><font size="1">组合是一种整体-部分的关系，在问题域中这种关系很明显，直接分析就可以得出的。例如轮胎是车的一部分，树叶是树的一部分，手脚是身体的一部分这种的关系，非常明显的整体-部分关系。<br />
<br />
上述的几种关系（关联、聚合/组合、依赖）在代码中可能以指针、引用、值等的方式在另一个类中出现，不拘于形式，但在逻辑上他们就有以上的区别。<br />
<br />
这里还要说明一下，所谓的这些关系只是在某个问题域才有效，离开了这个问题域，可能这些关系就不成立了，例如可能在某个问题域中，我是一个木匠，需要拿着锤子去干活，可能整个问题的描述就是我拿着锤子怎么钉桌子，钉椅子，钉柜子；既然整个问题就是描述这个，我和锤子就不仅是偶然的依赖关系了，我和锤子的关系变得非常的紧密，可能就上升为组合关系（让我突然想起武侠小说的剑不离身，剑亡人亡...）。这个例子可能有点荒谬，但也是为了说明一个道理，就是关系和类一样，它们都是在一个问题领域中才成立的，离开了这个问题域，他们可能就不复存在了。<br />
<br />
<br />
<strong>4、泛化（继承）</strong></font><br />
<br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/inheri.jpg" /><br />
<br />
<font size="1">泛化关系：如果两个类存在泛化的关系时就使用，例如父和子，动物和老虎，植物和花等。<br />
ROSE生成的代码很简单，如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">#include&nbsp;</span><span style="color: #000000">"</span><span style="color: #000000">C11.h</span><span style="color: #000000">"</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C12&nbsp;:&nbsp;</span><span style="color: #0000ff">public</span><span style="color: #000000">&nbsp;C11<br />
<img id="_41_43_Open_Image" onclick="this.style.display='none'; document.getElementById('_41_43_Open_Text').style.display='none'; document.getElementById('_41_43_Closed_Image').style.display='inline'; document.getElementById('_41_43_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_41_43_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_41_43_Closed_Text').style.display='none'; document.getElementById('_41_43_Open_Image').style.display='inline'; document.getElementById('_41_43_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_41_43_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_41_43_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;</span></div>
</div>
<p><br />
<strong><font size="1">5、这里顺便提一下模板</font></strong><br />
<br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/dylgsy/Template.jpg" /><br />
<br />
<font size="1">上面的图对应的代码如下：</font></p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: #e6e6e6; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; word-break: break-all; padding-top: 4px; border-bottom: windowtext 0.5pt solid">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: #000000">template</span><span style="color: #000000">&lt;</span><span style="color: #0000ff">int</span><span style="color: #000000">&gt;</span><span style="color: #000000"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">class</span><span style="color: #000000">&nbsp;C13&nbsp;<br />
<img id="_25_27_Open_Image" onclick="this.style.display='none'; document.getElementById('_25_27_Open_Text').style.display='none'; document.getElementById('_25_27_Closed_Image').style.display='inline'; document.getElementById('_25_27_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_25_27_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_25_27_Closed_Text').style.display='none'; document.getElementById('_25_27_Open_Image').style.display='inline'; document.getElementById('_25_27_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_25_27_Closed_Text" style="border-right: #808080 1px solid; border-top: #808080 1px solid; display: none; border-left: #808080 1px solid; border-bottom: #808080 1px solid; background-color: #ffffff">...</span><span id="_25_27_Open_Text"><span style="color: #000000">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: #000000">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span></div>
</div>
<p><font size="1">这里再说一下重复度，其实看完了上面的描述之后，我们应该清楚了各个关系间的关系以及具体对应到代码是怎么样的，所谓的重复度，也只不过是上面的扩展，例如A和B有着&#8220;1对多&#8221;的重复度，那在A中就有一个列表，保存着B对象的N个引用，就是这样而已。<br />
<br />
好了，到这里，已经把上面的类图关系说完了，希望你能有所收获了，我也费了不少工夫啊（画图、生成代码、截图、写到BLOG上，唉，一头大汗）。不过如果能让你彻底理解UML类图的这些关系，也值得了。:)</font></p>
<img src ="http://www.blogjava.net/franlk/aggbug/156133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-10-26 14:14 <a href="http://www.blogjava.net/franlk/articles/156133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>demo</title><link>http://www.blogjava.net/franlk/articles/144638.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Wed, 12 Sep 2007 14:59:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/144638.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/144638.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/144638.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/144638.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/144638.html</trackback:ping><description><![CDATA[<p align="right">&nbsp;</p>
<p>package com.test;</p>
<p>import java.io.*;<br />
import java.util.regex.Matcher;<br />
import java.util.regex.Pattern;<br />
public class FileReadWrite {<br />
public static void main(String[] args){<br />
&nbsp;FileReader fRd = null;<br />
&nbsp;FileWriter fWt = null;<br />
&nbsp;try {<br />
//&nbsp;&nbsp;//<br />
//&nbsp;&nbsp;fRd = new FileReader("D:\\FRANLK\\temp\\txt.TXT");<br />
//&nbsp;&nbsp;fWt = new FileWriter("D:\\FRANLK\\temp\\out.TXT");<br />
//&nbsp;&nbsp;BufferedReader bufRd = new BufferedReader(fRd); <br />
//&nbsp;&nbsp;BufferedWriter bufWt = new BufferedWriter(fWt);<br />
//&nbsp;&nbsp;String strLine=bufRd.readLine();<br />
//&nbsp;&nbsp;while(strLine!=null){<br />
//&nbsp;&nbsp;&nbsp;System.out.println("--------"+strLine);<br />
//&nbsp;&nbsp;&nbsp;bufWt.newLine();<br />
//&nbsp;&nbsp;&nbsp;String strReg ="%[a-zA-Z]+%"; <br />
//&nbsp;&nbsp;&nbsp;bufWt.write("*****+++*"+strLine);<br />
//&nbsp;&nbsp;&nbsp;Pattern ptn = Pattern.compile(strReg);<br />
//&nbsp;&nbsp;&nbsp;Matcher mth =ptn.matcher(strLine);<br />
//&nbsp;&nbsp;&nbsp;System.out.println("aaaaaaaa--"+mth.group(0));<br />
//&nbsp;&nbsp;&nbsp;bufWt.newLine();<br />
//&nbsp;&nbsp;&nbsp;strLine=bufRd.readLine();<br />
//&nbsp;&nbsp;}&nbsp;&nbsp;<br />
//&nbsp;&nbsp;bufRd.close();<br />
//&nbsp;&nbsp;fRd.close();<br />
//&nbsp;&nbsp;bufWt.flush();<br />
//&nbsp;&nbsp;bufWt.close();<br />
//&nbsp;&nbsp;fWt.close();<br />
&nbsp;&nbsp;String regEx="^%\\w+%";<br />
&nbsp;&nbsp;String regEx2 = "%\\w+\\(";<br />
&nbsp;&nbsp;String regEx3 = "@.+。$";<br />
&nbsp;&nbsp;String regEx4 = "^%{1}(\\w+)%{1}(\\w+\\(\\))@{1}(.+)。$";<br />
&nbsp;&nbsp;String str="%int%available()@返回可以不受阻塞地从此文件输入流中读取的字节数。";<br />
&nbsp;&nbsp;Pattern p = Pattern.compile(regEx4);<br />
&nbsp;&nbsp;Matcher m =p.matcher(str);<br />
&nbsp;&nbsp;boolean rs=m.find();<br />
&nbsp;&nbsp;System.out.println("find---"+rs);<br />
&nbsp;&nbsp;System.out.println("++++"+m.groupCount());<br />
&nbsp;&nbsp;for(int i=1;i&lt;=m.groupCount();i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(m.group(i));<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;<br />
&nbsp;} catch (Exception e) {&nbsp;<br />
&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;}<br />
}<br />
}</p>
<img src ="http://www.blogjava.net/franlk/aggbug/144638.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-09-12 22:59 <a href="http://www.blogjava.net/franlk/articles/144638.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]struts标签介绍大全 </title><link>http://www.blogjava.net/franlk/articles/137491.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Fri, 17 Aug 2007 03:25:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/137491.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/137491.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/137491.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/137491.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/137491.html</trackback:ping><description><![CDATA[<br>摘录地址:http://blog.csdn.net/ericlian/archive/2006/10/15/1335611.aspx<br><br><br>
<div class=title>Struts标签<br><a href="http://www.solol.org/technologic/java/j-struts/#author">solo L</a><br>发布日期：2005年06月01日<br>更新日期：2005年06月01日 </div>
<div class=abstract>您使用过旅游指南吗？它总是能让我们快速的找到目的地。我对此有深刻的印象，希望这篇指南也能使您快速的完成Struts标签相关的任务。我深入细致的总结了日常使用Struts的一些经验，感觉Struts标签的用途非常广泛并且功能强大，但是学起来还是比较费时间的。我认为学习Struts标签最好的方式就是参考良好的示例，幸运的是这些示例您可以在下面找到。</div>
<p>Struts是Apache Jakarta的一个著名的开源项目，目标是为构建基于Java的web应用程序提供一个框架。</p>
<p>Struts提供了非常多的标签，依据功能和使用习惯的不同被分到了五个标签库中:</p>
<ul>
    <li>Bean Tags:该标签库包含的标签可以用来创建bean、访问bean和访问bean的属性。同时提供了依据cookies、headers和parameters的值创建相关bean的能力。
    <li>HTML Tags:该标签库包含的标签可以用来创建Struts输入表单。
    <li>Logic Tags:该标签库包含的标签可以用来进行逻辑判断、集合迭代和流程控制。
    <li>Nested Tags:该标签库建立在前三个标签库的基础上，具有前三个标签库的所有功能，只是允许标签间的嵌套。
    <li>Tiles Tags:该标签库包含的标签可以用来创建tiles样式的页面。 </li>
</ul>
<p>这篇指南主要介绍前三个标签库中的标签。如果您对后两类标签也感兴趣可以查阅<a href="http://www.solol.org/technologic/java/j-struts/#resource">参考资料</a>中的Struts的用户指南。 </p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e77>bean:cookie</a></div>
<p>cookie最早是由Netscape公司提出来的，用来存储客户的少量状态信息。如果您对cookie的具体细节感兴趣可以查阅<a href="http://www.solol.org/technologic/java/j-struts/#resource">参考资料</a>中的cookie spec。 </p>
<p>bean:cookie标签取回请求中名称为name的cookie的值。如果没有指定multiple属性则依据刚取回的值创建一个Cookie类型的bean。如果指定了multiple属性则依据刚取回的值创建一个Cookie[]类型的数组。然后用id属性值将Cookie或Cookie[]绑定到page作用域中(这种绑定是为了其它标签能够使用该值)，并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。</p>
<p>下面的代码片段示例了如何使用bean:cookie标签读取名为JSESSIONID的cookie的值，并且使用了两种方式进行了输出：</p>
<pre>&lt;logic:present cookie="JSESSIONID"&gt;  &lt;bean:cookie id="jSession" name="JSESSIONID"/&gt;  &lt;!-- 其它标签通过绑定到page作用域中的属性使用该值 --&gt;  这个cookie的名称是&lt;bean:write name="jSession" property="name"/&gt;，  值为&lt;bean:write name="jSession" property="value"/&gt;。&lt;br/&gt;  &lt;!-- JSP脚本通过scripting变量使用该值 --&gt;  &lt;%    String name = jSession.getName();    String value = jSession.getValue();    out.println("这个cookie的名称是"+name+"，值为"+value+"。&lt;br/&gt;");	  %&gt;&lt;/logic:present&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e98>bean:define</a></div>
<p>bean:define标签在toScope(如果没有指定值就使用page作用域)指定的作用域中创建一个新属性，同时创建一个scripting变量。我们可以通过id值使用它们。新创建的属性可以由其它标签使用，而新创建的scripting变量可以由JSP脚本使用。</p>
<p>我们可以使用三种方式为新创建的属性和scripting变量赋值： </p>
<ul>
    <li>通过该标签的name、property和scope取回值，并且保持类型的一致性，除非取回的值为Java的原始类型，这时会使用适合的包装器类对这些值进行包装。
    <li>通过该标签的value指定值，这时新创建的属性和scripting变量的类型为java.lang.String。
    <li>通过在该标签的体中嵌入值，这时新创建的属性和scripting变量的类型为java.lang.String。 </li>
</ul>
<p>&nbsp;</p>
<p>下面的代码片段示例了如何使用bean:define标签创建新属性values和新scripting变量values，它将listForm中persons的值取出来赋给values:</p>
<pre>&lt;bean:define id="values" name="listForm" property = "persons" 	type="java.util.List"/&gt; </pre>
<p>下面给出ListForm的代码片段以帮助您更好的理解，其中Person是一个只有id和name两个属性的简单bean：</p>
<pre>public class ListForm extends ActionForm {  private List&lt;Person&gt; persons = null;  public List&lt;Person&gt; getPersons() {    return persons;  }  public void setPersons(List&lt;Person&gt; persons) {    this.persons = persons;  }  public void reset(ActionMapping mapping,       HttpServletRequest request) {    persons = null;  }} </pre>
<p>下面的代码片段示例了logic:iterate标签如何使用bean:define标签创建的新属性values:</p>
<pre>&lt;logic:iterate id="person" name="values"&gt;  &lt;bean:write name="person" property="id"/&gt;&lt;br/&gt;&lt;/logic:iterate&gt;</pre>
<p>下面的代码片段示例了JSP脚本如何使用bean:define标签创建的新scripting变量values:</p>
<pre>&lt;%  Person p = new Person();  for(int i=0;i&lt;values.size();i++){    p = (Person)values.get(i);    out.println(p.getId());    out.println("&lt;br/&gt;");  }		%&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e148>bean:header</a></div>
<p>bean:header标签取回请求中名称为name的header的值。如果没有指定multiple属性则依据刚取回的值创建一个String类型的bean。如果指定了multiple属性则依据刚取回的值创建一个String[]类型的数组。然后用id属性值将String或String[]绑定到page作用域中(这种绑定是为了其它标签能够使用该值)，并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。</p>
<p>下面是我的浏览器发送的header的内容，这些内容和浏览器有关，因此您的浏览器发送的内容可能和下面列出的不同。不过这没有关系，因为要理解bean:header标签您只要对这些内容有一个大概的认识就足够了。</p>
<pre>accept: */* accept-language: zh-cn accept-encoding: gzip, deflate user-agent: Mozilla/4.0 (compatible; MSIE 6.0; //应该在同一行  Windows NT 5.1; SV1; .NET CLR 1.1.4322) host: localhost:8080 connection: Keep-Alive </pre>
<p>下面的代码片段示例了如何使用bean:header标签读取名为User-Agent的header的值，并且使用了两种方式进行了输出：</p>
<pre>&lt;logic:present header="User-Agent"&gt;  &lt;!-- 其它标签通过绑定到page作用域中的属性使用该值 --&gt;  您的浏览器是&lt;bean:header id="userAgent" name="User-Agent"/&gt;  &lt;bean:write name="userAgent"/&gt;。&lt;br/&gt;  &lt;!-- JSP脚本通过scripting变量使用该值 --&gt;  &lt;%    out.println("您的浏览器是"+userAgent+"。&lt;br/&gt;");	  %&gt;&lt;/logic:present&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e169>bean:include</a></div>
<p>bean:include标签对指定url(由forward、href或page确定)处的资源做一个请求，将响应数据作为一个String类型的bean绑定到page作用域，同时创建一个scripting变量。我们可以通过id值访问它们。</p>
<p>下面的代码片段示例了bean:include标签的用法，其中include.txt文件包含要include的内容，然后将这些内容输出:</p>
<pre>&lt;bean:include id="value" page="/include.txt"/&gt;&lt;!-- 其它标签通过绑定到page作用域中的属性使用该值 --&gt;&lt;bean:write name="value"/&gt;&lt;br/&gt;&lt;!-- JSP脚本通过scripting变量使用该值 --&gt;&lt;%  out.println(value);	%&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e184>bean:message</a></div>
<p>bean:message标签用来从指定的locale中取回国际化的消息并输出，在这个过程中我们还可以传递五个以内的参数。message key可以通过key直接指定，也可以通过name和property间接的指定。</p>
<p>bean:message标签有两种指定message key的方式，一是通过key属性直接指定；二是通过name和property属性间接的指定，其中message key是在message resources文件中定义的。</p>
<p>我们可以在struts-config.xml文件中使用&lt;message-resources&gt;来设置message resources文件。</p>
<p>为了介绍该标签我使用了三个message resources文件，三个文件的名字分别为Resources.properties、Resources_en.properties和Resources_zh.properties。在struts-config.xml文件中的设置(这里不用设置三个，struts会依据locale自动找到对应的文件)如下：</p>
<pre>&lt;message-resources parameter="Resources" /&gt;</pre>
<p>三个message resources文件中定义的message key为：</p>
<pre>&lt;!-- Resources.properties --&gt;resource=Resources.properties.from=Resources.properties.&lt;!-- Resources_en.properties --&gt;from=Resources_en.properties.&lt;!-- Resources_zh.properties   因为文件的编码被限制为ISO8859所以要有汉字必须用jdk的native2ascii提前转换 --&gt;from=Resources_zh.properties.</pre>
<p>下面的代码片段示例了bean:message标签的用法:</p>
<pre>&lt;bean:message key="from"/&gt;&lt;br/&gt;&lt;bean:message key="resource"/&gt;&lt;br/&gt;&lt;html:link action="/locale?language=en"&gt;English&lt;/html:link&gt;&lt;html:link action="/locale?language=zh"&gt;Chinese&lt;/html:link&gt;</pre>
<p>上面的代码中含有改变locale的两个html:link标签，要使它们工作您的struts-config.xml文件中必须含有下面定义的form和action:</p>
<pre>&lt;form-bean name="localeForm"     type="org.apache.struts.action.DynaActionForm"&gt;  &lt;form-property name="language" type="java.lang.String" /&gt;  &lt;form-property name="country" type="java.lang.String" /&gt;  &lt;!--action成功后要跳到那里--&gt;  &lt;form-property name="page"  type="java.lang.String"     initial="/message.jsp"/&gt;&lt;/form-bean&gt;	&lt;action path="/locale" type="org.apache.struts.actions.LocaleAction"  name="localeForm" scope="request"&gt;&lt;/action&gt;</pre>
<p>在不同的locale下我们得到了如下的两个结果：</p>
<pre>在locale为zh时的结果：Resources_zh.properties.Resources.properties.在locale为en时的结果：	Resources_en.properties.Resources.properties.</pre>
<p>让我们来看一下在locale为zh时如何得到的是上面的结果。因为locale为zh所以&lt;bean:message key="from"/&gt;&lt;br/&gt;先找Resources_zh.properties这个文件从中得到form键的值。而&lt;bean:message key="resource"/&gt;&lt;br/&gt;也会先找Resources_zh.properties这个文件但这次没有找到resource键，这时Struts会到Resources.properties这个文件中找，很幸运这里找到了。如果还没有找到，或message resource文件不存在就会抛出异常。当locale为en时类似，您可以自己试试。 </p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e235>bean:page</a></div>
<p>bean:page标签将页上下文中的application、config、request、response 或 session取出，然后用id属性值将它们绑定到page作用域中(这种绑定是为了其它标签能够使用该值)，并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。</p>
<p>下面的代码片段示例了bean:page标签取出response，然后使用bean:write标签将response的characterEncoding和contentType属性输出：</p>
<pre>&lt;bean:page id="res" property="response"/&gt;&lt;!-- 其它标签通过绑定到page作用域中的属性使用该值 --&gt;&lt;bean:write name="res" property="characterEncoding"/&gt;&lt;br/&gt;&lt;bean:write name="res" property="contentType"/&gt;&lt;br/&gt;&lt;!-- JSP脚本通过scripting变量使用该值 --&gt;&lt;%  String characterEncoding = res.getCharacterEncoding();  String contentType = res.getContentType();  out.println(characterEncoding+"&lt;br/&gt;");	  out.println(contentType+"&lt;br/&gt;");	%&gt;</pre>
<p>您可以用和上面类似的代码访问application、config、request 或 session中的任何一个对象。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e253>bean:parameter</a></div>
<p>bean:parameter标签取回请求中的参数值。如果没有指定multiple属性则依据刚取回的值创建一个String类型的bean。如果指定了multiple属性则依据刚取回的值创建一个String[]类型的数组。然后用id属性值将String或String[]绑定到page作用域中(这种绑定是为了其它标签能够使用该值)，并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。</p>
<p>下面的两个代码片段使用相同的url传递参数，url的形式为http://127.0.0.1:8080/struts-demo/parameter.jsp?param=1&amp;param=2&amp;param=3。前面的代码片段中没有指定multiple属性，因此p是String类型而且仅仅读取了参数的第一个值。后面的代码片段中指定了multiple属性的值，因此ps是String[]类型的包含所有参数的值。</p>
<pre>&lt;bean:parameter id="p" name="param"/&gt;&lt;bean:write name="p"/&gt;</pre>
<pre>&lt;bean:parameter id="ps" multiple="true" name="param"/&gt;&lt;logic:iterate id="p" name="ps"&gt;  &lt;bean:write name="p"/&gt;&lt;br/&gt;&lt;/logic:iterate&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e271>bean:resource</a></div>
<p>bean:resource标签取回指定的web应用程序的资源，以InputStream或String的形式保存到page作用域中并且创建scripting变量。采用什么形式取决于标签的input属性，如果指定input则以InputStream的形式保存，如果没有指定input则以String的形式保存。</p>
<p>下面的两个代码片段示例了bean:resource标签，其中resource.txt是要使用的资源文件。前面的代码片段中没有指定input属性，因此以String的形式处理资源文件，bean:write标签输出资源文件的内容。后面的代码片段中指定了input属性的值，因此以InputStream的形式使用资源文件，两个bean:write标签分别输出InputStream对象的实例名(如java.io.ByteArrayInputStream@16dadf9)和类名(如class java.io.ByteArrayInputStream)。 </p>
<pre>&lt;bean:resource id="str" name="/resource.txt"/&gt;&lt;!-- 其它标签通过绑定到page作用域中的属性使用该值 --&gt;&lt;bean:write name="str"/&gt;&lt;br/&gt;&lt;!-- JSP脚本通过scripting变量使用该值 --&gt;&lt;%  out.println(str+"&lt;br/&gt;");%&gt;</pre>
<pre>&lt;bean:resource id="is" input="true" name="/resource.txt"/&gt;&lt;!-- 其它标签通过绑定到page作用域中的属性使用该值 --&gt;&lt;bean:write name="is"/&gt;&lt;br/&gt;&lt;bean:write name="is" property="class"/&gt;&lt;!-- JSP脚本通过scripting变量使用该值 --&gt;&lt;%  out.println(is+"&lt;br/&gt;");  out.println(is.getClass()+"&lt;br/&gt;");%&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e290>bean:size</a></div>
<p>bean:size标签创建一个java.lang.Integer类型的bean，这个bean的值为该标签指定的Collection或Map中所含元素的个数。 这可以和logic:iterate标签配合使用，因为logic:iterate标签不能得到所叠代的集合的元素的个数，这有时候很不方便。 </p>
<p>下面的代码片段示例了bean:size标签取出persons中还有元素的个数，其中listForm和persons的定义参见bean:define标签部分：</p>
<pre>&lt;logic:notEmpty name="listForm" property = "persons"&gt;		  &lt;bean:size id="size" name="listForm" property = "persons"/&gt;  &lt;bean:write name="size"/&gt;		&lt;/logic:notEmpty&gt;  </pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e305>bean:struts</a></div>
<p>bean:struts标签取回Struts的内部对象formBean、forward或mapping的值，然后用id绑定到page作用域中(这种绑定是为了其它标签能够使用该值)，并创建对应的scripting变量(这种变量是为了JSP脚本能够使用该值)。</p>
<p>下面的代码片段示例了bean:struts标签取出listForm对象，让我们先来看一下listForm的定义在读代码：</p>
<pre>&lt;!-- listForm的定义&lt;form-bean name="listForm"   type="org.solo.struts.form.ListForm" /&gt; --&gt;&lt;bean:struts id="listFormBean" formBean="listForm"/&gt;name:&lt;bean:write name="listFormBean" property="name"/&gt;&lt;br/&gt;type:&lt;bean:write name="listFormBean" property="type"/&gt;&lt;br/&gt;dynamic:&lt;bean:write name="listFormBean" property="dynamic"/&gt;&lt;br/&gt;</pre>
<p>上面代码运行的结果为：</p>
<pre>name:listForm type:org.solo.struts.form.ListFormdynamic:false </pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e326>bean:write</a></div>
<p>bean:write标签将指定的bean的属性值写到当前的JspWriter中，并且可以对输出进行格式化。</p>
<p>下面的代码片段示例了bean:write标签输出User-Agent：</p>
<pre>&lt;logic:present header="User-Agent"&gt;  &lt;bean:header id="header" name="User-Agent"/&gt;  &lt;bean:write name="header"/&gt;&lt;/logic:present&gt;</pre>
<p>下面的代码片段示例了bean:write标签格式化输出当前日期，其中now是在DataForm中定义的一个java.util.Date类型的域(值为new Date())，format.date.standard是在资源文件中的一个键(format.date.standard=yyyy-MM-dd)：</p>
<pre>&lt;bean:define id="date" name="dataForm" property="now"/&gt;&lt;br/&gt;&lt;bean:write name="date"/&gt;&lt;br/&gt;&lt;bean:write name="date" format="MM/dd/yyyy"/&gt;&lt;br/&gt;&lt;bean:write name="date" formatKey="format.date.standard"/&gt;</pre>
<p>上面代码运行的结果为：</p>
<pre>Sun Jun 04 17:04:05 CST 200606/04/20062006-06-04</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e355>html:base</a></div>
<p>虽然这里的标题是html:base标签，但是这里也是这篇指南要介绍的第一个Struts html标签。因此我想在这里从整体上简单的介绍一下，最后给出一个对照表。其中的绝大多数标签就不一一介绍了，要介绍的也不会在这里介绍，而是将其独立出来以显重要性。</p>
<p>从用户处收集数据是动态web应用非常重要的一个方面，因此构建输入表单也就自然而然的成为struts框架的一个重要内容。Struts html标签库含有创建Struts输入表单的标签，和其它标签库(bean、logic、nested和tiles)中的标签一起协作就可以产生基于html的用户界面。</p>
<p>下面的对照表会使您对Struts html标签库有一个整体的印象：</p>
<p>&nbsp;</p>
<div>图示 1. Struts HTML标签和HTML元素对照表</div>
<img height=755 alt="Struts HTML标签和HTML元素对照表" src="http://www.solol.org/technologic/java/j-struts/strutshtmlvshtml.gif" width=679 orig_onmouseover="null" orig_onmouseout="null">
<p>&nbsp;</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e378>html:cancel</a></div>
<p>html:cancel标签生成一个取消按钮。当点击该按钮后action servlet会绕过相应的form bean的validate()方法，同时将控制权交给相应的action。在该action中可以使用Action.isCancelled(HttpServletRequest)方法判断是否被取消了。如果返回true表示这个action被取消了，否则表示这个action没有被取消。</p>
<p>请注意，如果您修改了html:cancel标签的property属性值，那么struts提供的cancel探测机制就失效了，您自己必须提供类似的机制。</p>
<p>下面是可取消的action的配置文件，注意&lt;set-property property="cancellable" value="true"/&gt;这一行，如果不添加Struts会抛出org.apache.struts.action.InvalidCancelException异常。这是我在完成本指南的过程中发现的唯一向下不兼容的地方。</p>
<pre>&lt;action path="/cancel"   type="org.solo.struts.action.CancelAction" name="cancelForm"     scope="request"&gt;  &lt;set-property property="cancellable" value="true"/&gt;  &lt;forward name="success" path="/cancel.jsp" /&gt;&lt;/action&gt;</pre>
<p>下面是html:cancel标签的代码：</p>
<pre>&lt;html:cancel&gt;取消&lt;/html:cancel&gt;</pre>
<p>下面是对应的action中的代码：</p>
<pre>if(isCancelled(request)){			  //action被取消时要做的事情写在这里  return mapping.findForward("cancel");}else{  //action没有被取消时要做的事情写在这里  return mapping.findForward("success");}</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e409>html:select</a></div>
<p>html:select标签生成一个select元素。是单选还是多选取决于该标签的multiple属性。如果指定了multiple="true"则为多选，此时对应的属性应该是一个数组。如果没有指定multiple="true"则为单选，此时对应的属性应该是标量。</p>
<p>注意：为了正确的处理没有做任何的选择的情况，在ActionForm中的reset()方法中必须将标量属性设置为默认值而将数组的长度置为0。</p>
<p>另外的一个重要问题就是struts如何生成option元素了，这个任务struts交给了html:option、html:options和html:optionsCollection三个标签。</p>
<p>html:option标签</p>
<p>html:option标签生成一个HTML的option元素。该标签必须嵌在html:select标签中。它的显示文本来自其标签体，也可以来自于资源文件。它的value属性用来指定什么值将要被提交。</p>
<pre>&lt;html:option value="one"&gt;one&lt;/html:option&gt;&lt;html:option value="two"&gt;two&lt;/html:option&gt;</pre>
<p>html:options标签</p>
<p>html:options标签生成多个HTML的option元素。该标签必须嵌在html:select标签中。而且工作方式有些特殊，它的name与property属性和其它标签的name与property属性意义不一致，让我们具体看一下它的工作方式。</p>
<ul>
    <li>指定collection属性
    <li>没有指定collection属性 </li>
</ul>
<p>指定collection属性</p>
<p>让我通过示例来介绍在指定collection属性时该标签的工作方式，首先要说明selectForm中的persons和listForm中的persons完全一致。请参见bean:define标签。</p>
<p>下面的代码先利用bean:define标签将selectForm中的persons取到page作用域中，然后html:options标签再依据collection="personCollection"选中这个persons并将其中的每一个对象(Person类型)生成一个option元素。该标签的property="id"表示persons中的对象(Person类型)的id属性将作为option元素的value值。该标签的labelProperty="name"表示persons中的对象(Person类型)的name属性将作为option元素的label值。</p>
<p>当这个select提交时所选择的值将被提交到selectForm(name="selectForm")中的person对象(这是在SelectForm中声明的一个Person类型的域专门用来接收提交的值)的id属性中(property="person.id")。</p>
<pre>&lt;bean:define id="personCollection" name="selectForm"   property="persons"/&gt;&lt;html:select name="selectForm" property="person.id" size="1"&gt;  &lt;html:options collection="personCollection" property="id"     labelProperty="name"/&gt; &lt;/html:select&gt;</pre>
<p>没有指定collection属性</p>
<p>让我通过示例来介绍没有指定collection属性时该标签的工作方式，先来看看ids和names的定义：</p>
<pre>  private List&lt;String&gt; ids = null;  private List&lt;String&gt; names = null;</pre>
<p>上面的代码来自SelectForm，其中ids是一个String的列表，names也是一个String的列表。我们暂时假定这两个列表含有相同数目的元素。有了这些让我们开始介绍下面的代码。html:options标签用ids中的第i个值作为option元素的value值同时使用names中相同位置的值(第i个值)作为option元素的label值。如果ids比names长那么多出的ids中的值将即作为option的value又作为option的label。如果ids比names短那么多出的names的值会被丢掉。</p>
<p>当这个select提交时所选择的值将被提交到selectForm(name="selectForm")中的person对象(这是在SelectForm中声明的一个Person类型的域专门用来接收提交的值)的id属性中(property="person.id")。</p>
<pre>&lt;html:select name="selectForm" property="person.id" size="1"&gt;  &lt;html:options property="ids" labelProperty="names"/&gt; &lt;/html:select&gt;</pre>
<p>html:optionsCollection标签</p>
<p>html:optionsCollection标签生成多个HTML的option元素。该标签必须嵌在html:select标签中。它的功能和html:options标签的相同，但是它的name与property属性和其它标签的name与property属性意义一致，理解起来比较自然。</p>
<p>让我通过示例来介绍html:optionsCollection标签的用法。首先依据name="selectForm"和property="persons"取到selectForm中的persons列表，然后将列表中的对象(Person类型)的id属性作为option元素的value值(value="id")，将列表中的对象(Person类型)的name属性作为option元素的label值(label="name")。</p>
<pre>&lt;html:select name="selectForm" property="person.id" size="1"&gt;  &lt;html:optionsCollection name="selectForm" property="persons"   label="name" value="id"/&gt; &lt;/html:select&gt;</pre>
<p>下面是一个多选的示例，虽然示例中使用了html:options标签，但是html:option和html:optionsCollection也能够用来多选。而且您还必须意识到html:option、html:options和html:optionsCollection这三个标签可以同时使用。代码中的personIds是SelectForm中声明的一个String[]类型的数组用来接收提交的多个值。</p>
<pre>&lt;html:select name="selectForm" property="personIds"     multiple="true" size="2"&gt;  &lt;html:options property="ids" labelProperty="names"/&gt; &lt;/html:select&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e504>html:checkbox</a></div>
<p>html:check标签生成一个checkbox。这里的value值可以是true，yes或on。如果您要提交其它的值(如某种形式的标识)应该考虑使用html:multibox标签。</p>
<p>注意:为了正确的处理没有选中的checkbox您必须在reset()中设置对应的属性为false。</p>
<p>下面的代码示例了html:checkbox标签的用法，其中CheckboxForm中声明了三个boolean类型的域，如下：</p>
<pre>              <!-- 略掉了get方法(也可以是isXXX形式)和set方法 -->	  private boolean one = false;  private boolean two = false;  private boolean three = false;</pre>
<pre>&lt;html:checkbox name="checkboxForm" property="one"&gt;  One&lt;/html:checkbox&gt;&lt;html:checkbox name="checkboxForm" property="two"&gt;  Two&lt;/html:checkbox&gt;&lt;html:checkbox name="checkboxForm" property="three"&gt;  Three&lt;/html:checkbox&gt;</pre>
<p>如果选中后被提交则相应的属性的值为true。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e531>html:radio</a></div>
<p>html:radio标签生成一个radio。主要的用法有两种，下面我们通过代码来示例。</p>
<p>下面的代码示例了html:radio标签的一般用法，如果被提交则选中的radio的value值将被提交到radioForm中的id中。</p>
<pre>&lt;html:radio name="radioForm" property="id" value="00001"&gt;  One&lt;/html:radio&gt;&lt;html:radio name="radioForm" property="id" value="00002"&gt;  Two&lt;/html:radio&gt;</pre>
<p>下面的代码示例了html:radio标签的典型用法，其中的persons和bean:define标签中的一致，您可以参考bean:define标签。我只介绍这个&lt;html:radio idName="person" property="id" value="id"&gt;，idName指定html:radio要使用的bean(这里为person)，value="id"表示person的id属性将作为radio元素的value值而property="id"表示提交时选中的radio的值将被提交给radioForm中的id属性。 </p>
<pre>&lt;logic:notEmpty name="radioForm" property="persons"&gt;		  &lt;logic:iterate id="person" name="radioForm" property="persons"&gt;    &lt;html:radio idName="person" property="id" value="id"&gt;      &lt;bean:write name="person" property="name"/&gt;    &lt;/html:radio&gt;   &lt;/logic:iterate&gt;		&lt;/logic:notEmpty&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e552>html:multibox</a></div>
<p>html:multibox标签生成多个checkbox。当您要使用大量的checkbox时使用这个标签非常方便，可以使您避免在ActionForm中声明大量的boolean类型的变量，带之以一个数组就行了。</p>
<p>注意:为了正确的处理没有选中的checkbox您必须在reset()中设置数组的长度为0。</p>
<p>下面的代码示例了html:multibox标签的一般用法，如果被提交则选中的所有checkbox的value值将被提交到multiboxForm中的selectedItems中，这是一个String[]数组。</p>
<pre>&lt;html:multibox name="multiboxForm" property="selectedItems"   value="00001"/&gt;&lt;html:multibox name="multiboxForm" property="selectedItems"   value="00002"/&gt;</pre>
<p>下面的代码示例了html:multibox标签的典型用法：</p>
<pre>&lt;logic:iterate id="person" name="multiboxForm" property="persons"&gt;   &lt;html:multibox property="selectedItems"&gt;    &lt;bean:write name="person" property="id"/&gt;  &lt;/html:multibox&gt;   &lt;bean:write name="person" property="name"/&gt; &lt;/logic:iterate&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e578>html:link</a></div>
<p>html:link标签生成一个锚点(&lt;a&gt;)元素。我从html:link标签如何构造基本url和如何构造query参数两个方面来介绍这个标签。</p>
<p>构造基本url是依据该标签的如下四个属性进行的，这四个属性一次只能出现一个。让我们看看它们： </p>
<ul>
    <li>forward，指定一个全局ActionForward的名称。另外如果forward是module相关的则该forward必须指向一个action而不能是一个页面。
    <li>action，指定一个Action的名称。
    <li>href，struts会直接使用这个值而不会对其进行任何处理。
    <li>page，指定一个页面的路径，必须以/开始。 </li>
</ul>
<p>&nbsp;</p>
<p>构造query参数，下面列举了可能的形式，其中baseurl只是一个占位符： </p>
<ul>
    <li>baseurl?p=00001(单参单值)
    <li>baseurl?p1=00001&amp;p2=00002&amp;p3=00003(多参单值)
    <li>baseurl?p=00001&amp;p=00002&amp;p=00003(单参多值)
    <li>baseurl?p1=00001&amp;p2=00002&amp;p=00001&amp;p=00002&amp;p=00003(混合) </li>
</ul>
<p>&nbsp;</p>
<p>下面我们以代码示例来说明每一种html:link的用法，首先让我们花点时间看看相关action中的代码：</p>
<pre>&lt;!-- 下面所有代码的数据都是在这里构造的 --&gt;public ActionForward execute(ActionMapping mapping,ActionForm form,    HttpServletRequest request,HttpServletResponse response) {  DataForm dataForm = (DataForm) form;  dataForm.setParam("00001");  HashMap paramSingleMap = new HashMap();  paramSingleMap.put("p1","00001");  paramSingleMap.put("p2","00002");  paramSingleMap.put("p3","00003");		  dataForm.setParamSingleMap(paramSingleMap);  HashMap paramMultiMap = new HashMap();  paramMultiMap.put("p",new String[]{"00001","00002","00003"});		  dataForm.setParamMultiMap(paramMultiMap);  HashMap paramSMMap = new HashMap();  paramSMMap.put("p1","00001");  paramSMMap.put("p2","00002");  paramSMMap.put("p",new String[]{"00001","00002","00003"});		  dataForm.setParamSMMap(paramSMMap);  List&lt;Person&gt; persons = new ArrayList&lt;Person&gt;();		  Person person1 = new Person();  person1.setId("00001");  person1.setName("赵辰");		  Person person2 = new Person();  person2.setId("00002");  person2.setName("李为芳");		  Person person3 = new Person();  person3.setId("00003");  person3.setName("王微");		  persons.add(person1);  persons.add(person2);  persons.add(person3);		  dataForm.setPersons(persons);  return mapping.findForward("success");}</pre>
<pre>&lt;!-- 这用来设置一个位置 --&gt;&lt;html:link linkName="top"/&gt;&lt;!-- 这用来定位到上面的那个位置 --&gt;&lt;html:link page="/link.do" anchor="top"&gt;Go Top&lt;/html:link&gt;</pre>
<pre>&lt;html:link page="/link.do" paramId="p" paramName="dataForm"     paramProperty="param"&gt;  单参单值&lt;/html:link&gt;&lt;br/&gt;&lt;html:link page="/link.do" name="dataForm" property="paramSingleMap"&gt;  多参单值&lt;/html:link&gt;&lt;br/&gt;&lt;html:link page="/link.do" name="dataForm" property="paramMultiMap"&gt;  单参多值&lt;/html:link&gt;&lt;br/&gt;&lt;html:link page="/link.do" name="dataForm" property="paramSMMap"&gt;  混合&lt;/html:link&gt;</pre>
<p>下面的代码示例了html:link标签的indexed属性和indexId属性的用法，这两个属性只有html:link标签嵌套在logic:iterate标签中时才可用。</p>
<pre>&lt;logic:iterate id="person" name="dataForm" property="persons"&gt;  &lt;html:link action="/link.do" paramId="person" paramName="person" 	  paramProperty="id" indexed="true" indexId="number"&gt;    person  &lt;/html:link&gt;  &lt;br/&gt;&lt;/logic:iterate&gt;&lt;!-- 下面是上面代码的运行结果(产生的html)  &lt;a href="/struts-demo/link.do?person=00001&amp;number=0"&gt;赵辰&lt;/a&gt;&lt;br/&gt;  &lt;a href="/struts-demo/link.do?person=00002&amp;number=1"&gt;李为芳&lt;/a&gt;&lt;br/&gt;  &lt;a href="/struts-demo/link.do?person=00003&amp;number=2"&gt;王微&lt;/a&gt;&lt;br/&gt;   其中的number是由indexId="number"确定的，而该参数的值为元素在集合中的位置。--&gt;</pre>
<p>html:rewrite标签和html:link标签类似只是不生成锚点(&lt;a&gt;)，而是简单的输出字符串。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e645>html:errors</a></div>
<p>html:errors标签和html:messages标签的功能相似，所以我们放到一起来介绍。</p>
<p>html:errors标签将由name属性指定的ActionMessages、ActionErrors、String和String[]直接输出到页面中。</p>
<p>html:messages标签将用由name属性(注意message属性值对它的影响)指定的ActionMessages、ActionErrors、String和String[]创建一个新的属性和scripting变量，使用id属性值作为名称。</p>
<p>html:errors标签和html:messages标签的property属性是用来为errors和messages分类的。我们可以给这两个标签指定property属性，以便只显示某一类的错误或消息。</p>
<p>在资源文件增加了如下的内容：</p>
<pre># -- standard errors --errors.header=&lt;ul&gt;errors.prefix=&lt;li&gt;errors.suffix=&lt;/li&gt;errors.footer=&lt;/ul&gt;error=error with none value .error1=error1 with one value is {0} .error2=error2 with two values are {0} , {1} .error3=error3 with three values are {0} , {1} , {2} .error4=error4 with four values are {0} , {1} , {2} ,{3} .</pre>
<p>下面的代码示例了actionErrors的构造：</p>
<pre>public ActionErrors validate(ActionMapping mapping,     HttpServletRequest request) {  ActionErrors actionErrors = new ActionErrors();  actionErrors.add("property1",  new ActionMessage("error"));  actionErrors.add("property2",  new ActionMessage("error1","value0"));  actionErrors.add("property2",  new ActionMessage("error2","value0","value1"));  actionErrors.add("property3",  new ActionMessage("error3","value0","value1","value2"));  actionErrors.add("property3",  new ActionMessage("error4","value0","value1","value2","value3"));  actionErrors.add("property4",  new ActionMessage("error1",new Object[]{"value0"}));  actionErrors.add("property4",  new ActionMessage("error2",new Object[]{"value0","value1"}));  actionErrors.add("property4",  new ActionMessage("error3",new Object[]{"value0","value1",    "value2"}));  actionErrors.add("property5",  new ActionMessage("error4",new Object[]{"value0","value1",    "value2","value3"}));  actionErrors.add("notBundle",  new ActionMessage("not a bundle key",false));  return actionErrors;}	</pre>
<p>errors标签代码示例：</p>
<pre>&lt;html:errors/&gt;&lt;br/&gt;	&lt;html:errors property="property4"/&gt;</pre>
<p>messages标签代码示例：</p>
<pre>&lt;logic:messagesPresent&gt;  &lt;ul&gt;  &lt;html:messages id="message"&gt;    &lt;li&gt;&lt;bean:write name="message"/&gt;&lt;/li&gt;  &lt;/html:messages&gt;  &lt;/ul&gt;&lt;/logic:messagesPresent&gt;&lt;br/&gt;&lt;logic:messagesPresent&gt;  &lt;ul&gt;  &lt;html:messages id="message" property="property4"&gt;    &lt;li&gt;&lt;bean:write name="message"/&gt;&lt;/li&gt;  &lt;/html:messages&gt;&lt;/ul&gt;&lt;/logic:messagesPresent&gt;</pre>
<p>&nbsp;</p>
<div>图示 2. 上面的两段代码示例运行结果相同，如下所示：</div>
<img height=368 alt=运行结果 src="http://www.solol.org/technologic/java/j-struts/errorsmessages.gif" width=553 orig_onmouseover="null" orig_onmouseout="null">
<p>&nbsp;</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e697>html:javascript</a></div>
<p>html:javascript标签生成用于校验的javascript脚本代码。</p>
<p>下面的代码片段示例了html:javascript标签的基本用法，其中formName属性的值是在validation.xml文件的&lt;formset&gt;中定义的form的名称。有一点值得注意的是在确定&lt;formset&gt;时要使用合适的language属性值。</p>
<pre>&lt;html:javascript formName="dataForm"/&gt;</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e713>html:xhtml</a></div>
<p>html:xhtml标签在页面中一出现就是告诉该页的所有其它的Struts html标签以XHTML1.0兼容的形式输出。这和将html:html标签的xhtml属性值指定为true有些类似。如果上述情况都没有出现，Struts html标签将以html4.01兼容的形式输出。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e722>logic:iterate</a></div>
<p>logic:iterate标签用来迭代集合，您可以使用如下方式来为这个标签指定其要叠代的集合：</p>
<ul>
    <li>使用一个运行时表达式，这个表达式的值是一个集合。
    <li>用name属性引用一个JSP Bean，这个JSP Bean本身就是一个集合。
    <li>用name属性引用一个JSP Bean，这个JSP Bean的一个属性是一个集合，这时可以联合使用property来指定这个集合。 </li>
</ul>
<p>上面所提到的集合可以是：</p>
<ul>
    <li>对象类型或原子类型的数组(Array)。
    <li>java.util.Collection的实现，包括ArrayList，Vector。
    <li>java.util.Enumeration的实现。
    <li>java.util.Iterator的实现。
    <li>java.util.Map的实现，包括HashMap，Hashtable和TreeMap。 </li>
</ul>
<p>如果您叠代的集合中含有null的值，这时需要采取一定的措施，因为这时logic:iterate不会在page作用域中创建对象。一般是使用&lt;logic:present&gt;标签或&lt;logic:notPresent&gt;标签来判断一下。</p>
<p>下面是logic:iterate叠代ArrayList的示例的对象引用关系和部分代码：</p>
<p>&nbsp;</p>
<div>图示 3. logic:iterate中对象的引用关系</div>
<img height=258 alt=logic:iterate中对象的引用关系 src="http://www.solol.org/technologic/java/j-struts/iterate.gif" width=614 orig_onmouseover="null" orig_onmouseout="null">
<p>&nbsp;</p>
<p>图中的persons列表是在ListAction中填充的，在这里只是简单的加入了三个Person对象，在实际的应用中这些数据应该取自数据库。具体的代码如下：</p>
<pre>public ActionForward execute(ActionMapping mapping,ActionForm form,    HttpServletRequest request,	HttpServletResponse response) {  ListForm listForm = (ListForm) form;	  List&lt;Person&gt; persons = new ArrayList&lt;Person&gt;();	  Person person1 = new Person();  person1.setId("00001");  person1.setName("赵辰");	  Person person2 = new Person();  person2.setId("00002");  person2.setName("李为芳");	  Person person3 = new Person();  person3.setId("00003");  person3.setName("王微");	  persons.add(person1);  persons.add(person2);  persons.add(person3);	  listForm.setPersons(persons);	  return mapping.findForward("success");}</pre>
<p>标签输出的结果为：</p>
<pre>00001--&gt;赵辰 00002--&gt;李为芳 00003--&gt;王微</pre>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e791>logic:present</a></div>
<p>如果指定的值出现该标签就会创建其标签体内的内容。该标签用于以下情况：</p>
<ul>
    <li>检查具有指定名称的cookie是否出现。
    <li>检查具有指定名称的header是否出现。
    <li>检查具有指定名称的JSP Bean是否出现 或 检查具有指定名称的JSP Bean中的property属性是否出现。
    <li>检查request中指定名称的参数是否出现。
    <li>检查当前的认证用户是否与指定的安全角色相关联。
    <li>检查当前认证的主体是否具有指定的名字。 </li>
</ul>
<p>下面的代码示例了logic:present标签检查具有指定名称User-Agent的header是否出现：</p>
<pre>&lt;logic:present header="User-Agent"&gt;  您的浏览器是&lt;bean:header id="userAgent" name="User-Agent"/&gt;    &lt;bean:write name="userAgent"/&gt;。&lt;br/&gt;&lt;/logic:present&gt;</pre>
<p>logic:notPresent标签的应用正好和logic:present标签相反。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e832>logic:messagesPresent</a></div>
<p>logic:messagesPresent标签用于以下情况：</p>
<ul>
    <li>在request作用域中存在一个ActionMessages对象，标签的property属性和ActionMessages中的property对应。
    <li>在request作用域中存在一个ActionErrors对象，标签的property属性和ActionErrors中的property对应。
    <li>存在一个String对象，将其转换(构造)成ActionMessage然后在添加到ActionMessages中。
    <li>存在一个String Array对象，将数组中的每一个String转换成一个ActionMessage，在将其添加到ActionMessages中。 </li>
</ul>
<p>标签的message属性值为true时将以Globals.MESSAGE_KEY为key在request作用域中查找Message，其它情况下，将name的值作为key查找，如果name 没有出现，默认值为Globals.ERROR_KEY。 </p>
<p>下面的代码示例了logic:messagesPresent标签的典型用法：</p>
<pre>&lt;logic:messagesPresent&gt;  &lt;ul&gt;  &lt;html:messages id="message"&gt;    &lt;li&gt;&lt;bean:write name="message"/&gt;&lt;/li&gt;  &lt;/html:messages&gt;  &lt;/ul&gt;&lt;/logic:messagesPresent&gt;	</pre>
<p>标签logic:messagesNotPresent的应用正好和logic:messagesPresent的应用相反。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e869>logic:empty</a></div>
<p>logic:empty标签是用来判断是否为空的。如果为空，该标签体中嵌入的内容就会被处理。该标签用于以下情况：</p>
<ul>
    <li>当Java对象为null时
    <li>当String对象为""时
    <li>当java.util.Collection对象中的isEmpty()返回true时
    <li>当java.util.Map对象中的isEmpty()返回true时 </li>
</ul>
<p>下面的代码示例了logic:empty标签判断集合persons是否为空：</p>
<pre>&lt;logic:empty name="listForm" property = "persons"&gt;  &lt;div&gt;集合persons为空!&lt;/div&gt;			&lt;/logic:empty&gt; 	</pre>
<p>logic:notEmpty标签的应用正好和logic:empty标签相反。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e902>logic:match</a></div>
<p>logic:match标签用来处理子串匹配问题。</p>
<p>如果指定的值匹配该标签就会创建其标签体内的内容。该标签用于以下情况： </p>
<ul>
    <li>检查具有指定名称的cookie是否与该标签的value匹配。
    <li>检查具有指定名称的header是否与该标签的value匹配。
    <li>检查具有指定名称的JSP Bean是否与该标签的value匹配 或 检查具有指定名称的JSP Bean中的property属性值是否与该标签的value匹配。
    <li>检查request中指定名称的参数值是否与该标签的value匹配。 </li>
</ul>
<p>&nbsp;</p>
<p>下面的代码示例了logic:match标签的典型用法：</p>
<pre>&lt;logic:present header="User-Agent"&gt;  &lt;logic:match header="User-Agent" value="MSIE 6.0"&gt;    MS IE 6.0  &lt;/logic:match&gt;&lt;/logic:present&gt; 	</pre>
<p>logic:notMatch标签的应用正好和logic:match标签相反。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e939>logic:equal</a></div>
<p>这里要介绍的不只是logic:equal(=)标签，而是要介绍一类标签，这类标签完成比较运算，包括：</p>
<ul>
    <li>logic:equal(=)
    <li>logic:notEqual(!=)
    <li>logic:greaterEqual(&gt;=)
    <li>logic:lessEqual(&lt;=)
    <li>logic:graterThan(&gt;)
    <li>logic:lessThan(&lt;) </li>
</ul>
<p>该类标签的用法类似，我们只介绍logic:equal标签，其它的留给您自己去完成。</p>
<p>logic:equal是用来判断是否相等的。如果相等，该标签体中嵌入的内容就会被处理。该标签用于以下情况：</p>
<ul>
    <li>比较由该标签的cookie属性指定的cookie的值是否与该标签的value属性值相等。
    <li>比较由该标签的header属性指定的header的值是否与该标签的value属性值相等。
    <li>比较由该标签的name属性指定的JSP Bean是否与该标签的value属性值相等(property属性不出现)或比较由该标签的name属性指定的JSP Bean中的property属性值是否与该标签的value属性值相等。
    <li>比较由该标签的parameter属性指定的参数值(request中)是否与该标签的value属性值相等。 </li>
</ul>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e991>logic:forward</a></div>
<p>我觉得将forward和redirect这两个动作放到一起对比着介绍更加有利于理解，基于此原因也就将logic:forward和logic:redirect这两个标签也拿到这里一起介绍了。</p>
<p>让我们看看这两个动作的区别： </p>
<ul>
    <li>forward是在servlet内部执行，浏览器完全不会感知到这个动作，原始的url也不会改变，浏览器重新装载的话也只是对原始的请求进行简单的重复。
    <li>redirect则分成两个步骤：第一步是web应用程序告诉浏览器第二个url，然后浏览器向第二个url发送请求。 </li>
</ul>
<p>&nbsp;</p>
<p>redirect比forward慢，因为浏览器要做二次请求。还有就是要注意，在第一次的请求作用域(request作用域)内的bean对于第二次请求是不可见的。</p>
<p>理解了上面描述的区别也就知道了什么时候该选用logic:forward标签什么时候该选用logic:redirect标签了。logic:forward标签完成PageContext.forward()或HttpServletResponse.sendRedirect()，如何选择由控制器决定。logic:redirect标签完成HttpServletResponse.sendRedirect()。</p>
<p>在使用logic:redirect标签时我们可以向使用html:link一样构造baseurl和query参数。如果您感兴趣可以参考html:link标签。</p>
<div class=go-top>
<hr>
<a title=回页首 href="http://www.solol.org/technologic/java/j-struts/#top">回页首</a></div>
<div class=heading-major><a name=d3e1021>总结</a></div>
<p>这篇指南的背景是Struts-1.2.9，其中的所有的代码示例也都是在这个版本下调试通过的。目前Struts仍然在快速的发展中，但是从开发者应用的角度来讲还是比较稳定的。因此我有理由相信其中的代码示例也可以很好的运行在其它的版本之上。最后希望这篇指南能够让您心情愉快！</p>
<div class=resources><a name=resource>参考资料</a>
<ul>
    <li><a href="http://struts.apache.org/struts-doc-1.2.9/index.html">Struts的官方文档</a>
    <li><a href="http://struts.apache.org/struts-doc-1.2.9/userGuide/index.html">Struts的用户指南</a>
    <li><a href="http://wp.netscape.com/newsref/std/cookie_spec.html">cookie spec</a>，这是关于Cookie最的全面的说明。
    <li><a href="http://www.w3.org/TR/html4/index/elements.html">HTML元素</a> </li>
</ul>
</div>
<div class=authors>
<div class=author-heading><a name=author>关于作者</a></div>
<a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#115;&#111;&#108;&#111;&#95;&#108;&#64;&#101;&#121;&#111;&#117;&#46;&#99;&#111;&#109;&#63;&#99;&#99;&#61;&#115;&#111;&#108;&#111;&#46;&#108;&#32;&#97;&#116;&#32;&#104;&#111;&#116;&#109;&#97;&#105;&#108;&#46;&#99;&#111;&#109;">solo L</a> 一位有些理想主义的软件工程师，创建了<a href="http://www.solol.org/">solol.org</a>。他常常在<a href="http://www.solol.org/blogs/solol.html">这里</a>发表一些对技术的见解。&nbsp;</div>
<img src ="http://www.blogjava.net/franlk/aggbug/137491.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-08-17 11:25 <a href="http://www.blogjava.net/franlk/articles/137491.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]表单中"post"与"get"的区别</title><link>http://www.blogjava.net/franlk/articles/132588.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 26 Jul 2007 09:17:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/132588.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/132588.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/132588.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/132588.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/132588.html</trackback:ping><description><![CDATA[<br>摘录地址:http://www.mypm.net/blog/user1/wanghuifen/archives/2007/15900.html<br><br>Get：是以实体的方式得到由请求URI所指定资源的信息，如果请求URI只是一个数据产生过程，那么最终要在响应实体中返回的是处理过程的结果所指向的资源，而不是处理过程的描述。 <br><br>Post：用来向目的服务器发出请求，要求它接受被附在请求后的实体，并把它当作请求队列中请求URI所指定资源的附加新子项，Post被设计成用统一的方法实现下列功能： <br>1：对现有资源的解释 <br>2：向电子公告栏、新闻组、邮件列表或类似讨论组发信息。 <br>3：提交数据块 <br>4：通过附加操作来扩展数据库 <br><br>从上面描述可以看出，Get是向服务器发索取数据的一种请求；而Post是向服务器提交数据的一种请求，要提交的数据位于信息头后面的实体中。很理论化，但是很标准，method=&#8220;get&#8221;并不是从服务器上获取数据，get和post 只是发送机制不同，并不是一个取一个发！get方法会在IE地址栏里显示表示你提交时候所带的值；post方法不会 <br>-------------------------------------------------------------------------------- <br>1、 get是把参数数据队列加到提交表单的ACTION属性所指的URL中，值和表单内各个字段一一对应，在URL中可以看到。post是通过HTTP post机制，将表单内各个字段与其内容放置在HTML HEADER内一起传送到ACTION属性所指的URL地址。用户看不到这个过程。 <br><br>2、对于get方式，服务器端用Request.QueryString获取变量的值，对于post方式，服务器端用Request.Form获取提交的数据。两种方式的参数都可以用Request来获得。 <br><br>3、get传送的数据量较小，不能大于2KB。post传送的数据量较大，一般被默认为不受限制。但理论上，IIS4中最大量为80KB，IIS5中为100KB。 <br><br>4、get安全性非常低，post安全性较高。 <br><br>5、 &lt;form method="get" action="a.asp?b=b"&gt;跟&lt;form method="get" action="a.asp"&gt;是一样的，也就是说，action页面后边带的参数列表会被忽视；而&lt;form method="post" action="a.asp?b=b"&gt;跟&lt;form method="post" action="a.asp"&gt;是不一样的。 <br><br>另外，Get请求有如下特性：它会将数据添加到URL中，通过这种方式传递到服务器，通常利用一个问号？代表URL地址的结尾与数据参数的开端，后面的参数每一个数据参数以&#8220;名称=值&#8221;的形式出现，参数与参数之间利用一个连接符&amp;来区分。 <br>Post请求有如下特性：数据是放在HTTP主体中的，其组织方式不只一种，有&amp;连接方式，也有分割符方式，可隐藏参数，传递大批数据，比较方便。 <br><br><br>-------------------------------------------------------------------------------- <br><br>post 地址栏不会出现一大串?bjnghfgreygt这样的东西 <br>如果是get，就会出现了 <br>1、Get 方法通过 URL 请求来传递用户的数据，将表单内各字段名称与其内容，以成对的字符串连接，置于 action 属性所指程序的 url 后，如<a href="http://www.mdm.com/test.asp?name=asd&amp;password=sad" target=_blank>http://www.mdm.com/test.asp?name=asd&amp;password=sad</a>，数据都会直接显示在 url 上，就像用户点击一个链接一样；Post 方法通过 HTTP post 机制，将表单内各字段名称与其内容放置在 HTML 表头(header)内一起传送给服务器端交由 action 属性能所指的程序处理，该程序会通过标准输入(stdin)方式，将表单的数据读出并加以处理 <br>2、 Get 方式需要使用 Request.QueryString 来取得变量的值；而 Post 方式通过 Request.Form 来访问提交的内容 <br>3、Get 方式传输的数据量非常小，一般限制在 2 KB 左右，但是执行效率却比 Post 方法好；而 Post 方式传递的数据量相对较大，它是等待服务器来读取数据，不过也有字节限制，这是为了避免对服务器用大量数据进行恶意攻击，根据微软方面的说法，微软对用 Request.Form() 可接收的最大数据有限制，IIS 4 中为 80 KB 字节，IIS 5 中为 100 KB 字节 <br>建议：除非你肯定你提交的数据可以一次性提交，否则请尽量用 Post 方法 <br>4、Get 方式提交数据，会带来安全问题，比如一个登陆页面，通过 Get 方式提交数据时，用户名和密码将出现在 URL 上，如果页面可以被缓存或者其他人可以访问客户这台机器，就可以从历史记录获得该用户的帐号和密码，所以表单提交建议使用 Post 方法；Post 方法提交的表单页面常见的问题是，该页面如果刷新的时候，会弹出一个对话框 <br><br>建议：出于安全性考虑，建议最好使用 Post 提交数据
<img src ="http://www.blogjava.net/franlk/aggbug/132588.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-26 17:17 <a href="http://www.blogjava.net/franlk/articles/132588.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]资料系统整理(二)</title><link>http://www.blogjava.net/franlk/articles/132580.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 26 Jul 2007 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/132580.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/132580.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/132580.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/132580.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/132580.html</trackback:ping><description><![CDATA[<br>摘录地址:http://www.programfan.com/club/post-150766.html<br><br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Programming.C#.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows&nbsp;forms&nbsp;programming&nbsp;with&nbsp;c#.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─C_CPP<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A-LIST.Code.Optimization.Effective.Memory.Usage.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Accelerated.C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ANSI-ISO&nbsp;C++.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C&nbsp;Primer&nbsp;Plus&nbsp;5th.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++&nbsp;Complete&nbsp;Reference.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++&nbsp;For&nbsp;Artists.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++&nbsp;In&nbsp;A&nbsp;Nutshell.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++&nbsp;Primer&nbsp;3rd.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++&nbsp;Templates.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++.Coding.Standards.101.Rules.Guidelines.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++.Common.Knowledge.Essential.Intermediate.Programming.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++.Template.Metaprogramming.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;c++03.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++98.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++Primer3.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++_Primer_Plus4th.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++批判.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C++编程思想.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C.Plus.Plus.Common.Knowledge.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C99.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cpp.FAQs.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cpp.Gotchas.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Cryptography.in.C.and.C++-fly.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C_Compilers_Reference.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Dinkum&nbsp;C++&nbsp;Library.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Effective&nbsp;STL.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Efficient_C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Essential&nbsp;C++.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exceptional.C++.Style.40.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Exceptional_C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expert&nbsp;C&nbsp;Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Imperfect&nbsp;C++&nbsp;Practical&nbsp;Solutions&nbsp;for&nbsp;Real-Life&nbsp;Programming.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inside.the&nbsp;C++&nbsp;Object&nbsp;Model.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;More_Exceptional_C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Practical&nbsp;C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Secure&nbsp;Programming&nbsp;Cookbook&nbsp;for&nbsp;C&nbsp;and&nbsp;C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SGISTL.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STL.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STL源码剖析.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TCPL3rd.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;Art&nbsp;of&nbsp;C++.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─DotNET<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NET_Game_Programming_with_DirectX_9_0.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[.NET].Net&nbsp;Framework&nbsp;Essentials&nbsp;Edt2.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─Java<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;21java.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Algorithms.In.Java.Graph.Algorithms.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Annotated&nbsp;Solution&nbsp;Guide&nbsp;for&nbsp;Thinking&nbsp;in&nbsp;Java.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ant-The&nbsp;Definitive&nbsp;Guide-pdf.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Ant使用指南.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Beginning&nbsp;Java&nbsp;2,&nbsp;JDK&nbsp;5&nbsp;Editionj.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Beginning.Java.Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Better.Faster.Lighter.Java.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Database&nbsp;Porgramming&nbsp;With&nbsp;Jdbc&nbsp;And&nbsp;Java&nbsp;2nd&nbsp;Edition.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expert&nbsp;one&nbsp;on&nbsp;one&nbsp;J2EE&nbsp;development&nbsp;without&nbsp;EJB.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Getting&nbsp;Started&nbsp;with&nbsp;Jboss4.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inside&nbsp;Java&nbsp;Virtual&nbsp;Machine.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inside&nbsp;SWT&nbsp;(The&nbsp;Eclipse&nbsp;Standard&nbsp;Widget&nbsp;Toolkit).pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;J2EE&nbsp;Tutorial中文版.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;J2EE-WEB.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;J2EE.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;J2ME&nbsp;in&nbsp;a&nbsp;Nutshell.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;J2ME.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j2se&nbsp;doc&nbsp;中文版.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;&amp;&nbsp;XML&nbsp;Data&nbsp;Binding.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;2&nbsp;Bible&nbsp;Enterprise&nbsp;Edition.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;2&nbsp;Primer&nbsp;Plus.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;2D&nbsp;Graphics.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Developing&nbsp;with&nbsp;J2ME.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Network&nbsp;Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Swing.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Swing2nd.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Threads&nbsp;2nd.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Threads&nbsp;Third&nbsp;Edition.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java&nbsp;Tools&nbsp;for&nbsp;Extreme&nbsp;Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.3d&nbsp;Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.All-In-One.Desk.Reference.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.and.XML.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Examples.In.A.Nutshell.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Frameworks&nbsp;And&nbsp;Components&nbsp;Accelerate&nbsp;Your&nbsp;Web&nbsp;Application&nbsp;Development.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.in.60.Minutes.a.Day.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Network.Programming.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.server&nbsp;Pages.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Server.Pages.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Servlet&nbsp;Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Servlet.And.JSP.Cookbook.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java.Tutorial.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java2参考大全.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;java3d.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;javascript10.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Javascript教程.exe<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JavaServer.Pages.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JavaTutorial.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java_api.hlp<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java正则表达式.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java经典代码.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Java联想（中文）.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jdk140文档.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jdt.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSP.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSP.pdf<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSP2_0技术手册.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Making&nbsp;Sense&nbsp;of&nbsp;XML,&nbsp;SOAP,&nbsp;WSDL&nbsp;and&nbsp;UDDI.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MySQL.and.Java.Developers.Guide.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Pro.JSP.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Programming&nbsp;for&nbsp;the&nbsp;Java&nbsp;Virtual&nbsp;Machine&nbsp;(1999,&nbsp;Addison&nbsp;Wesley).chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sunchinese.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;J2EE&nbsp;Tutorial.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The&nbsp;Struts&nbsp;Framework.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Think&nbsp;in&nbsp;Java&nbsp;中文版.PDF<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;实用J2EE设计模式编程指南.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;水木精华.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;精通swing程序设计.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─WEB<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;ASP.NET&nbsp;Server&nbsp;Controls&nbsp;And&nbsp;Components.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;ASP.NET.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;ASP.NET中文手册.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;ASP.NET高级编程实例.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;CGI技术全面接触.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;CSS.Cascading.Style.Sheets.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;CSS2中文手册.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;html基础教程.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;MySQL&nbsp;Manual.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Perl-CGI.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;PHP.5.Unleashed.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;PHP.MySQL.Programming.For.The.Absolute.Beginner.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;PHP.Programming.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;SQL.In.A.Nutshell.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Teach.Yourself.PHP.MySQL.And.Apache.In.24Hours.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;unix_orelly_perl.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Writing&nbsp;Apache&nbsp;Modules&nbsp;with&nbsp;Perl&nbsp;and&nbsp;C.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;XML.For.Dummies.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;XML.In.21.Days.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;├─PERL编程24学时教程<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;├─php5&nbsp;和&nbsp;mysql&nbsp;圣经(pdf)<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;John.Wiley.and.Sons.PHP5.and.MySQL.Bible.eBook.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;├─XML&nbsp;高级编程<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;└─XML编程技术大全<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─Win32<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Developing&nbsp;International&nbsp;Software&nbsp;(2nd).chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;EssntialCOM.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;FAT&nbsp;file&nbsp;system&nbsp;specification&nbsp;中文版.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;International&nbsp;Programming&nbsp;for&nbsp;Microsoft&nbsp;Windows&nbsp;(1st).chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;OpenGL三维图形程序设计.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Programming&nbsp;the&nbsp;Microsoft&nbsp;Windows&nbsp;Driver&nbsp;Model(2nd).chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;programmingwindows.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;vbapi函数手册.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Visual&nbsp;C++实践与提高_COM和COM+篇.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Visual&nbsp;C++网络教程.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;WIN32API.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Windows&nbsp;System&nbsp;Programming&nbsp;3rd&nbsp;Edition.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Windows界面下的网络编程.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Winsock规范及应用.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;深入理解COM+.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;├─windows网络编程<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Network&nbsp;Programming&nbsp;for&nbsp;Microsoft&nbsp;Windows&nbsp;2nd.CHM<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;├─WINDOWS网络编程技术<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;├─深入浅出&nbsp;MFC<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;└─驱动开发<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;VC++_NET开发驱动程序详解.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Win2000&nbsp;驱动程序设计.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows&nbsp;2000_XP&nbsp;WDM设备驱动程序开发.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows&nbsp;VxD与设备驱动程序权威指南.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows&nbsp;设备驱动程序技术内幕.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows&nbsp;设备驱动程序（VxD与WDM）开发实务.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows2000设备驱动程序设计指南.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows2000驱动程序设计指南.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WindowsWDM设备驱动程序开发指南.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Windows环境下的设备驱动程序设计.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;虚拟设备驱动程序开发起步与进阶.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;└─程序点滴<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;code_reading.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;DebugginApplications.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Debugging&nbsp;with&nbsp;GDB--the&nbsp;GNU&nbsp;Source-Level&nbsp;Debugger.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Generic&nbsp;Programming&nbsp;And&nbsp;Design&nbsp;Patterns&nbsp;Applied.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;gnu-make.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Learning&nbsp;GNU&nbsp;Emacs&nbsp;2nd&nbsp;Edition.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Multi-Paradigm&nbsp;Design&nbsp;for&nbsp;C++.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Programming&nbsp;with&nbsp;GNU&nbsp;Software.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;the&nbsp;pragmatic&nbsp;programmer.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Write&nbsp;Secure&nbsp;Code.CHM<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Writing&nbsp;Clean&nbsp;Code.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;人月神话.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;程序员修道.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;编程之道全本.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;设计模式.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─代码大全<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─程序设计实践
<img src ="http://www.blogjava.net/franlk/aggbug/132580.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-26 16:46 <a href="http://www.blogjava.net/franlk/articles/132580.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转载]资料系统整理(一)</title><link>http://www.blogjava.net/franlk/articles/132578.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 26 Jul 2007 08:45:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/132578.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/132578.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/132578.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/132578.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/132578.html</trackback:ping><description><![CDATA[<p><br>摘录地址:http://www.programfan.com/club/post-150766.html<br><br>├─CS<br>│&nbsp;&nbsp;│&nbsp;&nbsp;计算机图形学原理教程.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;计算机系课程.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─人工智能教程<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─数据库<br>│&nbsp;&nbsp;│&nbsp;&nbsp;├─数据库基础教程&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;└─数据库系统实现<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─算法<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;AL&amp;DS&nbsp;in&nbsp;C++.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;C数值算法程序大全.rar<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;diff2.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Introduction&nbsp;To&nbsp;Algorithm.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Mathematics&nbsp;-&nbsp;Fundamental&nbsp;Problems&nbsp;in&nbsp;Algorithmic&nbsp;Algebra.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;图论与算法设计.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;实用算法分析.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;并发程序设计.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;智能优化算法.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;最优化原理和方法.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;神经计算.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;算法.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;算法k-th&nbsp;shortest&nbsp;path.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;组合数学与程序设计.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;计算几何基础知识(英文pdf).pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;递归函数论.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;遗传算法原理及应用.zip<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;遗传算法及其应用.zip<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;├─《应用密码学》书<br>│&nbsp;&nbsp;│&nbsp;&nbsp;├─博弈论<br>│&nbsp;&nbsp;│&nbsp;&nbsp;├─并行计算方法<br>│&nbsp;&nbsp;│&nbsp;&nbsp;├─数据结构算法与应用<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;└─计算几何算法<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─编译原理<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Algorithms.For.Compiler.Design.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;Modern.Compiler.Implementation.in.Java.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;└─编译原理及实践<br>│&nbsp;&nbsp;├─网络<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;TEACH_YOURSELF_TCPIP_IN_14_DAYS.CHM<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;├─计算机网络<br>│&nbsp;&nbsp;│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;│&nbsp;&nbsp;└─计算机网络实用教程<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;└─计算机系统<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;cpu概述.ppt<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Memory&nbsp;Management,&nbsp;Algorithms&nbsp;and&nbsp;Implementation&nbsp;in&nbsp;C&nbsp;&amp;&nbsp;C++.chm<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Programming&nbsp;Embedded&nbsp;Systems&nbsp;in&nbsp;C&nbsp;and&nbsp;C++.chm<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;计算机系统结构.pdf<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;├─分布式系统设计<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;└─微型计算机硬件组成<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>├─Linux<br>│&nbsp;&nbsp;│&nbsp;&nbsp;C++&nbsp;GUI&nbsp;Programming&nbsp;with&nbsp;Qt&nbsp;3.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;GUI.Programming.with.wxWidgets.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;John&nbsp;Lions&nbsp;Unix&nbsp;V6.rar<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Linux&nbsp;Kernel核心中文手册.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Linux程序设计(原书第2版).rar<br>│&nbsp;&nbsp;│&nbsp;&nbsp;LINUX设备驱动程序.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Linux设备驱动程序第三版2.6.rar<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Qt-3.1-Whitepaper.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Qt参考文档qt-3.0.5-doc.rar<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Unix&nbsp;C&nbsp;program.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;Unixhandbook.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;UnixSocketProgrammingFAQ.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;UnixViEditorTutorial.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─IBM&nbsp;Linux<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bridging&nbsp;XPCOM.Bonobo&nbsp;-&nbsp;implementation.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Bridging&nbsp;XPCOM.Bonobo&nbsp;-&nbsp;techniques.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Building&nbsp;KDE&nbsp;themes&nbsp;for&nbsp;Linux.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compiling&nbsp;and&nbsp;installing&nbsp;software&nbsp;from&nbsp;sources.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Compiling&nbsp;the&nbsp;Linux&nbsp;kernel.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Creating&nbsp;dynamic&nbsp;Web&nbsp;sites&nbsp;with&nbsp;PHP&nbsp;and&nbsp;MySQL.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CVS&nbsp;for&nbsp;the&nbsp;developer&nbsp;or&nbsp;amateur.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Fast&nbsp;Web&nbsp;browsing&nbsp;with&nbsp;a&nbsp;caching.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Getting&nbsp;to&nbsp;know&nbsp;GRUB.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Inside&nbsp;the&nbsp;Apache&nbsp;directory&nbsp;structure.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Intro&nbsp;to&nbsp;vi.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux&nbsp;2.4&nbsp;stateful&nbsp;firewall&nbsp;design.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Rebol&nbsp;scripting&nbsp;basics.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Using&nbsp;JFS.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Using&nbsp;Perl&nbsp;to&nbsp;access&nbsp;DB2&nbsp;for&nbsp;Linux.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Using&nbsp;regular&nbsp;expressions.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─LINUX与UNIX&nbsp;SHELL编程指南<br>│&nbsp;&nbsp;├─Linux内核源代码情景分析<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─Linux管理员指南<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─LINUX系统管理白皮书<br>│&nbsp;&nbsp;├─LINUX编程白皮书<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─LINUX网站建设技术指南<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─linux英文原版书<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Advanced.Linux.3D.Graphics.Programming.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Advanced.Linux.Networking.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Advanced_Linux_Programming.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Automating_Unix_And_Linux_Administration.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;A_Practical_Guide_To_Linux_Commands_Editors_And_Shell_Programming.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Beginning_Linux_Programming.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Beginning_SUSE_Linux_From_Novice_to_Professional.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Building_Embedded_Linux_Systems.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Building_Secure_Servers_with_Linux.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Classic_Shell_Scripting.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gnu_Linux_Application_Programming.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HUNGRY_MINDS-Debian_Gnu_Linux_Bible.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Learning_GNU_Emacs.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Learning_Red_Hat_Enterprise_Linux_And_Fedora.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Learning_The_Bash_Shell.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Learning_The_UNIX_Operating_System.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Learning_The_VI_Editor.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux.All-in-one.Desk.Reference.for.Dummies.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Application_Development_For_The_Enterprise.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Bible_2005.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_C_Plus_Plus_Programming_HOWTO.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Debugging_and_Performance_Tuning_Tips_and_Techniques.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Enterprise_Cluster.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_in_a_Nutshell.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Kernel_Development.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Programming_Unleashed.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Security_Cookbook.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Linux_Shell_Scripting_With_Bash.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NEW_RIDERS-Inside_Linux.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Optimizing_Linux_Performance_A_Hands_On_Guide_To_Linux_Performance_Tools.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Redhat-Maximum_RPM.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Red_Hat_Fedora4_Unleashed.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Red_Hat_The_Complete_Reference_Enterprise_Linux_Fedora_The_Complete_Reference.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Samba3_by_Example_Practical_Exercises_to_Successful_Deployment.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Slackware.Linux.Essentials.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Slackware.Linux.Unleashed.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SUSE_Linux_9_Bible.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Teach_Yourself_OpenOffice2_Firefox_and_Thunderbird_for_Windows_All_In_One.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Teach_Yourself_Red_Hat_Fedora4_Linux_All_In_One.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The_Linux_Kernel_Primer_A_Top_Down_Approach_For_x86_and_PowerPC_Architectures.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The_Official_Samba3_HOWTO_and_Reference_Guide.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tuning_And_Customizing_A_Linux_System.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Understanding_The_Linux_Kernel_Second_Edition.pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unix&nbsp;shell&nbsp;programming.3rd.ed.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Using_Samba.chm<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Vi&nbsp;iMproved&nbsp;(VIM).pdf<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─SAMBA&nbsp;24学时教程<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─UNIX教程网络篇<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─UNIX环境高级编程<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;├─UNIX系统安全工具<br>│&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>│&nbsp;&nbsp;└─莱昂氏UNIX源代码分析<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>├─Math<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;concretemath.pdf<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MathEncyclopedia.chm<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The_Calculus_Bible.pdf<br>│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>└─编程<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;ARM&nbsp;Program&nbsp;Tecgniques.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Designing.Embedded.Communications.Software.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;GCC-the-Complete-Reference.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;SQL21自学通.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;Threads&nbsp;Primer.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;UML_Concept.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;UML核心技术.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;正则表达式之道.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─ASM<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80x86保护模式系列教程.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ASM.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Assembly&nbsp;Language&nbsp;The&nbsp;True&nbsp;Language&nbsp;of&nbsp;Programmers.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BIOS研发技术剖析(基本概论与设置).pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Intel&nbsp;Architecture&nbsp;Software&nbsp;Developer's&nbsp;Manual.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Introduction.to.80x86.Assembly.Language.and.Computer.Architecture.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;masm.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Professional.Assembly.Language.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The.Art.Of.Assembly.Language.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;win32汇编语言教程.chm<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;中断大全.hlp<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;汇编语言程序设计艺术.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;├─C#<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Beginning.ASP.dot.NET.1.1.with.Visual.C.Shap.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C#&nbsp;COM+&nbsp;Programming.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C#参考.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C#完全手册.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C#高级编程.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C.Sharp.pdf<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;C_Sharp_Primer_Plus.rar<br>&nbsp;&nbsp;&nbsp;&nbsp;│&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Design&nbsp;Patterns&nbsp;in&nbsp;C#.pdf</p>
<img src ="http://www.blogjava.net/franlk/aggbug/132578.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-26 16:45 <a href="http://www.blogjava.net/franlk/articles/132578.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]java 集合框架(Collection)和数组的排序</title><link>http://www.blogjava.net/franlk/articles/131860.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Mon, 23 Jul 2007 05:35:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/131860.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/131860.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/131860.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/131860.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/131860.html</trackback:ping><description><![CDATA[<p><br>摘录地址:http://www.xrss.cn/Info/15106.Html<br><br>根据约定，在使用Java编程的时候应尽可能的使用现有的类库，当然你也可以自己编写一个排序的方法，或者框架，但是有几个人能写得比JDK里的还要好呢？使用现有的类的另一个好处是代码易于阅读和维护，这篇文章主要讲的是如何使用现有的类库对数组和各种Collection容器进行排序，(文章中的一部分例子来自《Java Developers Almanac 1.4》)<br>&nbsp;&nbsp;&nbsp; 首先要知道两个类:Java.util.Arrays和Java.util.Collections(注意和Collection的区别)Collection是集合框架的顶层接口，而Collections是包含了许多静态方法。我们使用Arrays对数组进行排序，使用Collections对结合框架容器进行排序，如ArraysList,LinkedList等。<br>&nbsp;&nbsp;&nbsp; 例子中都要加上import Java.util.*和其他外壳代码，如类和静态main方法，我会在第一个例子里写出全部代码，接下来会无一例外的省略。<br>&nbsp;<br>对数组进行排序<br>&nbsp;<br>比如有一个整型数组:<br>&nbsp;&nbsp;&nbsp; int[] intArray = new int[] {4, 1, 3, -23};<br>我们如何进行排序呢？你这个时候是否在想快速排序的算法？看看下面的实现方法:<br>&nbsp;&nbsp;&nbsp; import Java.util.*;<br>&nbsp;&nbsp;&nbsp; public class Sort{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int[] intArray = new int[] {4, 1, 3, -23};<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Arrays.sort(intArray);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>这样我们就用Arrays的静态方法sort()对intArray进行了升序排序，现在数组已经变成了{-23,1,3,4}.<br>&nbsp;<br>如果是字符数组:<br>&nbsp;&nbsp;&nbsp; String[] strArray = new String[] {"z", "a", "C"};<br>我们用:<br>&nbsp;&nbsp;&nbsp; Arrays.sort(strArray);<br>进行排序后的结果是{C,a,z},sort()会根据元素的自然顺序进行升序排序。如果希望对大小写不敏感的话可以这样写:<br>&nbsp;&nbsp;&nbsp; Arrays.sort(strArray, String.CASE_INSENSITIVE_ORDER);<br>当然我们也可以指定数组的某一段进行排序比如我们要对数组下表0-2的部分(假设数组长度大于3)进行排序，其他部分保持不变，我们可以使用:<br>&nbsp;&nbsp;&nbsp; Arrays.sort(strArray,0,2);<br>这样，我们只对前三个元素进行了排序，而不会影响到后面的部分。<br>&nbsp;<br>当然有人会想，我怎样进行降序排序？在众多的sort方法中有一个<br>&nbsp;&nbsp;&nbsp; sort(T[] a, Comparator&lt;? super T&gt; c)<br>我们使用Comparator获取一个反序的比较器即可，Comparator会在稍后讲解，以前面的intArray[]为例:<br>&nbsp;&nbsp;&nbsp; Arrays.sort(intArray,Comparator.reverseOrder());<br>这样，我们得到的结果就是{4,3,1,-23}。如果不想修改原有代码我们也可以使用:<br>&nbsp;&nbsp;&nbsp; Collections.reverse(Arrays.asList(intArray));<br>得到该数组的反序。结果同样为4,3,1,-23}。</p>
<p>现在的情况变了，我们的数组里不再是基本数据类型(primtive type)或者String类型的数组，而是对象数组。这个数组的自然顺序是未知的，因此我们需要为该类实现Comparable接口，比如我们有一个Name类:<br>&nbsp;&nbsp;&nbsp; class Name implements Comparable&lt;Name&gt;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String firstName,lastName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Name(String firstName,String lastName){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.firstName=firstName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.lastName=lastName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compareTo(Name o) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //实现接口<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int lastCmp=lastName.compareTo(o.lastName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (lastCmp!=0?lastCmp:firstName.compareTo(o.firstName));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public String toString(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //便于输出测试<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return firstName+" "+lastName;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>这样，当我们对这个对象数组进行排序时，就会先比较lastName，然后比较firstName 然后得出两个对象的先后顺序，就像compareTo(Name o)里实现的那样。不妨用程序试一试:<br>&nbsp;&nbsp;&nbsp; import Java.util.*;<br>&nbsp;&nbsp;&nbsp; public class NameSort {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Name nameArray[] = {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Name("John", "Lennon"),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Name("Karl", "Marx"),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Name("Groucho", "Marx"),<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new Name("Oscar", "Grouch")<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Arrays.sort(nameArray);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0;i&lt;nameArray.length;i++){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.out.println(nameArray[i].toString());<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp; }<br>结果正如我们所愿:<br>&nbsp;&nbsp;&nbsp; Oscar Grouch<br>&nbsp;&nbsp;&nbsp; John Lennon<br>&nbsp;&nbsp;&nbsp; Groucho Marx<br>&nbsp;&nbsp;&nbsp; Karl Marx</p>
<p><br>对集合框架进行排序<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; 如果已经理解了Arrays.sort()对数组进行排序的话，集合框架的使用也是大同小异。只是将Arrays替换成了Collections,注意Collections是一个类而Collection是一个接口，虽然只差一个"s"但是它们的含义却完全不同。<br>假如有这样一个链表:<br>&nbsp;&nbsp;&nbsp; LinkedList list=new LinkedList();<br>&nbsp;&nbsp;&nbsp; list.add(4);<br>&nbsp;&nbsp;&nbsp; list.add(34);<br>&nbsp;&nbsp;&nbsp; list.add(22);<br>&nbsp;&nbsp;&nbsp; list.add(2);<br>我们只需要使用:<br>&nbsp;&nbsp;&nbsp; Collections.sort(list);<br>就可以将ll里的元素按从小到大的顺序进行排序，结果就成了:<br>&nbsp;&nbsp;&nbsp; [2, 4, 22, 34]<br>如果LinkedList里面的元素是String，同样会想基本数据类型一样从小到大排序。<br>如果要实现反序排序也就是从达到小排序:<br>&nbsp;&nbsp;&nbsp; Collections.sort(list,Collectons.reverseOrder());<br>如果LinkedList里面的元素是自定义的对象，可以像上面的Name对象一样实现Comparable接口，就可以让Collection.sort()为您排序了。<br>&nbsp;<br>如果你想按照自己的想法对一个对象进行排序，你可以使用<br>&nbsp;&nbsp;&nbsp; sort(List&lt;T&gt; list, Comparator&lt;? super T&gt; c)<br>这个方法进行排序，在给出例子之前，先要说明一下Comparator的使用，<br>Comparable接口的格式:<br>&nbsp;&nbsp;&nbsp; public interface Comparator&lt;T&gt; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int compare(T o1, T o2);<br>&nbsp;&nbsp;&nbsp; }<br>其实Comparator里的int compare(T o1,T o2)的写法和Comparable里的compareTo()方法的写法差不多。在上面的Name类中我们的比较是从LastName开始的，这是西方人的习惯，到了中国，我们想从fristName开始比较，又不想修改原来的代码，这个时候，Comparator就可以派上用场了:<br>&nbsp;&nbsp;&nbsp; final Comparator&lt;Name&gt; FIRST_NAME_ORDER=new Comparator&lt;Name&gt;() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public int compare(Name n1, Name n2) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int firstCmp=n1.firstName.compareTo(n2.firstName);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (firstCmp!=0?firstCmp:n1.lastName.compareTo <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (n2.firstName));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; };<br>这样一个我们自定义的Comparator FIRST_NAME_ORDER就写好了。<br>将上个例子里那个名字数组转化为List:<br>&nbsp;&nbsp;&nbsp; List&lt;Name&gt; list=Arrays.asList(nameArray);<br>&nbsp;&nbsp;&nbsp; Collections.sort(list,FIRST_NAME_ORDER);<br>这样我们就成功的使用自己定义的比较器设定排序。</p>
<p><br>该文章转载自网络大本营：<a href="http://www.xrss.cn/Info/15106.Html">http://www.xrss.cn/Info/15106.Html</a></p>
<img src ="http://www.blogjava.net/franlk/aggbug/131860.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-23 13:35 <a href="http://www.blogjava.net/franlk/articles/131860.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>代码收藏</title><link>http://www.blogjava.net/franlk/articles/131292.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 19 Jul 2007 08:30:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/131292.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/131292.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/131292.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/131292.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/131292.html</trackback:ping><description><![CDATA[<br><br>&nbsp; AJAX传输(<a href="http://www.javaeye.com/topic/9505">http://www.javaeye.com/topic/9505</a>)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;<span style="FONT-SIZE: 14pt">&nbsp;&nbsp; String.prototype.trim = function(){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return this.replace(/(^[\s]*)|([\s]*$)/g, "");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; var pop;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; function update(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var arr = new Array();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var node= document.getElementsByTagName("td");&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var rcount = 0;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(var i=2;i&lt;node.length-1;i=i+2){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp="";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (var j=0;j&lt;node[i].children.length;j++){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var temp = temp+(node[i].children[j].value).trim()+";";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; arr[rcount]=temp.trim();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rcount++;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try{&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var DataToSend = "nodes="+URLEncoding(arr);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; url = "upRefvalue.jsp";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; winpopup();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlhttp.onreadystatechange = getReady;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlhttp.open("POST",url,true);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xmlhttp.send(DataToSend);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch(e){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert(e.description);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; function streamtochar(StrStream)&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var stream = new ActiveXObject("ADODB.Stream");&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.type = 1;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Mode = 3;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Open() ;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Write(StrStream);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Position = 0;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Type = 2;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Charset = "GB2312";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var result = stream.ReadText();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream.Close();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stream = null;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; function getReady(){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(xmlhttp.readyState == 4){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(xmlhttp.status == 200){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop.hide();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; window.close();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else{&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; childDropDown.innerHTML = "数据装载失败,原因:" + xmlhttp.statusText;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; function winpopup(){&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var left = (screen.width-200)/2;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var top = screen.height/2;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop = window.createPopup();&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop.document.body.innerHTML = "&lt;body&gt;&lt;font size='2'&gt;正在提交数据，请稍候...&lt;/font&gt;&lt;/body&gt;";&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pop.show(left,top,300,60,document.body);&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }&nbsp; <br></span><br><span style="COLOR: red">&nbsp;=================================================================================<br><br></span>
<img src ="http://www.blogjava.net/franlk/aggbug/131292.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-19 16:30 <a href="http://www.blogjava.net/franlk/articles/131292.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Ajax简单例子</title><link>http://www.blogjava.net/franlk/articles/131285.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 19 Jul 2007 08:12:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/131285.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/131285.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/131285.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/131285.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/131285.html</trackback:ping><description><![CDATA[<br><br>=============jsp中的javaScript=====================================<br><br>&nbsp;&nbsp;&lt;%--向后台发送相应的信息--%&gt;<br>&nbsp;&nbsp;function sendUrl(val,method,check){<br>&nbsp;&nbsp;&nbsp; var param1 = document.all("param1").value;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; //指定请求发送的URL地址和参数<br>&nbsp;&nbsp;&nbsp; var&nbsp; url="/test.do?method=list&amp;param1="+param1;<br>&nbsp;&nbsp;&nbsp; if(window.XMLHttpRequest){<br>&nbsp;&nbsp;&nbsp; &nbsp;req=new XMLHttpRequest();<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; else if (window.ActiveXObject){<br>&nbsp;&nbsp;&nbsp; &nbsp;req = new ActiveXObject("Microsoft.XMLHTTP");<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; if(req){<br>&nbsp;&nbsp;&nbsp; req.open("GET",url,true);//向服务器发送请求<br>&nbsp;&nbsp;&nbsp; req.onreadystatechange=callback;//指定回调函数<br>&nbsp;&nbsp;&nbsp; req.send(null);<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;function callback() //回调函数<br>&nbsp;&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(req.readyState==4)//判断接受到的响应状态,如果是4表示加载完毕<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(req.status==200){<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; parseMessage();//收到服务器数据后进行解析<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("该结算户不存在!");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }else { //响应未加载成功,页面中的代码<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //document.getElementById("check_userbh").innerHTML="&lt;font color=\"red\"&gt;" + "正在查询用户信息..." + "&lt;/font&gt;";<br>&nbsp;&nbsp;&nbsp;&nbsp; //document.getElementById("check_userbh").innerHTML="&lt;img src=\"images/loading.gif\" width=\"103\" height=\"20\"&gt;";<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;//对返回数据进行解析<br>&nbsp;&nbsp;function parseMessage(){<br>&nbsp;&nbsp;&nbsp; var xmlDoc =req.responseText;<br>&nbsp;&nbsp;&nbsp; var form = document.forms[0];<br>&nbsp;&nbsp;&nbsp; if(xmlDoc.length==0){&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp;&nbsp; }else{<br>&nbsp;&nbsp;&nbsp; &nbsp;//alert(xmlDoc);&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;=================================java===========<br>&nbsp;&nbsp;try{<br>&nbsp;&nbsp;&nbsp;//设置返回内容类型<br>&nbsp;&nbsp;&nbsp;response.setContentType("text/xml;charset=GBK");<br>&nbsp;&nbsp;&nbsp;//设置不缓存<br>&nbsp;&nbsp;&nbsp;response.setHeader("Cache-Control","no-cache");<br>&nbsp;&nbsp;&nbsp;//用流输出到页面.<br>&nbsp;&nbsp;&nbsp;response.getWriter().write(strData);=====&gt;strData返回前台的数据<br>&nbsp;&nbsp;&nbsp;return null;<br>&nbsp;&nbsp;} catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;request.setAttribute("Exception", e);<br>&nbsp;&nbsp;&nbsp;return null;<br>&nbsp;&nbsp;}&nbsp;<br><br>
<img src ="http://www.blogjava.net/franlk/aggbug/131285.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-19 16:12 <a href="http://www.blogjava.net/franlk/articles/131285.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]ajax如何后台交互 </title><link>http://www.blogjava.net/franlk/articles/131284.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 19 Jul 2007 08:07:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/131284.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/131284.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/131284.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/131284.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/131284.html</trackback:ping><description><![CDATA[<p><br>摘录地址 :http://www.xrss.cn/Info/13658.Html </p>
<p><br>AJAX全称为&#8220;Asynchronous JavaScript and Xml&#8221;（异步JavaScript和Xml），是指一种创建交互式网页应用的网页开发技术。AJAX技术是目前在浏览器中通过JavaScript脚本可以使用的所有技术的集合。AJAX以一种崭新的方式来使用所有的这些技术，使得古老的B/S方式的Web开发焕发了新的活力。<br>AJAX技术之中，最核心的技术就是XmlHttpRequest，它最初的名称叫做XmlHTTP，是微软公司为了满足开发者的需要，1999年在IE5.0浏览器中率先推出的。后来这个技术被上述的规范命名为XmlHttpRequest。它正是AJAX技术之所以与众不同的地方。简而言之，XmlHttpRequest为运行于浏览器中的JavaScript脚本提供了一种在页面之内与服务器通信的手段。页面内的JavaScript可以在不刷新页面的情况下从服务器获取数据，或者向服务器提交数据。XmlHttpRequest的出现为Web开发提供了一种全新的可能性，甚至整个改变了人们对于Web应用由什么来组成的看法。它可以使我们以一种全新的方式来做Web开发，为用户提供更好的交互体验。<br>与传统的Web开发不同，AJAX并不是以一种基于静态页面的方式来看待Web应用的。从AJAX的角度看来，Web应用应由少量的页面组成，其中每个页面其实是一个更小型的AJAX应用。每个页面上面都包括有一些使用JavaScript开发的AJAX组件。这些组件使用XmlHttpRequest对象以异步的方式与服务器通信，从服务器获取需要的数据后使用DOM API来更新页面中的一部分内容。因此AJAX应用与传统的Web应用的区别主要在三个地方：<br>1. 不刷新整个页面，在页面内与服务器通信。<br>2. 使用异步方式与服务器通信，不需要打断用户的操作，具有更加迅速的的响应能力。<br>3. 应用仅由少量页面组成。大部分交互在页面之内完成，不需要切换整个页面。<br>由此可见，AJAX使得Web应用更加动态，带来了更高的智能，并且提供了表现能力丰富的AJAX UI组件。这样一类新型的Web应用叫做RIA（Rich Inte.Net Application）应用。<br>前面是本人在网上找的一些关于AJAX介绍的资料,以帮助不了解AJAX技术的读者尽快了解AJAX技术,下面本人将会把自己在实际开发过程中用到的一些AJAX技术及技巧给大家介绍一下.<br>使用AJAX技术最重要的就是创建XmlHttpRequest对象,关于如何创建该对象网上有很多资料.本人最常用的一个方法是<br>function createXmlHttpRequest() {<br>&nbsp;&nbsp;&nbsp; var Xmlhttp;<br>&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xmlhttp = new ActiveXObject('MsXml2.XmlHTTP');<br>&nbsp;&nbsp;&nbsp; } catch(e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xmlhttp = new ActiveXObject('Microsoft.XmlHTTP');<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Xmlhttp = new XmlHttpRequest();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch(e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert("创建XmlHttpRequest对象失败！");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; return Xmlhttp;<br>}<br>下面本人将列出一些例子及一些通过这些例子可以学到的东西．<br>下面一段代码是本人在做新增特定物品时，做验证以判断该物品是否已在数据库中存在的例子．<br>&lt;input type="text" style="width:100%" class="noEmptyInput" name="segment10" value="&lt;%=segment10%&gt;" maxlength="16" onblur="do_verify();"&gt;<br>function do_verify() {<br>&nbsp;&nbsp;&nbsp; var segment10 = document.mainFrm.segment10.value;<br>&nbsp;&nbsp;&nbsp; var inventoryItemId = document.mainFrm.inventoryItemId.value;<br>&nbsp;&nbsp;&nbsp; //&nbsp;&nbsp;&nbsp; alert(segment10)<br>&nbsp;&nbsp;&nbsp; XmlHttp = createXmlHttpRequest();<br>&nbsp;&nbsp;&nbsp; var url = "/servlet/com.sino.ies.inv.maintenance.servlet.ItemMaintainServlet?forward=doVerify&amp;segment10=" + segment10 + "&amp;inventoryItemId=" + inventoryItemId;<br>&nbsp;&nbsp;&nbsp; XmlHttp.onreadystatechange = handleReadyStateChange;<br>&nbsp;&nbsp;&nbsp; XmlHttp.open("post", url, true);　//传递数据的方法同样有GET和POST两种,但是当方法为POST时下面的一句话就必须写<br>&nbsp;&nbsp;&nbsp; XmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');<br>&nbsp;&nbsp;&nbsp; XmlHttp.send(null);<br>}<br>function handleReadyStateChange() {<br>&nbsp;&nbsp;&nbsp; if (XmlHttp.readyState == 4) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (XmlHttp.status == 200) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (XmlHttp.responseText == 'Y') {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.mainFrm.isExist.value = 'Y';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("flag").style.display = "block"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.mainFrm.segment10.focus();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.mainFrm.isExist.value = 'N';<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; document.getElementById("flag").style.display = "none"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } else {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; alert(XmlHttp.status);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; }<br>}<br>后台代码为:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; boolean success = itemDAO.doVerifyItem();&nbsp; //doVerifyItem为验证指定物品是否在数据库中存在的主要方法,如果该物品已存在该方法将返回TRUE<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; PrintWriter out = res.getWriter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (success) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.print("Y");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.flush();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; out.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } </p>
<p><a href="http://www.xrss.cn/Info/13658.Html"></a>&nbsp;</p>
<img src ="http://www.blogjava.net/franlk/aggbug/131284.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-07-19 16:07 <a href="http://www.blogjava.net/franlk/articles/131284.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]利用Java控制EXCEL实例详解</title><link>http://www.blogjava.net/franlk/articles/126813.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 28 Jun 2007 06:07:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/126813.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/126813.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/126813.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/126813.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/126813.html</trackback:ping><description><![CDATA[<p>&nbsp; <span><br></span><span>摘录地址</span><span>:http://java.ccidnet.com/art/3539/20070618/1116527_1.html</span></p>
<p>使用<span>Windows操作系统的朋友对Excel（电子表格）一定不会陌生，但是要使用Java语言来操纵Excel文件并不是一件容易的事。在Web应用日益盛行的今天，通过Web来操作Excel文件的需求越来越强烈，目前较为流行的操作是在JSP或Servlet 中创建一个CSV （comma separated values）文件，并将这个文件以MIME，text/csv类型返回给浏览器，接着浏览器调用Excel并且显示CSV文件。这样只是说可以访问到Excel文件，但是还不能真正的操纵Excel文件，本文将给大家一个惊喜，向大家介绍一个开放源码项目 Java Excel API，使用它大家就可以方便地操纵Excel文件了。 </span></p>
<p><span>JAVA EXCEL API简介 </span></p>
<p><span>Java Excel是一开放源码项目，通过它Java开发人员可以读取Excel文件的内容、创建新的Excel文件、更新已经存在的Excel文件。使用该API非Windows操作系统也可以通过纯Java应用来处理Excel数据表。因为是使用Java编写的，所以我们在Web应用中可以通过JSP、Servlet来调用API实现对Excel数据表的访问。现在发布的稳定版本是V2.0，提供以下功能： </span></p>
<p><span>&#183;从Excel 95、97、2000等格式的文件中读取数据； </span></p>
<p><span>&#183;读取Excel公式（可以读取Excel 97以后的公式）； </span></p>
<p><span>&#183;生成Excel数据表（格式为Excel 97）； </span></p>
<p><span>&#183;支持字体、数字、日期的格式化； </span></p>
<p><span>&#183;支持单元格的阴影操作，以及颜色操作； </span></p>
<p><span>&#183;修改已经存在的数据表； </span></p>
<p><span>&#183; 现在还不支持以下功能，但不久就会提供了： </span></p>
<p><span>&#183;不能够读取图表信息； </span></p>
<p>可以读，但是不能生成公式，任何类型公式最后的计算值都可以读出； </p>
<p>应用示例 </p>
<p>从<span>Excel文件读取数据表 </span></p>
<p><span>Java Excel API既可以从本地文件系统的一个文件(.xls)，也可以从输入流中读取Excel数据表。读取Excel数据表的第一步是创建Workbook(术语：工作薄)，下面的代码片段举例说明了应该如何操作：(完整代码见ExcelReading.java) </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>import java.io.*;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>import jxl.*;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>&#8230;</span><span> </span><span>&#8230;</span><span> </span><span>&#8230;</span><span> </span><span>&#8230;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>try</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//构建Workbook对象, 只读Workbook对象</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//直接从本地文件创建Workbook</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//从输入流创建Workbook</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>InputStream is = new FileInputStream(sourcefile);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>jxl.Workbook rwb = Workbook.getWorkbook(is);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>catch (Exception e)</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>e.printStackTrace();</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p></ccid_nobr>一旦创建了<span>Workbook，我们就可以通过它来访问Excel Sheet(术语：工作表)。参考下面的代码片段： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>//获取第一张Sheet表</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Sheet rs = rwb.getSheet(0);</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p></ccid_nobr>我们既可能通过<span>Sheet的名称来访问它，也可以通过下标来访问它。如果通过下标来访问的话，要注意的一点是下标从0开始，就像数组一样。 </span></p>
<p>一旦得到了<span>Sheet，我们就可以通过它来访问Excel Cell(术语：单元格)。参考下面的代码片段： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>//获取第一行，第一列的值</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Cell c00 = rs.getCell(0, 0);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String strc00 = c00.getContents();</span></pre>
            <pre><span>&nbsp;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>//获取第一行，第二列的值</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Cell c10 = rs.getCell(1, 0);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String strc10 = c10.getContents();</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>//获取第二行，第二列的值</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Cell c11 = rs.getCell(1, 1);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>String strc11 = c11.getContents();</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " +</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c00.getType());</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " +</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c10.getType());</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " +</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c11.getType());</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p></ccid_nobr>如果仅仅是取得<span>Cell的值，我们可以方便地通过getContents()方法，它可以将任何类型的Cell值都作为一个字符串返回。示例代码中Cell(0, 0)是文本型，Cell(1, 0)是数字型，Cell(1,1)是日期型，通过getContents()，三种类型的返回值都是字符型。 </span></p>
<p>如果有需要知道<span>Cell内容的确切类型，API也提供了一系列的方法。参考下面的代码片段： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>String strc00 = null;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>double strc10 = 0.00;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Date strc11 = null;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Cell c00 = rs.getCell(0, 0);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Cell c10 = rs.getCell(1, 0);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>Cell c11 = rs.getCell(1, 1);</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(c00.getType() == CellType.LABEL)</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>LabelCell labelc00 = (LabelCell)c00;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>strc00 = labelc00.getString();</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(c10.getType() == CellType.NUMBER)</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NmberCell numc10 = (NumberCell)c10;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>strc10 = numc10.getValue();</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>if(c11.getType() == CellType.DATE)</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>{</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>DateCell datec11 = (DateCell)c11;</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>strc11 = datec11.getDate();</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>}</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println("Cell(0, 0)" + " value : " + strc00 + "; type : " +</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c00.getType());</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println("Cell(1, 0)" + " value : " + strc10 + "; type : " +</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c10.getType());</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>System.out.println("Cell(1, 1)" + " value : " + strc11 + "; type : " +</span></pre>
            <pre><span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>c11.getType());</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p align=left><span><br></ccid_nobr><span id=tech_art_center>&nbsp;</span></p>
<p>在得到<span>Cell对象后，通过getType()方法可以获得该单元格的类型，然后与API提供的基本类型相匹配，强制转换成相应的类型，最后调用相应的取值方法getXXX()，就可以得到确定类型的值。API提供了以下基本类型，与Excel的数据格式相对应。 </span></p>
<p>每种类型的具体意义，请参见<span>Java Excel API Document。 </span></p>
<p>当你完成对<span>Excel电子表格数据的处理后，一定要使用close()方法来关闭先前创建的对象，以释放读取数据表的过程中所占用的内存空间，在读取大量数据时显得尤为重要。参考如下代码片段： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>//操作完成时，关闭对象，释放占用的内存空间 </span></pre>
            <pre><span>rwb.close();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>Java Excel API提供了许多访问Excel数据表的方法，在这里我只简要地介绍几个常用的方法，其它的方法请参考附录中的Java Excel API Document。 </span></p>
<p><span>Workbook类提供的方法 </span></p>
<p><span>1. int getNumberOfSheets() </span></p>
<p>获得工作薄（<span>Workbook）中工作表（Sheet）的个数，示例： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>int sheets = rwb.getNumberOfSheets();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>2. Sheet[] getSheets() </span></p>
<p>返回工作薄（<span>Workbook）中工作表（Sheet）对象数组，示例： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>Sheet[] sheets = rwb.getSheets();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>3. String getVersion() </span></p>
<p>返回正在使用的<span>API的版本号，好像是没什么太大的作用。 </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>String apiVersion = rwb.getVersion();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>Sheet接口提供的方法 </span></p>
<p><span>1. String getName() </span></p>
<p>获取<span>Sheet的名称，示例： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>jxl.Sheet rs = rwb.getSheet(0); </span></pre>
            <pre><span>String sheetName = rs.getName();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>2. int getColumns() </span></p>
<p>获取<span>Sheet表中所包含的总列数，示例： </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>jxl.Sheet rs = rwb.getSheet(0); </span></pre>
            <pre><span>int rsColumns = rs.getColumns();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>3. Cell[] getColumn(int column) </span></p>
<p>获取某一列的所有单元格，返回的是单元格对象数组，示例： </p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>jxl.Sheet rs = rwb.getSheet(0); </span></pre>
            <pre><span>Cell[] cell = rs.getColumn(0);</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p>&nbsp;</p>
<p><span><span>&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span>4. int getRows() </span></p>
<p><span>获取</span><span>Sheet</span><span>表中所包含的总行数，示例：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>jxl.Sheet rs = rwb.getSheet(0); </span></pre>
            <pre><span>int rsRows = rs.getRows();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>5. Cell[] getRow(int row) </span></p>
<p><span>获取某一行的所有单元格，返回的是单元格对象数组，示例子：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>jxl.Sheet rs = rwb.getSheet(0); </span></pre>
            <pre><span>Cell[] cell = rs.getRow(0);</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>6. Cell getCell(int column, int row) </span></p>
<p><span>获取指定单元格的对象引用，需要注意的是它的两个参数，第一个是列数，第二个是行数，这与通常的行、列组合有些不同。</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>jxl.Workbook rwb = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>jxl.Sheet rs = rwb.getSheet(0); </span></pre>
            <pre><span>Cell cell = rs.getCell(0, 0);</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>生成新的</span><span>Excel</span><span>工作薄</span><span> </span></p>
<p><span>下面的代码主要是向大家介绍如何生成简单的</span><span>Excel</span><span>工作表，在这里单元格的内容是不带任何修饰的</span><span>(</span><span>如：字体，颜色等等</span><span>)</span><span>，所有的内容都作为字符串写入。</span><span>(</span><span>完整代码见</span><span>ExcelWriting.java) </span></p>
<p><span>与读取</span><span>Excel</span><span>工作表相似，首先要使用</span><span>Workbook</span><span>类的工厂方法创建一个可写入的工作薄</span><span>(Workbook)</span><span>对象，这里要注意的是，只能通过</span><span>API</span><span>提供的工厂方法来创建</span><span>Workbook</span><span>，而不能使用</span><span>WritableWorkbook</span><span>的构造函数，因为类</span><span>WritableWorkbook</span><span>的构造函数为</span><span>protected</span><span>类型。示例代码片段如下：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>import java.io.*; </span></pre>
            <pre><span>import jxl.*; </span></pre>
            <pre><span>import jxl.write.*; </span></pre>
            <pre><span>&#8230;</span><span> </span><span>&#8230;</span><span> </span><span>&#8230;</span><span> </span><span>&#8230;</span><span> </span></pre>
            <pre><span>try </span></pre>
            <pre><span>{ </span></pre>
            <pre><span>//构建Workbook对象, 只读Workbook对象 </span></pre>
            <pre><span>//Method 1：创建可写入的Excel工作薄 </span></pre>
            <pre><span>jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile)); </span></pre>
            <pre><span>//Method 2：将WritableWorkbook直接写入到输出流 </span></pre>
            <pre><span>/* </span></pre>
            <pre><span>OutputStream os = new FileOutputStream(targetfile); </span></pre>
            <pre><span>jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(os); </span></pre>
            <pre><span>*/ </span></pre>
            <pre><span>} </span></pre>
            <pre><span>catch (Exception e) </span></pre>
            <pre><span>{ </span></pre>
            <pre><span>e.printStackTrace(); </span></pre>
            <pre><span>}</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>API</span><span>提供了两种方式来处理可写入的输出流，一种是直接生成本地文件，如果文件名不带全路径的话，缺省的文件会定位在当前目录，如果文件名带有全路径的话，则生成的</span><span>Excel</span><span>文件则会定位在相应的目录；另外一种是将</span><span>Excel</span><span>对象直接写入到输出流，例如：用户通过浏览器来访问</span><span>Web</span><span>服务器，如果</span><span>HTTP</span><span>头设置正确的话，浏览器自动调用客户端的</span><span>Excel</span><span>应用程序，来显示动态生成的</span><span>Excel</span><span>电子表格。</span><span> </span></p>
<p><span>接下来就是要创建工作表，创建工作表的方法与创建工作薄的方法几乎一样，同样是通过工厂模式方法获得相应的对象，该方法需要两个参数，一个是工作表的名称，另一个是工作表在工作薄中的位置，参考下面的代码片段：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>file://创建Excel工作表 </span></pre>
            <pre><span>jxl.write.WritableSheet ws = wwb.createSheet("Test Sheet 1", 0);</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>"</span><span>这锅也支好了，材料也准备齐全了，可以开始下锅了！</span><span>"</span><span>，现在要做的只是实例化</span><span>API</span><span>所提供的</span><span>Excel</span><span>基本数据类型，并将它们添加到工作表中就可以了，参考下面的代码片段：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>file://1/.添加Label对象 </span></pre>
            <pre><span>jxl.write.Label labelC = new jxl.write.Label(0, 0, "This is a Label cell"); </span></pre>
            <pre><span>ws.addCell(labelC); </span></pre>
            <pre><span>//添加带有字型Formatting的对象 </span></pre>
            <pre><span>jxl.write.WritableFont wf = new jxl.write.WritableFont(WritableFont.TIMES, 18, </span></pre>
            <pre><span>WritableFont.BOLD, true); </span></pre>
            <pre><span>jxl.write.WritableCellFormat wcfF = new jxl.write.WritableCellFormat(wf); </span></pre>
            <pre><span>jxl.write.Label labelCF = new jxl.write.Label(1, 0, "This is a Label Cell", wcfF); </span></pre>
            <pre><span>ws.addCell(labelCF); </span></pre>
            <pre><span>//添加带有字体颜色Formatting的对象 </span></pre>
            <pre><span>jxl.write.WritableFont wfc = new jxl.write.WritableFont(WritableFont.ARIAL, 10, </span></pre>
            <pre><span>WritableFont.NO_BOLD, false, </span></pre>
            <pre><span>UnderlineStyle.NO_UNDERLINE, jxl.format.Colour.RED); </span></pre>
            <pre><span>jxl.write.WritableCellFormat wcfFC = new jxl.write.WritableCellFormat(wfc); </span></pre>
            <pre><span>jxl.write.Label labelCFC = new jxl.write.Label(1, 0, "This is a Label Cell", wcfFC); </span></pre>
            <pre><span>ws.addCell(labelCF); </span></pre>
            <pre><span>//2.添加Number对象 </span></pre>
            <pre><span>jxl.write.Number labelN = new jxl.write.Number(0, 1, 3.1415926); </span></pre>
            <pre><span>ws.addCell(labelN); </span></pre>
            <pre><span>//添加带有formatting的Number对象 </span></pre>
            <pre><span>jxl.write.NumberFormat nf = new jxl.write.NumberFormat("#.##"); </span></pre>
            <pre><span>jxl.write.WritableCellFormat wcfN = new jxl.write.WritableCellFormat(nf); </span></pre>
            <pre><span>jxl.write.Number labelNF = new jxl.write.Number(1, 1, 3.1415926, wcfN); </span></pre>
            <pre><span>ws.addCell(labelNF); </span></pre>
            <pre><span>//3.添加Boolean对象 </span></pre>
            <pre><span>jxl.write.Boolean labelB = new jxl.write.Boolean(0, 2, false); </span></pre>
            <pre><span>ws.addCell(labelB); </span></pre>
            <pre><span>//4.添加DateTime对象 </span></pre>
            <pre><span>jxl.write.DateTime labelDT = new jxl.write.DateTime(0, 3, new java.util.Date()); </span></pre>
            <pre><span>ws.addCell(labelDT); </span></pre>
            <pre><span>//添加带有formatting的DateFormat对象 </span></pre>
            <pre><span>jxl.write.DateFormat df = new jxl.write.DateFormat("dd MM yyyy hh:mm:ss"); </span></pre>
            <pre><span>jxl.write.WritableCellFormat wcfDF = new jxl.write.WritableCellFormat(df); </span></pre>
            <pre><span>jxl.write.DateTime labelDTF = new jxl.write.DateTime(1, 3, new java.util.Date(), wcfDF); </span></pre>
            <pre><span>ws.addCell(labelDTF);</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p></span>&nbsp;</p>
<p>&nbsp;</p>
<p><span>这里有两点大家要引起大家的注意。第一点，在构造单元格时，单元格在工作表中的位置就已经确定了。一旦创建后，单元格的位置是不能够变更的，尽管单元格的内容是可以改变的。第二点，单元格的定位是按照下面这样的规律</span><span>(column, row)</span><span>，而且下标都是从</span><span>0</span><span>开始，例如，</span><span>A1</span><span>被存储在</span><span>(0, 0)</span><span>，</span><span>B1</span><span>被存储在</span><span>(1, 0)</span><span>。</span><span> </span></p>
<p><span>最后，不要忘记关闭打开的</span><span>Excel</span><span>工作薄对象，以释放占用的内存，参见下面的代码片段：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>file://写入Exel工作表 </span></pre>
            <pre><span>wwb.write(); </span></pre>
            <pre><span>//关闭Excel工作薄对象 </span></pre>
            <pre><span>wwb.close();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>这可能与读取</span><span>Excel</span><span>文件的操作有少少不同，在关闭</span><span>Excel</span><span>对象之前，你必须要先调用</span><span>write()</span><span>方法，因为先前的操作都是存储在缓存中的，所以要通过该方法将操作的内容保存在文件中。如果你先关闭了</span><span>Excel</span><span>对象，那么只能得到一张空的工作薄了。</span><span> </span></p>
<p><span>拷贝、更新</span><span>Excel</span><span>工作薄</span><span> </span></p>
<p><span>接下来简要介绍一下如何更新一个已经存在的工作薄，主要是下面二步操作，第一步是构造只读的</span><span>Excel</span><span>工作薄，第二步是利用已经创建的</span><span>Excel</span><span>工作薄创建新的可写入的</span><span>Excel</span><span>工作薄，参考下面的代码片段：</span><span>(</span><span>完整代码见</span><span>ExcelModifying.java) </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>file://创建只读的Excel工作薄的对象 </span></pre>
            <pre><span>jxl.Workbook rw = jxl.Workbook.getWorkbook(new File(sourcefile)); </span></pre>
            <pre><span>//创建可写入的Excel工作薄对象 </span></pre>
            <pre><span>jxl.write.WritableWorkbook wwb = Workbook.createWorkbook(new File(targetfile), rw); </span></pre>
            <pre><span>//读取第一张工作表 </span></pre>
            <pre><span>jxl.write.WritableSheet ws = wwb.getSheet(0); </span></pre>
            <pre><span>//获得第一个单元格对象 </span></pre>
            <pre><span>jxl.write.WritableCell wc = ws.getWritableCell(0, 0); </span></pre>
            <pre><span>//判断单元格的类型, 做出相应的转化 </span></pre>
            <pre><span>if(wc.getType() == CellType.LABEL) </span></pre>
            <pre><span>{ </span></pre>
            <pre><span>Label l = (Label)wc; </span></pre>
            <pre><span>l.setString("The value has been modified."); </span></pre>
            <pre><span>} </span></pre>
            <pre><span>//写入Excel对象 </span></pre>
            <pre><span>wwb.write(); </span></pre>
            <pre><span>//关闭可写入的Excel对象 </span></pre>
            <pre><span>wwb.close(); </span></pre>
            <pre><span>//关闭只读的Excel对象 </span></pre>
            <pre><span>rw.close();</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>之所以使用这种方式构建</span><span>Excel</span><span>对象，完全是因为效率的原因，因为上面的示例才是</span><span>API</span><span>的主要应用。为了提高性能，在读取工作表时，与数据相关的一些输出信息，所有的格式信息，如：字体、颜色等等，是不被处理的，因为我们的目的是获得行数据的值，既使没有了修饰，也不会对行数据的值产生什么影响。唯一的不利之处就是，在内存中会同时保存两个同样的工作表，这样当工作表体积比较大时，会占用相当大的内存，但现在好像内存的大小并不是什么关键因素了。</span><span> </span></p>
<p><span>一旦获得了可写入的工作表对象，我们就可以对单元格对象进行更新的操作了，在这里我们不必调用</span><span>API</span><span>提供的</span><span>add()</span><span>方法，因为单元格已经于工作表当中，所以我们只需要调用相应的</span><span>setXXX()</span><span>方法，就可以完成更新的操作了。</span><span> </span></p>
<p><span>尽单元格原有的格式化修饰是不能去掉的，我们还是可以将新的单元格修饰加上去，以使单元格的内容以不同的形式表现。</span><span> </span></p>
<p><span>新生成的工作表对象是可写入的，我们除了更新原有的单元格外，还可以添加新的单元格到工作表中，这与示例</span><span>2</span><span>的操作是完全一样的。</span><span> </span></p>
<p><span>最后，不要忘记调用</span><span>write()</span><span>方法，将更新的内容写入到文件中，然后关闭工作薄对象，这里有两个工作薄对象要关闭，一个是只读的，另外一个是可写入的。</span><span> </span></p>
<p><span>下面是在一个</span><span>Excel</span><span>表格中创建一个矩阵的简单例子：</span><span> </span></p>
<div align=center>
<table cellSpacing=0 borderColorDark=#ffffff cellPadding=0 width=400 borderColorLight=black border=1>
    <tbody>
        <tr>
            <td>
            <pre><ccid_code><span><ccid_nobr>import org.apache.poi.hssf.usermodel.*; </span></pre>
            <pre><span>import java.io.FileOutputStream; </span></pre>
            <pre>&nbsp;</pre>
            <pre><span>// code run against the jakarta-poi-1.5.0-FINAL-20020506.jar. </span></pre>
            <pre><span>public class PoiTest { </span></pre>
            <pre><span>static public void main(String[] args) throws Exception { </span></pre>
            <pre><span>FileOutputStream fos = new FileOutputStream("foo.xls"); </span></pre>
            <pre><span>HSSFWorkbook wb = new HSSFWorkbook(); </span></pre>
            <pre><span>HSSFSheet s = wb.createSheet(); </span></pre>
            <pre><span>wb.setSheetName(0, "Matrix"); </span></pre>
            <pre><span>for(short i=0; i&lt;50; i++) { </span></pre>
            <pre><span>HSSFRow row = s.createRow(i); </span></pre>
            <pre><span>for(short j=0; j&lt;50; j++) { </span></pre>
            <pre><span>HSSFCell cell = row.createCell(j); </span></pre>
            <pre><span>cell.setCellValue(""+i+","+j); </span></pre>
            <pre><span>} </span></pre>
            <pre><span>} </span></pre>
            <pre><span>wb.write(fos); </span></pre>
            <pre><span>fos.close(); </span></pre>
            <pre><span>} </span></pre>
            <pre><span>}</ccid_code></span></pre>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p><span></ccid_nobr>这段代码首先创建一个</span><span>Workbook</span><span>，从该</span><span>Workbook</span><span>中得到一个表格、命名，然后继续写入一个</span><span>50x50</span><span>的矩阵。最后输出到一个名为</span><span>foo.xls</span><span>的</span><span>Excel</span><span>文件，甚至在</span><span>Apple Mac</span><span>机上也可以打开。</span><span> </span></p>
<p><span>POI</span><span>项目是</span><span>Java</span><span>应用的令人兴奋的一步，为用户提供了</span><span>Windows</span><span>文档集成的新功能，允许</span><span>Java</span><span>开发人员方便地扩展其产品的功能。（责任编辑：龚勋）</span><span> </span></p>
<p></span></p>
<img src ="http://www.blogjava.net/franlk/aggbug/126813.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-06-28 14:07 <a href="http://www.blogjava.net/franlk/articles/126813.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]JAR文件揭密</title><link>http://www.blogjava.net/franlk/articles/109605.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Tue, 10 Apr 2007 05:02:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/109605.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/109605.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/109605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/109605.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/109605.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://blog.donews.com/javapro/articles/495288.aspx">http://blog.donews.com/javapro/articles/495288.aspx</a><br><br>&nbsp;
<p><span>大多数</span><span> Java </span><span>程序员都熟悉对</span><span> JAR </span><span>文件的基本操作。但是只有少数程序员了解</span><span> JAR </span><span>文件格式的强大功能。在本文中，作者探讨了</span><span> JAR </span><span>格式的许多功能和优势，包括打包、可执行的</span><span> JAR </span><span>文件、安全性和索引。</span> </p>
<p><span>JAR </span><span>文件是什么？</span><span> </span></p>
<p><span>JAR </span><span>文件格式以流行的</span><span> ZIP </span><span>文件格式为基础，用于将许多个文件聚集为一个文件。与</span><span> ZIP </span><span>文件不同的是，</span><span>JAR </span><span>文件不仅用于压缩和发布，而且还用于部署和封装库、组件和插件程序，并可被像编译器和</span><span> JVM </span><span>这样的工具直接使用。在</span><span> JAR </span><span>中包含特殊的文件，如</span><span> manifests </span><span>和部署描述符，用来指示工具如何处理特定的</span><span> JAR</span><span>。</span> </p>
<p>&nbsp;</p>
<p><span>一个</span><span> JAR </span><span>文件可以用于：</span> </p>
<p><span>用于发布和使用类库</span><span> </span></p>
<p><span>作为应用程序和扩展的构建单元</span><span> </span></p>
<p><span>作为组件、</span><span>applet </span><span>或者插件程序的部署单位</span><span> </span></p>
<p><span>用于打包与组件相关联的辅助资源</span><span> </span></p>
<p><span>JAR </span><span>文件格式提供了许多优势和功能，其中很多是传统的压缩格式如</span><span> ZIP </span><span>或者</span><span> TAR </span><span>所没有提供的。它们包括：</span><span> </span></p>
<p>&nbsp;</p>
<p><span>安全性。</span> <span>可以对</span><span> JAR </span><span>文件内容加上数字化签名。这样，能够识别签名的工具就可以有选择地为您授予软件安全特权，这是其他文件做不到的，它还可以检测代码是否被篡改过。</span><span> </span></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p><span>减少下载时间。</span> <span>如果一个</span><span> applet </span><span>捆绑到一个</span><span> JAR </span><span>文件中，那么浏览器就可以在一个</span><span> HTTP </span><span>事务中下载这个</span><span> applet </span><span>的类文件和相关的资源，而不是对每一个文件打开一个新连接。</span> </p>
<p>&nbsp;</p>
<p><span>压缩。</span><span>JAR </span><span>格式允许您压缩文件以提高存储效率。</span> </p>
<p>&nbsp;</p>
<p><span>传输平台扩展。</span> <span>Java </span><span>扩展框架</span><span>(Java Extensions Framework)</span><span>提供了向</span><span> Java </span><span>核心平台添加功能的方法，这些扩展是用</span><span> JAR </span><span>文件打包的</span><span>(Java 3D </span><span>和</span><span> JavaMail </span><span>就是由</span><span> Sun </span><span>开发的扩展例子</span><span>)</span><span>。</span> </p>
<p>&nbsp;</p>
<p><span>包密封。</span> <span>存储在</span><span> JAR </span><span>文件中的包可以选择进行密封，以增强版本一致性和安全性。密封一个包意味着包中的所有类都必须在同一</span><span> JAR </span><span>文件中找到。</span> </p>
<p>&nbsp;</p>
<p><span>包版本控制。</span> <span>一个</span><span> JAR </span><span>文件可以包含有关它所包含的文件的数据，如厂商和版本信息。</span> </p>
<p>&nbsp;</p>
<p><span>可移植性。</span> <span>处理</span><span> JAR </span><span>文件的机制是</span><span> Java </span><span>平台核心</span><span> API </span><span>的标准部分。</span><span> </span></p>
<p><span>压缩的和未压缩的</span><span> JAR </span></p>
<p><span>jar </span><span>工具</span><span>(</span><span>有关细节参阅</span><span> jar </span><span>工具</span><span>)</span><span>在默认情况下压缩文件。未压缩的</span><span> JAR </span><span>文件一般可以比压缩过的</span><span> JAR </span><span>文件更快地装载，因为在装载过程中要解压缩文件，但是未压缩的文件在网络上的下载时间可能更长。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>META-INF </span><span>目录</span><span> </span></p>
<p><span>大多数</span><span> JAR </span><span>文件包含一个</span><span> META-INF </span><span>目录，它用于存储包和扩展的配置数据，如安全性和版本信息。</span><span>Java 2 </span><span>平台识别并解释</span><span> META-INF </span><span>目录中的下述文件和目录，以便配置应用程序、扩展和类装载器：</span><span> </span></p>
<p>&nbsp;</p>
<p><span>MANIFEST.MF</span><span>。</span> <span>这个</span><span> manifest </span><span>文件定义了与扩展和包相关的数据。</span> </p>
<p>&nbsp;</p>
<p><span>INDEX.LIST</span><span>。</span> <span>这个文件由</span><span> jar </span><span>工具的新选项</span><span> -i </span><span>生成，它包含在应用程序或者扩展中定义的包的位置信息。它是</span><span> JarIndex </span><span>实现的一部分，并由类装载器用于加速类装载过程。</span></p>
<p>&nbsp;</p>
<p><span>xxx.SF</span><span>。</span> <span>这是</span><span> JAR </span><span>文件的签名文件。占位符</span><span> xxx </span><span>标识了签名者。</span> </p>
<p>&nbsp;</p>
<p><span>xxx.DSA</span><span>。</span> <span>与签名文件相关联的签名程序块文件，它存储了用于签名</span><span> JAR </span><span>文件的公共签名。</span><span> </span></p>
<p><span>jar </span><span>工具</span><span> </span></p>
<p><span>为了用</span><span> JAR </span><span>文件执行基本的任务，要使用作为</span><span>Java Development Kit </span><span>的一部分提供的</span><span> Java Archive Tool (jar </span><span>工具</span><span>)</span><span>。用</span><span> jar </span><span>命令调用</span><span> jar </span><span>工具。表</span><span> 1 </span><span>显示了一些常见的应用：</span><span> </span></p>
<p>&nbsp;</p>
<p><span>表</span><span> 1. </span><span>常见的</span><span> jar </span><span>工具用法</span> <span>功能</span> <span>命令</span><span> </span></p>
<p><span>用一个单独的文件创建一个</span><span> JAR </span><span>文件</span><span> jar cf jar-file input-file... </span></p>
<p><span>用一个目录创建一个</span><span> JAR </span><span>文件</span><span> jar cf jar-file dir-name </span></p>
<p><span>创建一个未压缩的</span><span> JAR </span><span>文件</span><span> jar cf0 jar-file dir-name </span></p>
<p><span>更新一个</span><span> JAR </span><span>文件</span><span> jar uf jar-file input-file... </span></p>
<p><span>查看一个</span><span> JAR </span><span>文件的内容</span><span> jar tf jar-file </span></p>
<p><span>提取一个</span><span> JAR </span><span>文件的内容</span><span> jar xf jar-file </span></p>
<p><span>从一个</span><span> JAR </span><span>文件中提取特定的文件</span><span> jar xf jar-file archived-file... </span></p>
<p><span>运行一个打包为可执行</span><span> JAR </span><span>文件的应用程序</span><span> java -jar app.jar </span></p>
<p>&nbsp;</p>
<p><span>可执行的</span><span> JAR </span></p>
<p><span>一个可执行的</span><span> jar </span><span>文件是一个自包含的</span><span> Java </span><span>应用程序，它存储在特别配置的</span><span>JAR </span><span>文件中，可以由</span><span> JVM </span><span>直接执行它而无需事先提取文件或者设置类路径。要运行存储在非可执行的</span><span> JAR </span><span>中的应用程序，必须将它加入到您的类路径中，并用名字调用应用程序的主类。但是使用可执行的</span><span> JAR </span><span>文件，我们可以不用提取它或者知道主要入口点就可以运行一个应用程序。可执行</span><span> JAR </span><span>有助于方便发布和执行</span><span> Java </span><span>应用程序。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>创建可执行</span><span> JAR </span></p>
<p><span>创建一个可执行</span><span> JAR </span><span>很容易。首先将所有应用程序代码放到一个目录中。假设应用程序中的主类是</span><span> com.mycompany.myapp.Sample</span><span>。您要创建一个包含应用程序代码的</span><span> JAR </span><span>文件并标识出主类。为此，在某个位置</span><span>(</span><span>不是在应用程序目录中</span><span>)</span><span>创建一个名为</span><span> manifest </span><span>的文件，并在其中加入以下一行：</span> </p>
<p>&nbsp;</p>
<p><span>Main-Class: com.mycompany.myapp.Sample </span></p>
<p>&nbsp;</p>
<p><span>然后，像这样创建</span><span> JAR </span><span>文件：</span> </p>
<p><span>jar cmf manifest ExecutableJar.jar application-dir </span></p>
<p>&nbsp;</p>
<p><span>所要做的就是这些了</span><span> -- </span><span>现在可以用</span><span> java -jar </span><span>执行这个</span><span> JAR </span><span>文件</span><span> ExecutableJar.jar</span><span>。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>一个可执行的</span><span> JAR </span><span>必须通过</span><span> menifest </span><span>文件的头引用它所需要的所有其他从属</span><span> JAR</span><span>。如果使用了</span><span> -jar </span><span>选项，那么环境变量</span><span> CLASSPATH </span><span>和在命令行中指定的所有类路径都被</span><span> JVM </span><span>所忽略。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>启动可执行</span><span> JAR </span></p>
<p><span>既然我们已经将自己的应用程序打包到了一个名为</span><span> ExecutableJar.jar </span><span>的可执行</span><span> JAR </span><span>中了，那么我们就可以用下面的命令直接从文件启动这个应用程序：</span> </p>
<p><span>java -jar ExecutableJar.jar </span></p>
<p>&nbsp;</p>
<p><span>包密封</span><span> </span></p>
<p><span>密封</span><span> JAR </span><span>文件中的一个包意味着在这个包中定义的所有类都必须在同一个</span><span> JAR </span><span>文件中找到。这使包的作者可以增强打包类之间的版本一致性。密封还提供了防止代码篡改的手段。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>要密封包，需要在</span><span> JAR </span><span>的</span><span> manifest </span><span>文件中为包添加一个</span><span> Name </span><span>头，然后加上值为&#8220;</span><span>true</span><span>&#8221;的</span><span> Sealed </span><span>头。与可执行的</span><span> JAR </span><span>一样，可以在创建</span><span> JAR </span><span>时，通过指定一个具有适当头元素的</span><span> manifest </span><span>文件密封一个</span><span> JAR</span><span>，如下所示：</span> </p>
<p><span>Name: com/samplePackage/ </span></p>
<p><span>Sealed: true </span></p>
<p>&nbsp;</p>
<p><span>Name </span><span>头标识出包的相对路径名。它以一个&#8220;</span><span>/</span><span>&#8221;结束以与文件名区别。在</span><span> Name </span><span>头后面第一个空行之前的所有头都作用于在</span><span> Name </span><span>头中指定的文件或者包。在上述例子中，因为</span><span> Sealed </span><span>头出现在</span><span> Name </span><span>头后并且中间没有空行，所以</span><span> Sealed </span><span>头将被解释为只应用到包</span><span> com/samplePackage </span><span>上。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>如果试图从密封包所在的</span><span> JAR </span><span>文件以外的其他地方装载密封包中的一个类，那么</span><span> JVM </span><span>将抛出一个</span><span> SecurityException</span><span>。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>扩展打包</span><span> </span></p>
<p><span>扩展为</span><span> Java </span><span>平台增加了功能，在</span><span> JAR </span><span>文件格式中已经加入了扩展机制。扩展机制使得</span><span> JAR </span><span>文件可以通过</span><span> manifest </span><span>文件中的</span><span> Class-Path </span><span>头指定所需要的其他</span><span> JAR </span><span>文件。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>假设</span><span> extension1.jar </span><span>和</span><span> extension2.jar </span><span>是同一个目录中的两个</span><span> JAR </span><span>文件，</span><span>extension1.jar </span><span>的</span><span> manifest </span><span>文件包含以下头：</span> </p>
<p>&nbsp;</p>
<p><span>Class-Path: extension2.jar </span></p>
<p>&nbsp;</p>
<p><span>这个头表明</span><span> extension2.jar </span><span>中的类是</span><span> extension1.jar </span><span>中的类的扩展类。</span><span>extension1.jar </span><span>中的类可以调用</span><span> extension2.jar </span><span>中的类，并且不要求</span><span> extension2.jar </span><span>处在类路径中。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>在装载使用扩展机制的</span><span> JAR </span><span>时，</span><span>JVM </span><span>会高效而自动地将在</span><span>Class-Path </span><span>头中引用的</span><span> JAR </span><span>添加到类路径中。不过，扩展</span><span> JAR </span><span>路径被解释为相对路径，所以一般来说，扩展</span><span> JAR </span><span>必须存储在引用它的</span><span> JAR </span><span>所在的同一目录中。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>例如，假设类</span><span> ExtensionClient </span><span>引用了类</span><span> ExtensionDemo,</span><span>它捆绑在一个名为</span><span> ExtensionClient.jar </span><span>的</span><span> JAR </span><span>文件中，而类</span><span> ExtensionDemo </span><span>则捆绑在</span><span> ExtensionDemo.jar </span><span>中。为了使</span><span> ExtensionDemo.jar </span><span>可以成为扩展，必须将</span><span> ExtensionDemo.jar </span><span>列在</span><span> ExtensionClient.jar </span><span>的</span><span> manifest </span><span>的</span><span> Class-Path </span><span>头中，如下所示：</span> </p>
<p>&nbsp;</p>
<p><span>Manifest-Version: 1.0 </span></p>
<p><span>Class-Path: ExtensionDemo.jar </span></p>
<p>&nbsp;</p>
<p><span>在这个</span><span> manifest </span><span>中</span><span> Class-Path </span><span>头的值是没有指定路径的</span><span> ExtensionDemo.jar</span><span>，表明</span><span> ExtensionDemo.jar </span><span>与</span><span> ExtensionClient JAR </span><span>文件处在同一目录中。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>JAR </span><span>文件中的安全性</span><span> </span></p>
<p><span>JAR </span><span>文件可以用</span><span> jarsigner </span><span>工具或者直接通过</span><span> java.security API </span><span>签名。一个签名的</span><span> JAR </span><span>文件与原来的</span><span> JAR </span><span>文件完全相同，只是更新了它的</span><span> manifest</span><span>，并在</span><span> META-INF </span><span>目录中增加了两个文件，一个签名文件和一个签名块文件。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>JAR </span><span>文件是用一个存储在</span><span> Keystore </span><span>数据库中的证书签名的。存储在</span><span> keystore </span><span>中的证书有密码保护，必须向</span><span> jarsigner </span><span>工具提供这个密码才能对</span><span> JAR </span><span>文件签名。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>图</span><span> 1. Keystore </span><span>数据库</span> </p>
<p>&nbsp;</p>
<p><span>JAR </span><span>的每一位签名者都由在</span><span> JAR </span><span>文件的</span><span> META-INF </span><span>目录中的一个具有</span><span> .SF </span><span>扩展名的签名文件表示。这个文件的格式类似于</span><span> manifest </span><span>文件</span><span> -- </span><span>一组</span><span> RFC-822 </span><span>头。如下所示，它的组成包括一个主要部分，它包括了由签名者提供的信息、但是不特别针对任何特定的</span><span> JAR </span><span>文件项，还有一系列的单独的项，这些项也必须包含在</span><span> menifest </span><span>文件中。在验证一个签名的</span><span> JAR </span><span>时，将签名文件的摘要值与对</span><span> JAR </span><span>文件中的相应项计算的摘要值进行比较。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>清单</span><span> 1. </span><span>签名</span><span> JAR </span><span>中的</span><span> Manifest </span><span>和</span><span> signature </span><span>文件</span><span> </span></p>
<p><span>Contents of signature file META-INF/MANIFEST.MF </span></p>
<p>&nbsp;</p>
<p><span>Manifest-Version: 1.0 </span></p>
<p><span>Created-By: 1.3.0 (Sun Microsystems Inc.) </span></p>
<p>&nbsp;</p>
<p><span>Name: Sample.java </span></p>
<p><span>SHA1-Digest: 3+DdYW8INICtyG8ZarHlFxX0W6g= </span></p>
<p>&nbsp;</p>
<p><span>Name: Sample.class </span></p>
<p><span>SHA1-Digest: YJ5yQHBZBJ3SsTNcHJFqUkfWEmI= </span></p>
<p>&nbsp;</p>
<p><span>Contents of signature file META-INF/JAMES.SF </span></p>
<p>&nbsp;</p>
<p><span>Signature-Version: 1.0 </span></p>
<p><span>SHA1-Digest-Manifest: HBstZOJBuuTJ6QMIdB90T8sjaOM= </span></p>
<p><span>Created-By: 1.3.0 (Sun Microsystems Inc.) </span></p>
<p>&nbsp;</p>
<p><span>Name: Sample.java </span></p>
<p><span>SHA1-Digest: qipMDrkurQcKwnyIlI3Jtrnia8Q= </span></p>
<p>&nbsp;</p>
<p><span>Name: Sample.class </span></p>
<p><span>SHA1-Digest: pT2DYby8QXPcCzv2NwpLxd8p4G4= </span></p>
<p>&nbsp;</p>
<p><span>数字签名</span><span> </span></p>
<p><span>一个数字签名是</span><span>.SF </span><span>签名文件的已签名版本。数字签名文件是二进制文件，并且与</span><span> .SF </span><span>文件有相同的文件名，但是扩展名不同。根据数字签名的类型</span><span> -- RSA</span><span>、</span><span>DSA </span><span>或者</span><span> PGP -- </span><span>以及用于签名</span><span> JAR </span><span>的证书类型而有不同的扩展名。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>Keystore </span></p>
<p><span>要签名一个</span><span> JAR </span><span>文件，必须首先有一个私钥。私钥及其相关的公钥证书存储在名为</span><span> keystores </span><span>的、有密码保护的数据库中。</span><span>JDK </span><span>包含创建和修改</span><span> keystores </span><span>的工具。</span><span>keystore </span><span>中的每一个密钥都可以用一个别名标识，它通常是拥有这个密钥的签名者的名字。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>所有</span><span> keystore </span><span>项</span><span>(</span><span>密钥和信任的证书项</span><span>)</span><span>都是用唯一别名访问的。别名是在用</span><span> keytool -genkey </span><span>命令生成密钥对</span><span>(</span><span>公钥和私钥</span><span>)</span><span>并在</span><span> keystore </span><span>中添加项时指定的。之后的</span><span> keytool </span><span>命令必须使用同样的别名引用这一项。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>例如，要用别名&#8220;</span><span>james</span><span>&#8221;生成一个新的公钥</span><span>/</span><span>私钥对并将公钥包装到自签名的证书中，要使用下述命令：</span> </p>
<p><span>keytool -genkey -alias james -keypass jamespass </span></p>
<p><span>-validity 80 -keystore jamesKeyStore </span></p>
<p><span>-storepass jamesKeyStorePass </span></p>
<p>&nbsp;</p>
<p><span>这个命令序列指定了一个初始密码&#8220;</span><span>jamespass</span><span>&#8221;，后续的命令在访问</span><span> keystore </span><span>&#8220;</span><span>jamesKeyStore</span><span>&#8221;中与别名&#8220;</span><span>james</span><span>&#8221;相关联的私钥时，就需要这个密码。如果</span><span> keystore</span><span>&#8220;</span><span>jamesKeyStore</span><span>&#8221;不存在，则</span><span> keytool </span><span>会自动创建它。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>jarsigner </span><span>工具</span><span> </span></p>
<p><span>jarsigner </span><span>工具使用</span><span> keystore </span><span>生成或者验证</span><span> JAR </span><span>文件的数字签名。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>假设像上述例子那样创建了</span><span> keystore </span><span>&#8220;</span><span>jamesKeyStore</span><span>&#8221;，并且它包含一个别名为&#8220;</span><span>james</span><span>&#8221;的密钥，可以用下面的命令签名一个</span><span> JAR </span><span>文件：</span> </p>
<p>&nbsp;</p>
<p><span>jarsigner -keystore jamesKeyStore -storepass jamesKeyStorePass </span></p>
<p><span>-keypass jamespass -signedjar SSample.jar Sample.jar james </span></p>
<p>&nbsp;</p>
<p><span>这个命令用密码&#8220;</span><span>jamesKeyStorePass</span><span>&#8221;从名为&#8220;</span><span>jamesKeyStore</span><span>&#8221;的</span><span> keystore </span><span>中提出别名为&#8220;</span><span>james</span><span>&#8221;、密码为&#8220;</span><span>jamespass</span><span>&#8221;的密钥，并对</span><span> Sample.jar </span><span>文件签名、创建一个签名的</span><span> JAR -- SSample.jar</span><span>。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>jarsigner </span><span>工具还可以验证一个签名的</span><span> JAR </span><span>文件，这种操作比签名</span><span> JAR </span><span>文件要简单得多，只需执行以下命令：</span> </p>
<p><span>jarsigner -verify SSample.jar </span></p>
<p>&nbsp;</p>
<p><span>如果签名的</span><span> JAR </span><span>文件没有被篡改过，那么</span><span> jarsigner </span><span>工具就会告诉您</span><span> JAR </span><span>通过验证了。否则，它会抛出一个</span><span> SecurityException</span><span>，</span> <span>表明哪些文件没有通过验证。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>还可以用</span><span> java.util.jar </span><span>和</span><span> java.security API </span><span>以编程方式签名</span><span> JAR(</span><span>有关细节参阅参考资料</span><span>)</span><span>。也可以使用像</span><span> Netscape Object Signing Tool </span><span>这样的工具。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>JAR </span><span>索引</span><span> </span></p>
<p><span>如果一个应用程序或者</span><span> applet </span><span>捆绑到多个</span><span> JAR </span><span>文件中，那么类装载器就使用一个简单的线性搜索算法搜索类路径中的每一个元素，这使类装载器可能要下载并打开许多个</span><span> JAR </span><span>文件，直到找到所要的类或者资源。如果类装载器试图寻找一个不存在的资源，那么在应用程序或者</span><span> applet </span><span>中的所有</span><span> JAR </span><span>文件都会下载。对于大型的网络应用程序和</span><span> applet</span><span>，这会导致启动缓慢、响应迟缓并浪费带宽。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>从</span><span> JDK 1.3 </span><span>以后，</span><span>JAR </span><span>文件格式开始支持索引以优化网络应用程序中类的搜索过程，特别是</span><span> applet</span><span>。</span><span>JarIndex </span><span>机制收集在</span><span> applet </span><span>或者应用程序中定义的所有</span><span> JAR </span><span>文件的内容，并将这些信息存储到第一个</span><span> JAR </span><span>文件中的索引文件中。下载了第一个</span><span> JAR </span><span>文件后，</span><span>applet </span><span>类装载器将使用收集的内容信息高效地装载</span><span> JAR </span><span>文件。这个目录信息存储在根</span><span> JAR </span><span>文件的</span><span> META-INF </span><span>目录中的一个名为</span><span> INDEX.LIST </span><span>的简单文本文件中。</span><span> </span></p>
<p>&nbsp;</p>
<p><span>创建一个</span><span> JarIndex </span></p>
<p><span>可以通过在</span><span> jar </span><span>命令中指定</span><span> -i </span><span>选项创建一个</span><span> JarIndex</span><span>。假设我们的目录结构如下图所示：</span><span> </span></p>
<p>&nbsp;</p>
<p><span>图</span><span> 2. JarIndex </span></p>
<p>&nbsp;</p>
<p><span>您将使用下述命令为</span><span> JarIndex_Main.jar</span><span>、</span><span>JarIndex_test.jar </span><span>和</span><span> JarIndex_test1.jar </span><span>创建一个索引文件：</span> </p>
<p>&nbsp;</p>
<p><span>jar -i JarIndex_Main.jar JarIndex_test.jar SampleDir/JarIndex_test1.jar </span></p>
<p>&nbsp;</p>
<p><span>INDEX.LIST </span><span>文件的格式很简单，包含每个已索引的</span><span> JAR </span><span>文件中包含的包或者类的名字，如清单</span><span> 2 </span><span>所示：</span><span> </span></p>
<p>&nbsp;</p>
<p><span>清单</span><span> 2. JarIndex INDEX.LIST </span><span>文件示例</span><span> </span></p>
<p>&nbsp;</p>
<p><span>JarIndex-Version: 1.0 </span></p>
<p>&nbsp;</p>
<p><span>JarIndex_Main.jar </span></p>
<p><span>sp </span></p>
<p>&nbsp;</p>
<p><span>JarIndex_test.jar </span></p>
<p><span>Sample </span></p>
<p>&nbsp;</p>
<p><span>SampleDir/JarIndex_test1.jar </span></p>
<p><span>org </span></p>
<p><span>org/apache </span></p>
<p><span>org/apache/xerces </span></p>
<p><span>org/apache/xerces/framework </span></p>
<p><span>org/apache/xerces/framework/xml4j </span></p>
<p>&nbsp;</p>
<p><span>结束语</span><span> </span></p>
<p><span>JAR </span><span>格式远远超出了一种压缩格式，它有许多可以改进效率、安全性和组织</span><span> Java </span><span>应用程序的功能。因为这些功能已经建立在核心平台</span><span> -- </span><span>包括编译器和类装载器</span><span> -- </span><span>中了，所以开发人员可以利用</span><span> JAR </span><span>文件格式的能力简化和改进开发和部署过程。</span><span>.</span></p>
<img src ="http://www.blogjava.net/franlk/aggbug/109605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-04-10 13:02 <a href="http://www.blogjava.net/franlk/articles/109605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]Ajax原理详细说明 [ 来自：ibm开发者网站 ]</title><link>http://www.blogjava.net/franlk/articles/104172.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Fri, 16 Mar 2007 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/104172.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/104172.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/104172.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/104172.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/104172.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://hi.baidu.com/momoca/blog/item/247c43a9a64e9dfc1e17a2c6.html">http://hi.baidu.com/momoca/blog/item/247c43a9a64e9dfc1e17a2c6.html</a><br /><br /><div class="tit">Ajax原理详细说明 [ 来自：ibm开发者网站 ]</div><div class="date">2006年11月17日 星期五 下午 05:44</div><table style="TABLE-LAYOUT: fixed"><tbody><tr><td><div class="cnt">Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成，这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本文的作者是一位 Ajax 专家，他演示了这些技术如何协同工作 —— 从总体概述到细节的讨论 —— 使高效的 Web 开发成为现实。他还揭开了 Ajax 核心概念的神秘面纱，包括 XMLHttpRequest 对象。<br />五年前，如果不知道 XML，您就是一只无人重视的丑小鸭。十八个月前，Ruby 成了关注的中心，不知道 Ruby 的程序员只能坐冷板凳了。今天，如果想跟上最新的技术时尚，那您的目标就是 Ajax。<br />但是，Ajax 不仅仅是一种时尚，它是一种构建网站的强大方法，而且不像学习一种全新的语言那样困难。<br />但在详细探讨 Ajax 是什么之前，先让我们花几分钟了解 Ajax 做什么。目前，编写应用程序时有两种基本的选择：<br /><br />    * 桌面应用程序<br />    * Web 应用程序 <br /><br />两者是类似的，桌面应用程序通常以 CD 为介质（有时候可从网站下载）并完全安装到您的计算机上。桌面应用程序可能使用互联网下载更新，但运行这些应用程序的代码在桌面计算机上。Web 应用程序运行在某处的 Web 服务器上 —— 毫不奇怪，要通过 Web 浏览器访问这种应用程序。<br />不过，比这些应用程序的运行代码放在何处更重要的是，应用程序如何运转以及如何与其进行交互。桌面应用程序一般很快（就在您的计算机上运行，不用等待互联网连接），具有漂亮的用户界面（通常和操作系统有关）和非凡的动态性。可以单击、选择、输入、打开菜单和子菜单、到处巡游，基本上不需要等待。<br />另一方面，Web 应用程序是最新的潮流，它们提供了在桌面上不能实现的服务（比如 Amazon.com 和 eBay）。但是，伴随着 Web 的强大而出现的是等待，等待服务器响应，等待屏幕刷新，等待请求返回和生成新的页面。<br />显然这样说过于简略了，但基本的概念就是如此。您可能已经猜到，Ajax 尝试建立桌面应用程序的功能和交互性，与不断更新的 Web 应用程序之间的桥梁。可以使用像桌面应用程序中常见的动态用户界面和漂亮的控件，不过是在 Web 应用程序中。<br />还等什么呢？我们来看看 Ajax 如何将笨拙的 Web 界面转化成能迅速响应的 Ajax 应用程序吧。<br />老技术，新技巧<br />在谈到 Ajax 时，实际上涉及到多种技术，要灵活地运用它必须深入了解这些不同的技术（本系列的头几篇文章将分别讨论这些技术）。好消息是您可能已经非常熟悉其中的大部分技术，更好的是这些技术都很容易学习，并不像完整的编程语言（如 Java 或 Ruby）那样困难。<br />Ajax 的定义<br />顺便说一下，Ajax 是 Asynchronous JavaScript and XML（以及 DHTML 等）的缩写。这个短语是 Adaptive Path 的 Jesse James Garrett 发明的（请参阅 参考资料），按照 Jesse 的解释，这不是个首字母缩写词。<br />下面是 Ajax 应用程序所用到的基本技术：<br /><br />    * HTML 用于建立 Web 表单并确定应用程序其他部分使用的字段。<br />    * JavaScript 代码是运行 Ajax 应用程序的核心代码，帮助改进与服务器应用程序的通信。<br />    * DHTML 或 Dynamic HTML，用于动态更新表单。我们将使用div、span和其他动态 HTML 元素来标记 HTML。<br />    * 文档对象模型 DOM 用于（通过 JavaScript 代码）处理 HTML 结构和（某些情况下）服务器返回的 XML。 <br /><br />我们来进一步分析这些技术的职责。以后的文章中我将深入讨论这些技术，目前只要熟悉这些组件和技术就可以了。对这些代码越熟悉，就越容易从对这些技术的零散了解转变到真正把握这些技术（同时也真正打开了 Web 应用程序开发的大门）。<br />XMLHttpRequest 对象<br />要了解的一个对象可能对您来说也是最陌生的，即XMLHttpRequest。这是一个 JavaScript 对象，创建该对象很简单，如清单 1 所示。<br /><br />清单 1. 创建新的 XMLHttpRequest 对象<br /> <br />&lt;script language="javascript" type="text/javascript"&gt;<br />var xmlHttp = new XMLHttpRequest();<br />&lt;/script&gt;<br /> <br />下一期文章中将进一步讨论这个对象，现在要知道这是处理所有服务器通信的对象。继续阅读之前，先停下来想一想：通过XMLHttpRequest对象与服务器进行对话的是 JavaScript 技术。这不是一般的应用程序流，这恰恰是 Ajax 的强大功能的来源。<br />在一般的 Web 应用程序中，用户填写表单字段并单击 Submit 按钮。然后整个表单发送到服务器，服务器将它转发给处理表单的脚本（通常是 PHP 或 Java，也可能是 CGI 进程或者类似的东西），脚本执行完成后再发送回全新的页面。该页面可能是带有已经填充某些数据的新表单的 HTML，也可能是确认页面，或者是具有根据原来表单中输入数据选择的某些选项的页面。当然，在服务器上的脚本或程序处理和返回新表单时用户必须等待。屏幕变成一片空白，等到服务器返回数据后再重新绘制。这就是交互性差的原因，用户得不到立即反馈，因此感觉不同于桌面应用程序。<br />Ajax 基本上就是把 JavaScript 技术和XMLHttpRequest对象放在 Web 表单和服务器之间。当用户填写表单时，数据发送给一些 JavaScript 代码而不是直接发送给服务器。相反，JavaScript 代码捕获表单数据并向服务器发送请求。同时用户屏幕上的表单也不会闪烁、消失或延迟。换句话说，JavaScript 代码在幕后发送请求，用户甚至不知道请求的发出。更好的是，请求是异步发送的，就是说 JavaScript 代码（和用户）不用等待服务器的响应。因此用户可以继续输入数据、滚动屏幕和使用应用程序。<br />然后，服务器将数据返回 JavaScript 代码（仍然在 Web 表单中），后者决定如何处理这些数据。它可以迅速更新表单数据，让人感觉应用程序是立即完成的，表单没有提交或刷新而用户得到了新数据。JavaScript 代码甚至可以对收到的数据执行某种计算，再发送另一个请求，完全不需要用户干预！这就是XMLHttpRequest的强大之处。它可以根据需要自行与服务器进行交互，用户甚至可以完全不知道幕后发生的一切。结果就是类似于桌面应用程序的动态、快速响应、高交互性的体验，但是背后又拥有互联网的全部强大力量。<br />加入一些 JavaScript<br />得到XMLHttpRequest的句柄后，其他的 JavaScript 代码就非常简单了。事实上，我们将使用 JavaScript 代码完成非常基本的任务：<br /><br />    * 获取表单数据：JavaScript 代码很容易从 HTML 表单中抽取数据并发送到服务器。<br />    * 修改表单上的数据：更新表单也很简单，从设置字段值到迅速替换图像。<br />    * 解析 HTML 和 XML：使用 JavaScript 代码操纵 DOM（请参阅 下一节），处理 HTML 表单服务器返回的 XML 数据的结构。 <br /><br />对于前两点，需要非常熟悉getElementById()方法，如 清单 2 所示。<br /><br />清单 2. 用 JavaScript 代码捕获和设置字段值<br /> <br />// Get the value of the "phone" field and stuff it in a variable called phone<br />var phone = document.getElementById("phone").value;<br /> <br />// Set some values on a form using an array called response<br />document.getElementById("order").value = response[0];<br />document.getElementById("address").value = response[1];<br /> <br />这里没有特别需要注意的地方，真是好极了！您应该认识到这里并没有非常复杂的东西。只要掌握了XMLHttpRequest，Ajax 应用程序的其他部分就是如 清单 2 所示的简单 JavaScript 代码了，混合有少量的 HTML。同时，还要用一点儿 DOM，我们就来看看吧。<br />以 DOM 结束<br />最后还有 DOM，即文档对象模型。可能对有些读者来说 DOM 有点儿令人生畏，HTML 设计者很少使用它，即使 JavaScript 程序员也不大用到它，除非要完成某项高端编程任务。大量使用 DOM 的是复杂的 Java 和 C/C++ 程序，这可能就是 DOM 被认为难以学习的原因。<br />幸运的是，在 JavaScript 技术中使用 DOM 很容易，也非常直观。现在，按照常规也许应该说明如何使用 DOM，或者至少要给出一些示例代码，但这样做也可能误导您。即使不理会 DOM，仍然能深入地探讨 Ajax，这也是我准备采用的方法。以后的文章将再次讨论 DOM，现在只要知道可能需要 DOM 就可以了。当需要在 JavaScript 代码和服务器之间传递 XML 和改变 HTML 表单的时候，我们再深入研究 DOM。没有它也能做一些有趣的工作，因此现在就把 DOM 放到一边吧。<br /> <br />回页首<br /> <br />获取 Request 对象<br />有了上面的基础知识后，我们来看看一些具体的例子。XMLHttpRequest是 Ajax 应用程序的核心，而且对很多读者来说可能还比较陌生，我们就从这里开始吧。从 清单 1 可以看出，创建和使用这个对象非常简单，不是吗？等一等。<br />还记得几年前的那些讨厌的浏览器战争吗？没有一样东西在不同的浏览器上得到同样的结果。不管您是否相信，这些战争仍然在继续，虽然规模较小。但令人奇怪的是，XMLHttpRequest成了这场战争的牺牲品之一。因此获得XMLHttpRequest对象可能需要采用不同的方法。下面我将详细地进行解释。<br />使用 Microsoft 浏览器<br />Microsoft 浏览器 Internet Explorer 使用 MSXML 解析器处理 XML（可以通过 参考资料 进一步了解 MSXML）。因此如果编写的 Ajax 应用程序要和 Internet Explorer 打交道，那么必须用一种特殊的方式创建对象。<br />但并不是这么简单。根据 Internet Explorer 中安装的 JavaScript 技术版本不同，MSXML 实际上有两种不同的版本，因此必须对这两种情况分别编写代码。请参阅 清单 3，其中的代码在 Microsoft 浏览器上创建了一个XMLHttpRequest。<br /><br />清单 3. 在 Microsoft 浏览器上创建 XMLHttpRequest 对象<br /> <br />var xmlHttp = false;<br />try {<br /> xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");<br />} catch (e) {<br /> try {<br />    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");<br /> } catch (e2) {<br />    xmlHttp = false;<br /> }<br />}<br /> <br />您对这些代码可能还不完全理解，但没有关系。当本系列文章结束的时候，您将对 JavaScript 编程、错误处理、条件编译等有更深的了解。现在只要牢牢记住其中的两行代码：<br />xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");<br />和<br />xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");。<br />这两行代码基本上就是尝试使用一个版本的 MSXML 创建对象，如果失败则使用另一个版本创建该对象。不错吧？如果都不成功，则将xmlHttp变量设为 false，告诉您的代码出现了问题。如果出现这种情况，可能是因为安装了非 Microsoft 浏览器，需要使用不同的代码。<br />处理 Mozilla 和非 Microsoft 浏览器<br />如果选择的浏览器不是 Internet Explorer，或者为非 Microsoft 浏览器编写代码，就需要使用不同的代码。事实上就是 清单 1 所示的一行简单代码：<br />var xmlHttp = new XMLHttpRequest object;。<br />这行简单得多的代码在 Mozilla、Firefox、Safari、Opera 以及基本上所有以任何形式或方式支持 Ajax 的非 Microsoft 浏览器中，创建了XMLHttpRequest对象。<br />结合起来<br />关键是要支持所有浏览器。谁愿意编写一个只能用于 Internet Explorer 或者非 Microsoft 浏览器的应用程序呢？或者更糟，要编写一个应用程序两次？当然不！因此代码要同时支持 Internet Explorer 和非 Microsoft 浏览器。清单 4 显示了这样的代码。<br /><br />清单 4. 以支持多种浏览器的方式创建 XMLHttpRequest 对象<br /> <br />/* Create a new XMLHttpRequest object to talk to the Web server */<br />var xmlHttp = false;<br />/*@cc_on @*/<br />/*@if (@_jscript_version &gt;= 5)<br />try {<br /> xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");<br />} catch (e) {<br /> try {<br />    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");<br /> } catch (e2) {<br />    xmlHttp = false;<br /> }<br />}<br />@end @*/<br /> <br />if (!xmlHttp &amp;&amp; typeof XMLHttpRequest != 'undefined') {<br /> xmlHttp = new XMLHttpRequest();<br />}<br /> <br />现在先不管那些注释掉的奇怪符号，如@cc_on，这是特殊的 JavaScript 编译器命令，将在下一期针对XMLHttpRequest的文章中详细讨论。这段代码的核心分为三步：<br />1.       建立一个变量xmlHttp来引用即将创建的XMLHttpRequest对象。<br />2.       尝试在 Microsoft 浏览器中创建该对象：<br />o        尝试使用Msxml2.XMLHTTP对象创建它。<br />o        如果失败，再尝试Microsoft.XMLHTTP对象。<br />3.       如果仍然没有建立xmlHttp，则以非 Microsoft 的方式创建该对象。<br />最后，xmlHttp应该引用一个有效的XMLHttpRequest对象，无论运行什么样的浏览器。<br />关于安全性的一点说明<br />安全性如何呢？现在浏览器允许用户提高他们的安全等级，关闭 JavaScript 技术，禁用浏览器中的任何选项。在这种情况下，代码无论如何都不会工作。此时必须适当地处理问题，这需要单独的一篇文章来讨论，要放到以后了（这个系列够长了吧？不用担心，读完之前也许您就掌握了）。现在要编写一段健壮但不够完美的代码，对于掌握 Ajax 来说就很好了。以后我们还将讨论更多的细节。<br /> <br />回页首<br /> <br />Ajax 世界中的请求/响应<br />现在我们介绍了 Ajax，对XMLHttpRequest对象以及如何创建它也有了基本的了解。如果阅读得很仔细，您可能已经知道与服务器上的 Web 应用程序打交道的是 JavaScript 技术，而不是直接提交给那个应用程序的 HTML 表单。<br />还缺少什么呢？到底如何使用XMLHttpRequest。因为这段代码非常重要，您编写的每个 Ajax 应用程序都要以某种形式使用它，先看看 Ajax 的基本请求/响应模型是什么样吧。<br />发出请求<br />您已经有了一个崭新的XMLHttpRequest对象，现在让它干点活儿吧。首先需要一个 Web 页面能够调用的 JavaScript 方法（比如当用户输入文本或者从菜单中选择一项时）。接下来就是在所有 Ajax 应用程序中基本都雷同的流程：<br />1.       从 Web 表单中获取需要的数据。<br />2.       建立要连接的 URL。<br />3.       打开到服务器的连接。<br />4.       设置服务器在完成后要运行的函数。<br />5.       发送请求。<br />清单 5 中的示例 Ajax 方法就是按照这个顺序组织的：<br /><br />清单 5. 发出 Ajax 请求<br /> <br />function callServer() {<br /> // Get the city and state from the web form<br /> var city = document.getElementById("city").value;<br /> var state = document.getElementById("state").value;<br /> // Only go on if there are values for both fields<br /> if ((city == null) || (city == "")) return;<br /> if ((state == null) || (state == "")) return;<br /> <br /> // Build the URL to connect to<br /> var url = "/scripts/getZipCode.php?city=" + escape(city) + "&amp;state=" + escape(state);<br /> <br /> // Open a connection to the server<br /> xmlHttp.open("GET", url, true);<br /> <br /> // Setup a function for the server to run when it's done<br /> xmlHttp.onreadystatechange = updatePage;<br /> <br /> // Send the request<br /> xmlHttp.send(null);<br />}<br /> <br />其中大部分代码意义都很明确。开始的代码使用基本 JavaScript 代码获取几个表单字段的值。然后设置一个 PHP 脚本作为链接的目标。要注意脚本 URL 的指定方式，city 和 state（来自表单）使用简单的 GET 参数附加在 URL 之后。<br />然后打开一个连接，这是您第一次看到使用XMLHttpRequest。其中指定了连接方法（GET）和要连接的 URL。最后一个参数如果设为true，那么将请求一个异步连接（这就是 Ajax 的由来）。如果使用false，那么代码发出请求后将等待服务器返回的响应。如果设为true，当服务器在后台处理请求的时候用户仍然可以使用表单（甚至调用其他 JavaScript 方法）。<br />xmlHttp（要记住，这是XMLHttpRequest对象实例）的onreadystatechange属性可以告诉服务器在运行完成后（可能要用五分钟或者五个小时）做什么。因为代码没有等待服务器，必须让服务器知道怎么做以便您能作出响应。在这个示例中，如果服务器处理完了请求，一个特殊的名为updatePage()的方法将被触发。<br />最后，使用值null调用send()。因为已经在请求 URL 中添加了要发送给服务器的数据（city 和 state），所以请求中不需要发送任何数据。这样就发出了请求，服务器按照您的要求工作。<br />如果没有发现任何新鲜的东西，您应该体会到这是多么简单明了！除了牢牢记住 Ajax 的异步特性外，这些内容都相当简单。应该感激 Ajax 使您能够专心编写漂亮的应用程序和界面，而不用担心复杂的 HTTP 请求/响应代码。<br />清单 5 中的代码说明了 Ajax 的易用性。数据是简单的文本，可以作为请求 URL 的一部分。用 GET 而不是更复杂的 POST 发送请求。没有 XML 和要添加的内容头部，请求体中没有要发送的数据；换句话说，这就是 Ajax 的乌托邦。<br />不用担心，随着本系列文章的展开，事情会变得越来越复杂。您将看到如何发送 POST 请求、如何设置请求头部和内容类型、如何在消息中编码 XML、如何增加请求的安全性，可以做的工作还有很多！暂时先不用管那些难点，掌握好基本的东西就行了，很快我们就会建立一整套的 Ajax 工具库。<br />处理响应<br />现在要面对服务器的响应了。现在只要知道两点：<br /><br />    * 什么也不要做，直到xmlHttp.readyState属性的值等于 4。<br />    * 服务器将把响应填充到xmlHttp.responseText属性中。 <br /><br />其中的第一点，即就绪状态，将在下一篇文章中详细讨论，您将进一步了解 HTTP 请求的阶段，可能比您设想的还多。现在只要检查一个特定的值（4）就可以了（下一期文章中还有更多的值要介绍）。第二点，使用xmlHttp.responseText属性获得服务器的响应，这很简单。清单 6 中的示例方法可供服务器根据 清单 5 中发送的数据调用。<br /><br />清单 6. 处理服务器响应<br /> <br />function updatePage() {<br /> if (xmlHttp.readyState == 4) {<br />    var response = xmlHttp.responseText;<br />    document.getElementById("zipCode").value = response;<br /> }<br />}<br /> <br />这些代码同样既不难也不复杂。它等待服务器调用，如果是就绪状态，则使用服务器返回的值（这里是用户输入的城市和州的 ZIP 编码）设置另一个表单字段的值。于是包含 ZIP 编码的zipCode字段突然出现了，而用户没有按任何按钮！这就是前面所说的桌面应用程序的感觉。快速响应、动态感受等等，这些都只因为有了小小的一段 Ajax 代码。<br />细心的读者可能注意到zipCode是一个普通的文本字段。一旦服务器返回 ZIP 编码，updatePage()方法就用城市/州的 ZIP 编码设置那个字段的值，用户就可以改写该值。这样做有两个原因：保持例子简单，说明有时候可能希望用户能够修改服务器返回的数据。要记住这两点，它们对于好的用户界面设计来说很重要。<br /> <br />回页首<br /> <br />连接 Web 表单<br />还有什么呢？实际上没有多少了。一个 JavaScript 方法捕捉用户输入表单的信息并将其发送到服务器，另一个 JavaScript 方法监听和处理响应，并在响应返回时设置字段的值。所有这些实际上都依赖于调用第一个 JavaScript 方法，它启动了整个过程。最明显的办法是在 HTML 表单中增加一个按钮，但这是 2001 年的办法，您不这样认为吗？还是像 清单 7 这样利用 JavaScript 技术吧。<br /><br />清单 7. 启动一个 Ajax 过程<br /> <br />&lt;form&gt;<br /> &lt;p&gt;City: &lt;input type="text" name="city" id="city" size="25"<br />       onChange="callServer();" /&gt;&lt;/p&gt;<br /> &lt;p&gt;State: &lt;input type="text" name="state" id="state" size="25"<br />       onChange="callServer();" /&gt;&lt;/p&gt;<br /> &lt;p&gt;Zip Code: &lt;input type="text" name="zipCode" id="city" size="5" /&gt;&lt;/p&gt;<br />&lt;/form&gt;<br /> <br />如果感觉这像是一段相当普通的代码，那就对了，正是如此！当用户在 city 或 state 字段中输入新的值时，callServer()方法就被触发，于是 Ajax 开始运行了。有点儿明白怎么回事了吧？好，就是如此！<br /> <br />回页首<br /> <br />结束语<br />现在您可能已经准备开始编写第一个 Ajax 应用程序了，至少也希望认真读一下 参考资料 中的那些文章了吧？但可以首先从这些应用程序如何工作的基本概念开始，对XMLHttpRequest对象有基本的了解。在下一期文章中，您将掌握这个对象，学会如何处理 JavaScript 和服务器的通信、如何使用 HTML 表单以及如何获得 DOM 句柄。<br />现在先花点儿时间考虑考虑 Ajax 应用程序有多么强大。设想一下，当单击按钮、输入一个字段、从组合框中选择一个选项或者用鼠标在屏幕上拖动时，Web 表单能够立刻作出响应会是什么情形。想一想异步究竟意味着什么，想一想 JavaScript 代码运行而且不等待服务器对它的请求作出响应。会遇到什么样的问题？会进入什么样的领域？考虑到这种新的方法，编程的时候应如何改变表单的设计？<br />如果在这些问题上花一点儿时间，与简单地剪切/粘贴某些代码到您根本不理解的应用程序中相比，收益会更多。在下一期文章中，我们将把这些概念付诸实践，详细介绍使应用程序按照这种方式工作所需要的代码。因此，现在先享受一下 Ajax 所带来的可能性吧。</div></td></tr></tbody></table><img src ="http://www.blogjava.net/franlk/aggbug/104172.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-03-16 10:37 <a href="http://www.blogjava.net/franlk/articles/104172.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]用java实现浮点数的精确计算</title><link>http://www.blogjava.net/franlk/articles/95926.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Thu, 25 Jan 2007 06:34:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/95926.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/95926.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/95926.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/95926.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/95926.html</trackback:ping><description><![CDATA[
		<p>摘录地址：<a href="http://www.javajsp.net/javablog/blog/200607/2404.html">http://www.javajsp.net/javablog/blog/200607/2404.html</a><br /><br /><font size="2">问题的提出：<br /><br />如果我们编译运行下面这个程序会看到什么？<br /><br />public class Test{<br /><br />public static void main(String args[]){<br /><br />System.out.println(0.05+0.01);<br /><br />System.out.println(1.0-0.42);<br /><br />System.out.println(4.015*100);<br /><br />System.out.println(123.3/100);<br /><br />}<br /><br />};<br /><br />你没有看错！结果确实是<br /><br />0.060000000000000005<br /><br />0.5800000000000001<br /><br />401.49999999999994<br /><br />1.2329999999999999<br /><br />Java中的简单浮点数类型float和double不能够进行运算。不光是Java，在其它很多编程<br />语言中也有这样的问题。在大多数情况下，计算的结果是准确的，但是多试几次（可以做<br />一个循环）就可以试出类似上面的错误。现在终于理解为什么要有BCD码了。<br /><br />这个问题相当严重，如果你有9.999999999999元，你的计算机是不会认为你可以购买10元<br />的商品的。<br /><br />在有的编程语言中提供了专门的货币类型来处理这种情况，但是Java没有。现在让我们看<br />看如何解决这个问题。<br /><br /><br /><br />四舍五入<br /><br />我们的第一个反应是做四舍五入。Math类中的round方法不能设置保留几位小数，我们只<br />能象这样（保留两位）：<br /><br />public double round(double value){<br /><br />return Math.round(value*100)/100.0;<br /><br />}<br /><br />非常不幸，上面的代码并不能正常工作，给这个方法传入4.015它将返回4.01而不是<br />4.02，如我们在上面看到的<br /><br />4.015*100=401.49999999999994<br /><br />因此如果我们要做到精确的四舍五入，不能利用简单类型做任何运算<br /><br />java.text.DecimalFormat也不能解决这个问题：<br /><br />System.out.println(new java.text.DecimalFormat("0.00").format(4.025));<br /><br />输出是4.02<br /><br /><br /><br />BigDecimal<br />在《Effective Java》这本书中也提到这个原则，float和double只能用来做科学计算或者<br />是工程计算，在商业计算中我们要用 java.math.BigDecimal。BigDecimal一共有4个够造<br />方法，我们不关心用BigInteger来够造的那两个，那么还有两个，它们是：<br /><br />BigDecimal(double val)<br /><br />Translates a double into a BigDecimal.<br /><br />BigDecimal(String val)<br /><br />Translates the String repre sentation of a BigDecimal into a BigDecimal.<br /><br />上面的API简要描述相当的明确，而且通常情况下，上面的那一个使用起来要方便一些。<br />我们可能想都不想就用上了，会有什么问题呢？等到出了问题的时候，才发现上面哪个够<br />造方法的详细说明中有这么一段：<br /><br />Note: the results of this constructor can be somewhat unpredictable. One might<br />assume that new BigDecimal(.1) is exactly equal to .1, but it is actually<br />equal to .1000000000000000055511151231257827021181583404541015625. This is so<br />because .1 cannot be represented exactly as a double (or, for that matter, as<br />a binary fraction of any finite length). Thus, the long value that is being<br />passed in to the constructor is not exactly equal to .1, appearances<br />nonwithstanding.<br /><br />The (String) constructor, on the other hand, is perfectly predictable: new<br />BigDecimal(".1") is exactly equal to .1, as one would expect. Therefore, it is<br />generally recommended that the (String) constructor be used in preference to<br />this one.<br /><br /><br /><br />原来我们如果需要精确计算，非要用String来够造BigDecimal不可！在《Effective Java》<br />一书中的例子是用String来够造BigDecimal的，但是书上却没有强调这一点，这也许是一<br />个小小的失误吧。<br /><br /><br /><br />解决方案<br /><br />现在我们已经可以解决这个问题了，原则是使用BigDecimal并且一定要用String来够造。<br /><br />但是想像一下吧，如果我们要做一个加法运算，需要先将两个浮点数转为String，然后够<br />造成BigDecimal，在其中一个上调用add方法，传入另一个作为参数，然后把运算的结果<br />（BigDecimal）再转换为浮点数。你能够忍受这么烦琐的过程吗？下面我们提供一个工具<br />类Arith来简化操作。它提供以下静态方法，包括加减乘除和四舍五入：<br /><br />public static double add(double v1,double v2)<br /><br />public static double sub(double v1,double v2)<br /><br />public static double mul(double v1,double v2)<br /><br />public static double div(double v1,double v2)<br /><br />public static double div(double v1,double v2,int scale)<br /><br />public static double round(double v,int scale)<br /><br /><br /><br />附录<br /><br /><br /><br />源文件Arith.java：<br /><br /><br /><br />import java.math.BigDecimal;<br /><br /><br /><br />/**<br /><br />* 由于Java的简单类型不能够精确的对浮点数进行运算，这个工具类提供精<br /><br />* 确的浮点数运算，包括加减乘除和四舍五入。<br /><br />*/<br /><br />public class Arith{<br /><br /><br /><br />//默认除法运算精度<br /><br />private static final int DEF_DIV_SCALE = 10;<br /><br /><br /><br />//这个类不能实例化<br /><br />private Arith(){<br /><br />}<br /><br /><br /><br /><br /><br />/**<br /><br />* 提供精确的加法运算。<br /><br />* @param v1 被加数<br /><br />* @param v2 加数<br /><br />* @return 两个参数的和<br /><br />*/<br /><br />public static double add(double v1,double v2){<br /><br />BigDecimal b1 = new BigDecimal(Double.toString(v1));<br /><br />BigDecimal b2 = new BigDecimal(Double.toString(v2));<br /><br />return b1.add(b2).doubleValue();<br /><br />}<br /><br /><br /><br />/**<br /><br />* 提供精确的减法运算。<br /><br />* @param v1 被减数<br /><br />* @param v2 减数<br /><br />* @return 两个参数的差<br /><br />*/<br /><br />public static double sub(double v1,double v2){<br /><br />BigDecimal b1 = new BigDecimal(Double.toString(v1));<br /><br />BigDecimal b2 = new BigDecimal(Double.toString(v2));<br /><br />return b1.subtract(b2).doubleValue();<br /><br />}<br /><br /><br /><br />/**<br /><br />* 提供精确的乘法运算。<br /><br />* @param v1 被乘数<br /><br />* @param v2 乘数<br /><br />* @return 两个参数的积<br /><br />*/<br /><br />public static double mul(double v1,double v2){<br /><br />BigDecimal b1 = new BigDecimal(Double.toString(v1));<br /><br />BigDecimal b2 = new BigDecimal(Double.toString(v2));<br /><br />return b1.multiply(b2).doubleValue();<br /><br />}<br /><br /><br /><br />/**<br /><br />* 提供（相对）精确的除法运算，当发生除不尽的情况时，精确到<br /><br />* 小数点以后10位，以后的数字四舍五入。<br /><br />* @param v1 被除数<br /><br />* @param v2 除数<br /><br />* @return 两个参数的商<br /><br />*/<br /><br />public static double div(double v1,double v2){<br /><br />return div(v1,v2,DEF_DIV_SCALE);<br /><br />}<br /><br /><br /><br />/**<br /><br />* 提供（相对）精确的除法运算。当发生除不尽的情况时，由scale参数指<br /><br />* 定精度，以后的数字四舍五入。<br /><br />* @param v1 被除数<br /><br />* @param v2 除数<br /><br />* @param scale 表示表示需要精确到小数点以后几位。<br /><br />* @return 两个参数的商<br /><br />*/<br /><br />public static double div(double v1,double v2,int scale){<br /><br />if(scale&lt;0){<br /><br />throw new IllegalArgumentException(<br /><br />"The scale must be a positive integer or zero");<br /><br />}<br /><br />BigDecimal b1 = new BigDecimal(Double.toString(v1));<br /><br />BigDecimal b2 = new BigDecimal(Double.toString(v2));<br /><br />return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();<br /><br />}<br /><br /><br /><br />/**<br /><br />* 提供精确的小数位四舍五入处理。<br /><br />* @param v 需要四舍五入的数字<br /><br />* @param scale 小数点后保留几位<br /><br />* @return 四舍五入后的结果<br /><br />*/<br /><br />public static double round(double v,int scale){<br /><br />if(scale&lt;0){<br /><br />throw new IllegalArgumentException(<br /><br />"The scale must be a positive integer or zero");<br /><br />}<br /><br />BigDecimal b = new BigDecimal(Double.toString(v));<br /><br />BigDecimal one = new BigDecimal("1");<br /><br />return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();<br /><br />}<br /><br />}</font></p>
<img src ="http://www.blogjava.net/franlk/aggbug/95926.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2007-01-25 14:34 <a href="http://www.blogjava.net/franlk/articles/95926.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]有效编写软件的75条建议</title><link>http://www.blogjava.net/franlk/articles/87456.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Wed, 13 Dec 2006 04:51:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/87456.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/87456.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/87456.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/87456.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/87456.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://community.csdn.net/Expert/TopicView3.asp?id=5213848">http://community.csdn.net/Expert/TopicView3.asp?id=5213848</a><br /><br />1. 你们的项目组使用源代码管理工具了么？<br />　　　　应该用。VSS、CVS、PVCS、ClearCase、CCC/Harvest、FireFly都可以。我的选择是VSS。<br /><br />　　 2. 你们的项目组使用缺陷管理系统了么？<br />　　　　应该用。ClearQuest太复杂，我的推荐是BugZilla。 <br /><br />　　3. 你们的测试组还在用Word写测试用例么？<br />　　　　不要用Word写测试用例（Test Case）。应该用一个专门的系统，可以是Test Manager，也可以是自己开发一个ASP.NET的小网站。主要目的是Track和Browse。<br /><br />　　4. 你们的项目组有没有建立一个门户网站？<br />　　　　要有一个门户网站，用来放Contact Info、Baselined Schedule、News等等。推荐Sharepoint Portal Server 2003来实现，15分钟就搞定。买不起SPS 2003可以用WSS (Windows Sharepoint Service)。 <br /><br />　　5. 你们的项目组用了你能买到最好的工具么？<br />　　　　应该用尽量好的工具来工作。比如，应该用VS.NET而不是Notepad来写C#。用Notepad写程序多半只是一种炫耀。但也要考虑到经费，所以说是“你能买到最好的”。 <br /><br />　　6. 你们的程序员工作在安静的环境里么？<br />　　　　需要安静环境。这点极端重要，而且要保证每个人的空间大于一定面积。 <br /><br />　　7. 你们的员工每个人都有一部电话么？<br />　　　 需要每人一部电话。而且电话最好是带留言功能的。当然，上这么一套带留言电话系统开销不小。不过至少每人一部电话要有，千万别搞得经常有人站起来喊：“某某某电话”。《人件》里面就强烈谴责这种做法。 <br /><br />　　8. 你们每个人都知道出了问题应该找谁么？<br />　　　　应该知道。任何一个Feature至少都应该有一个Owner，当然，Owner可以继续Dispatch给其他人。<br /><br />　　9. 你遇到过有人说“我以为…”么？<br />　　　　要消灭“我以为”。Never assume anything。 <br /><br />　　10. 你们的项目组中所有的人都坐在一起么？<br />　　　　需要。我反对Virtual Team，也反对Dev在美国、Test在中国这种开发方式。能坐在一起就最好坐在一起，好处多得不得了。 <br /><br />　　11. 你们的进度表是否反映最新开发进展情况？ <br />　　　　应该反映。但是，应该用Baseline的方法来管理进度表：维护一份稳定的Schedule，再维护一份最新更改。Baseline的方法也应该用于其它的Spec。Baseline是变更管理里面的一个重要手段。<br /><br />　　12. 你们的工作量是先由每个人自己估算的么？<br />　　　　应该让每个人自己估算。要从下而上估算工作量，而不是从上往下分派。除非有其他原因，比如政治任务工期固定等。 <br /><br />　　13. 你们的开发人员从项目一开始就加班么？<br />　　　　不要这样。不要一开始就搞疲劳战。从项目一开始就加班，只能说明项目进度不合理。当然，一些对日软件外包必须天天加班，那属于剥削的范畴。 <br /><br />　　14. 你们的项目计划中Buffer Time是加在每个小任务后面的么？<br />　　　　不要。Buffer Time加在每个小任务后面，很容易轻易的就被消耗掉。Buffer Time要整段的加在一个Milestone或者checkpoint前面。 <br /><br />　　15. 值得再多花一些时间，从95%做到100%好值得，非常值得。<br />　　　　尤其当项目后期人困马乏的时候，要坚持。这会给产品带来质的区别。 <br /><br />　　16. 登记新缺陷时，是否写清了重现步骤？<br />　　　　要。这属于Dev和Test之间的沟通手段。面对面沟通需要，详细填写Repro Steps也需要。 <br /><br />　　17. 写新代码前会把已知缺陷解决么？<br />　　　　要。每个人的缺陷不能超过10个或15个，否则必须先解决老的bug才能继续写新代码。 <br /><br />　　18. 你们对缺陷的轻重缓急有事先的约定么？<br />　　　　必须有定义。Severity要分1、2、3，约定好：蓝屏和Data Lost算Sev 1，Function Error算Sev 2，界面上的算Sev 3。但这种约定可以根据产品质量现状适当进行调整。<br /><br />　　19. 你们对意见不一的缺陷有三国会议么？<br />　　　　 必须要有。要有一个明确的决策过程。这类似于CCB (Change Control Board)的概念。 <br /><br />　　20. 所有的缺陷都是由登记的人最后关闭的么？ <br />　　　　Bug应该由Opener关闭。Dev不能私自关闭Bug。 <br /><br />　　21. 你们的程序员厌恶修改老的代码么？<br />　　　　厌恶是正常的。解决方法是组织Code Review，单独留出时间来。XP也是一个方法。<br /><br />　　22. 你们项目组有Team Morale Activity么？<br />　　　　每个月都要搞一次，吃饭、唱歌、Outing、打球、开卡丁车等等，一定要有。不要剩这些钱。 <br /><br />　　23. 你们项目组有自己的Logo么？<br />　　　　要有自己的Logo。至少应该有自己的Codename。 <br /><br />　　24. 你们的员工有印有公司Logo的T-Shirt么？<br />　　　　要有。能增强归属感。当然，T-Shirt要做的好看一些，最好用80支的棉来做。别没穿几次就破破烂烂的。<br /><br />　　25. 总经理至少每月参加次项目组会议要的。<br />　　　　要让team member觉得高层关注这个项目。<br /><br />　　26. 你们是给每个Dev开一个分支么？<br />　　　　反对。Branch的管理以及Merge的工作量太大，而且容易出错。 <br /><br />　　27. 有人长期不Check-In代码么？<br />　　　　不可以。对大部分项目来说，最多两三天就应该Check-In。 <br /><br />　　28. 在Check-In代码时都填写注释了么？<br />　　　　要写的，至少一两句话，比如“解决了Bug No.225”。如果往高处拔，这也算做“配置审计”的一部分。<br /><br />　　29. 有没有设定每天Check-In的最后期限？<br />　　　　要的，要明确Check-In Deadline。否则会Build Break。 <br /><br />　　30. 你们能把所有源码一下子编译成安装文件吗？ <br />　　　　要的。这是每日编译（Daily Build）的基础。而且必须要能够做成自动的。 <br /><br />　　31. 你们的项目组做每日编译么？<br />　　当然要做。有三样东西是软件项目/产品开发必备的：1. bug management; 2. source control; 3. daily build。 <br /><br />　　32. 你们公司有没有积累一个项目风险列表？<br />　　　　要。Risk Inventory。否则，下个项目开始的时候，又只能拍脑袋分析Risk了。<br /><br />　　33. 设计越简单越好越简单越好。<br />　　　　设计时候多一句话，将来可能就带来无穷无尽的烦恼。应该从一开始就勇敢的砍。这叫scope management。 <br /><br />　　34. 尽量利用现有的产品、技术、代码千万别什么东西都自己Coding。BizTalk和Sharepoint就是最好的例子，有这两个作为基础，可以把起点提高很多。或者可以尽量多用现成的Control之类的。或者尽量用XML，而不是自己去Parse一个文本文件；尽量用RegExp，而不是自己从头操作字符串，等等等等。这就是“软件复用”的体现。<br /><br />　　35. 你们会隔一段时间就停下来夯实代码么？<br />　　　　要。最好一个月左右一次。传言去年年初Windows组在Stevb的命令下停过一个月增强安全。Btw，“夯”这个字念“hang”，第一声。 <br /><br />　　36. 你们的项目组每个人都写Daily Report么？<br />　　　　要写。五分钟就够了，写10句话左右，告诉自己小组的人今天我干了什么。一则为了沟通，二则鞭策自己（要是游手好闲一天，自己都会不好意思写的）。<br /><br />　　 37. 你们的项目经理会发出Weekly Report么？<br />　　　　　要。也是为了沟通。内容包括目前进度，可能的风险，质量状况，各种工作的进展等。<br /><br />　　 38. 你们项目组是否至少每周全体开会一次？<br />　　　　　要。一定要开会。程序员讨厌开会，但每个礼拜开会时间加起来至少应该有4小时。包括team meeting, spec review meeting, bug triage meeting。千万别大家闷头写code。 <br /><br />　　39. 你们项目组的会议、讨论都有记录么？<br />　　　　会前发meeting request和agenda，会中有人负责主持和记录，会后有人负责发meeting minutes，这都是effective meeting的要点。而且，每个会议都要形成agreements和action items。<br /><br />　　 40. 其他部门知道你们项目组在干什么么？<br />　　　　要发一些Newsflash给整个大组织。Show your team’s value。否则，当你坐在电梯里面，其他部门的人问：“你们在干嘛”，你回答“ABC项目”的时候，别人全然不知，那种感觉不太好。<br />41. 通过Email进行所有正式沟通 <br />　　　　Email的好处是免得抵赖。但也要避免矫枉过正，最好的方法是先用电话和当面说，然后Email来确认。 <br /><br />　　42. 为项目组建立多个Mailing Group <br />　　　　如果在AD+Exchange里面，就建Distribution List。比如，我会建ABC Project Core Team，ABC Project Dev Team，ABC Project All Testers，ABC Project Extended Team等等。这样发起Email来方便，而且能让该收到email的人都收到、不该收到不被骚扰。 <br /><br />　　43. 每个人都知道哪里可以找到全部的文档么？<br />　　　　应该每个人都知道。这叫做知识管理（Knowledge Management）。最方便的就是把文档放在一个集中的File Share，更好的方法是用Sharepoint。 <br /><br />　　44. 你做决定、做变化时，告诉大家原因了么？<br />　　　　要告诉大家原因。Empower team member的手段之一是提供足够的information，这是MSF一开篇的几个原则之一。的确如此，tell me why是人之常情，tell me why了才能有understanding。中国人做事喜欢搞限制，限制信息，似乎能够看到某一份文件的人就是有身份的人。大错特错。权威、权力，不在于是不是能access information/data，而在于是不是掌握资源。 <br /><br />　　45. Stay agile and expect change 要这样。<br />　　　　需求一定会变的，已经写好的代码一定会被要求修改的。做好心理准备，对change不要抗拒，而是expect change。 <br /><br />　　46. 你们有没有专职的软件测试人员？<br />　　　　要有专职测试。如果人手不够，可以peer test，交换了测试。千万别自己测试自己的。 <br /><br />　　47. 你们的测试有一份总的计划来规定做什么和怎么做么？<br />　　　　 这就是Test Plan。要不要做性能测试？要不要做Usability测试？什么时候开始测试性能？测试通过的标准是什么？用什么手段，自动的还是手动的？这些问题需要用Test Plan来回答。<br /><br />　　 48. 你是先写Test Case然后再测试的么？<br />　　　　应该如此。应该先设计再编程、先test case再测试。当然，事情是灵活的。我有时候在做第一遍测试的同时补上test case。至于先test case再开发，我不喜欢，因为不习惯，太麻烦，至于别人推荐，那试试看也无妨。 <br /><br />　　49. 你是否会为各种输入组合创建测试用例？<br />　　　　不要，不要搞边界条件组合。当心组合爆炸。有很多test case工具能够自动生成各种边界条件的组合——但要想清楚，你是否有时间去运行那么多test case。 <br /><br />　　50. 你们的程序员能看到测试用例么？<br />　　　　要。让Dev看到Test Case吧。我们都是为了同一个目的走到一起来的：提高质量。<br /><br />　　 51. 你们是否随便抓一些人来做易用性测试？ <br />　　　　要这么做。自己看自己写的程序界面，怎么看都是顺眼的。这叫做审美疲劳——臭的看久了也就不臭了，不方便的永久了也就习惯了。 <br />　　52. 你对自动测试的期望正确么？<br />　　　　别期望太高。依我看，除了性能测试以外，还是暂时先忘掉“自动测试”吧，忘掉WinRunner和LoadRunner吧。对于国内的软件测试的现状来说，只能“矫枉必须过正”了。<br /><br />　　53. 你们的性能测试是等所有功能都开发完才做的么？<br />　　　　不能这样。性能测试不能被归到所谓的“系统测试”阶段。早测早改正，早死早升天。<br /><br />　　54. 你注意到测试中的杀虫剂效应了么？<br />　　　　虫子有抗药性，Bug也有。发现的新Bug越来越少是正常的。这时候，最好大家交换一下测试的area，或者用用看其他工具和手法，就又会发现一些新bug了。<br /><br />　　 55. 你们项目组中有人能说出产品的当前整体质量情况么？<br />　　　　要有。当老板问起这个产品目前质量如何，Test Lead/Manager应该负责回答。 <br /><br />　　56. 你们有单元测试么？<br />　　　　单元测试要有的。不过没有单元测试也不是不可以，我做过没有单元测试的项目，也做成功了——可能是侥幸，可能是大家都是熟手的关系。还是那句话，软件工程是非常实践、非常工程、非常灵活的一套方法，某些方法在某些情况下会比另一些方法好，反之亦然。 <br /><br />　　57. 你们的程序员是写完代码就扔过墙的么？<br />　　　　大忌。写好一块程序以后，即便不做单元测试，也应该自己先跑一跑。虽然有了专门的测试人员，做开发的人也不可以一点测试都不做。微软还有Test Release Document的说法，程序太烂的话，测试有权踢回去。<br /><br />　　 58. 你们的程序中所有的函数都有输入检查么？<br />　　　　不要。虽然说做输入检查是write secure code的要点，但不要做太多的输入检查，有些内部函数之间的参数传递就不必检查输入了，省点功夫。同样的道理，未必要给所有的函数都写注释。写一部分主要的就够了。<br /><br />　　 59. 产品有统一的错误处理机制和报错界面么？<br />　　　　要有。最好能有统一的error message，然后每个error message都带一个error number。这样，用户可以自己根据error number到user manual里面去看看错误的具体描述和可能原因，就像SQL Server的错误那样。同样，ASP.NET也要有统一的Exception处理。可以参考有关的Application Block。<br /><br />　　60. 你们有统一的代码书写规范么？<br />　　　　要有。Code Convention很多，搞一份来发给大家就可以了。当然，要是有FxCop这种工具来检查代码就更好了。 <br /><br />　　61. 你们的每个人都了解项目的商业意义么？<br />　　　　要。这是Vision的意思。别把项目只当成工作。有时候要想着自己是在为中国某某行业的信息化作先驱者，或者时不时的告诉team member，这个项目能够为某某某国家部门每年节省多少多少百万的纳税人的钱，这样就有动力了。平凡的事情也是可以有个崇高的目标的。<br /><br />　　 62. 产品各部分的界面和操作习惯一致么？<br />　　　　要这样。要让用户觉得整个程序好像是一个人写出来的那样。<br /><br />　　 63. 有可以作为宣传亮点的Cool Feature么？<br />　　　　要。这是增强团队凝聚力、信心的。而且，“一俊遮百丑”，有亮点就可以掩盖一些问题。这样，对于客户来说，会感觉产品从质量角度来说还是acceptable的。或者说，cool feature或者说亮点可以作为质量问题的一个事后弥补措施。 <br /><br />　　 64. 尽可能缩短产品的启动时间要这样。<br />　　　　　软件启动时间（Start-Up time）是客户对性能好坏的第一印象。<br /><br />　　 65. 不要过于注重内在品质而忽视了第一眼的外在印象程序员容易犯这个错误：太看重性能、稳定性、存储效率，但忽视了外在感受。而高层经理、客户正相反。这两方面要兼顾，协调这些是PM的工作。<br /><br />　　 66. 你们根据详细产品功能说明书做开发么？<br />　　　　要这样。要有设计才能开发，这是必须的。设计文档，应该说清楚这个产品会怎么运行，应该采取一些讲故事的方法。设计的时候千万别钻细节，别钻到数据库、代码等具体实现里面去，那些是后面的事情，一步步来不能着急。<br /><br />　 　67. 开始开发和测试之前每个人都仔细审阅功能设计么？<br />　　　　要做。Function Spec review是用来统一思想的。而且，review过以后形成了一致意见，将来再也没有人可以说“你看，当初我就是反对这么设计的，现在吃苦头了吧”<br /><br />　　68. 所有人都始终想着The Whole Image么？<br />　　　　要这样。项目里面每个人虽然都只是在制造一片叶子，但每个人都应该知道自己在制造的那片叶子所在的树是怎么样子的。我反对软件蓝领，反对过分的把软件制造看成流水线、车间。参见第61条。<br /><br />　　 69. Dev工作的划分是单纯纵向或横向的么？<br />　　　　不能单纯的根据功能模块分，或者单纯根据表现层、中间层、数据库层分。我推荐这么做：首先根据功能模块分，然后每个“层”都有一个Owner来Review所有人的设计和代码，保证consistency。 <br /><br />　　70. 你们的程序员写程序设计说明文档么？<br />　　　　要。不过我听说微软的程序员1999年以前也不写。所以说，写不写也不是绝对的，偷懒有时候也是可以的。参见第56条。<br /><br />　　71. 你在招人面试时让他写一段程序么？<br />　　　　要的。我最喜欢让人做字符串和链表一类的题目。这种题目有很多循环、判断、指针、递归等，既不偏向过于考算法，也不偏向过于考特定的API。<br /><br />　　72. 你们有没有技术交流讲座？<br />　　　　要的。每一两个礼拜搞一次内部的Tech Talk或者Chalk Talk吧。让组员之间分享技术心得，这笔花钱送到外面去培训划算。<br /><br />　　73. 你们的程序员都能专注于一件事情么？<br />　　　　要让程序员专注一件事。例如说，一个部门有两个项目和10个人，一种方法是让10个人同时参加两个项目，每个项目上每个人都花50%时间；另一种方法是5个人去项目A，5个人去项目B，每个人都100%在某一个项目上。我一定选后面一种。这个道理很多人都懂，但很多领导实践起来就把属下当成可以任意拆分的资源了。 <br /><br />　　74. 你们的程序员会夸大完成某项工作所需要的时间么？<br />　　　　会的，这是常见的，尤其会在项目后期夸大做某个change所需要的时间，以次来抵制change。解决的方法是坐下来慢慢磨，磨掉程序员的逆反心理，一起分析，并把估算时间的颗粒度变小。 <br /><br />　　75. 尽量不要用Virtual Heads 最好不要用Virtual Heads。<br />　　　　Virtual heads意味着resource is not secure，shared resource会降低resource的工作效率，容易增加出错的机会，会让一心二用的人没有太多时间去review spec、review design。一个dedicated的人，要强过两个只能投入50%时间和精力的人。我是吃过亏的：7个part time的tester，发现的Bug和干的活，加起来还不如两个full-time的。参见第73条。73条是针对程序员的，75条是针对Resource Manager的。<br /><img src ="http://www.blogjava.net/franlk/aggbug/87456.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-12-13 12:51 <a href="http://www.blogjava.net/franlk/articles/87456.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]Struts中不同的Action和ActionForm组合</title><link>http://www.blogjava.net/franlk/articles/82797.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Wed, 22 Nov 2006 07:57:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/82797.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/82797.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/82797.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/82797.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/82797.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://dev.csdn.net/article/58/58808.shtm">http://dev.csdn.net/article/58/58808.shtm</a><br /><br /><span id="ArticleContent1_ArticleContent1_lblContent">  
<p>在TSS.com上看到一篇好文，有关Struts使用中各种不同的Action和ActionForm组合的利弊。我先消化一下，整理好，供大家参考。原文标题：Struts action mappings: Divide Et Impera，作者：Michael Juravlev。在TSS上的URL：<a href="http://www.theserverside.com/articles/article.tss?l=StrutsActionMapping">http://www.theserverside.com/articles/article.tss?l=StrutsActionMapping</a></p><p><font color="#808080" size="1">说明：阅读本文需要一定的Struts基础。<br />注：文中小写的action不一定代表具体的Struts Action类，有时也指作为一个整体的action mapping。</font></p><p><br /><strong>[1] 完整的action</strong></p><p>&lt;action path="/aFullAction"<br />    type="somePackage.someActionClass"&gt;<br />    name="someForm"<br />    input="someJSP.jsp"<br />    &lt;forward name="successful" path="someJSP.jsp"/&gt;<br />    &lt;forward name="failed" path="someOtherJSP.jsp"/&gt;<br />&lt;/action&gt;</p><p>首先，Struts的ActionServlet接收到一个请求，然后根据struts-config.xml的配置定位到相应的mapping（映射）；接下来如果form的范围是request或者在定义的范围中找不到这个form，创建一个新的form实例；取得form实例以后，调用其reset()方法，然后将表单中的参数放入form，如果validate属性不为false，调用validate()方法；如果validate()返回非空的ActionErrors，将会被转到input属性指定的URI，如果返回空的ActionErrors，那么执行Action的execute()方法，根据返回的ActionForward确定目标URI。</p><p>这样做的效果是：execute()仅当validate()成功以后才执行；input属性指定的是一个URI。</p><p><br /><strong>[2] 仅有Form的action</strong></p><p>&lt;action path="/aFormOnlyAction"<br />    type="org.apache.struts.actions.ForwardAction"<br />    name="someForm"<br />    input="someJSP.jsp"<br />    parameter="someOtherJSP.jsp"<br />/&gt;</p><p>首先，Struts会在定义的scope搜寻someForm，如果找到则重用，如果找不到则新建一个实例；取得form实例以后，调用其reset()方法，然后将表单中的参数放入form，如果validate属性不为false，调用validate()方法；如果validate()返回非空的ActionErrors，将会被转到input属性指定的URI，如果返回空的ActionErrors，那么转到parameter属性指定的目标URI。</p><p>这样做的效果是：没有action类可以存放我们的业务逻辑，所以所有需要写入的逻辑都只能写到form的reset()或者validate()方法中。validate()的作用是验证和访问业务层。因为这里的action映射不包括forward（也没有意义），所以不能重定向，只能用默认的那个forward。这种仅有form的action可以用来处理数据获取并forward到另一个JSP来显示。</p><p><br /><strong>[3] 仅有Action的action</strong></p><p>&lt;action path="/anActionOnlyAction"<br />    type="somePackage.someActionClass"&gt;<br />    input="someJSP.jsp"<br />    &lt;forward name="successful" path="someJSP.jsp"/&gt;<br />    &lt;forward name="failed" path="someOtherJSP.jsp"/&gt;<br />&lt;/action&gt;</p><p>首先，ActionServlet接收到请求后，取得action类实例，调用execute()方法；然后根据返回的ActionForward在配置中找forward，forward到指定的URI或action。</p><p>这样做的效果是：没有form实例被传入execute()方法，于是execute()必须自己从请求中获取参数。Action可以被forward或者重定向。这种action不能处理通过HTML FORM提交的请求，只能处理链接式的请求。</p><p><br /><strong>[4] 仅有JSP的action</strong></p><p>&lt;action path="/aJSPOnlyAction"<br />    type="org.apache.struts.actions.ForwardAction"<br />    parameter="someOtherJSP.jsp"<br />/&gt;</p><p>首先，ActionServlet接到请求后调用ForwardAction的execute()方法，execute()根据配置的parameter属性值来forward到那个URI。</p><p>这样做的效果是：没有任何form被实例化，比较现实的情形可能是form在request更高级别的范围中定义；或者这个action被用作在应用程序编译好后充当系统参数，只需要更改这个配置文件而不需要重新编译系统。</p><p><br /><strong>[5] 两个action对应一个form</strong></p><p>&lt;action path="/anAction"<br />    type="somePackage.someActionClass"&gt;<br />    name="someForm"<br />    input="someJSP.jsp"<br />    &lt;forward name="successful" path="/anotherAction.do"/&gt;<br />&lt;/action&gt;<br />&lt;action path="/anotherAction"<br />    type="somePackage.someOtherActionClass"&gt;<br />    name="someForm"<br />    input="someOtherJSP.jsp"<br />    &lt;forward name="successful" path="someResultJSP.jsp"/&gt;<br />&lt;/action&gt;</p><p>就每个单独的action来讲，处理上并没有和完整的action有什么实质的区别。这个组合模式可以被用来传递命令对象（form）。需要注意的是在后一个action中同样会调用form的reset()和validate()方法，因此我们必须确保form中的信息不被重写。</p><p>处理的方式大致分为两种：a) 在request中放入一个指示器表明前一个action有意向后一个action传递form，从而在后一个action可以保留那个form中的值，这一方式只能在使用forward时使用。b) 当使用redirect而不是forward时，可以把指示器放在session或更高的级别，在命令链的最后一环将这个指示器清除。</p><p><br /><strong>[6] 两个action对应两个form</strong></p><p>&lt;action path="/anAction"<br />    type="somePackage.someActionClass"&gt;<br />    name="someForm"<br />    input="someJSP.jsp"<br />    &lt;forward name="successful" path="/anotherAction.do" redirect="true"/&gt;<br />&lt;/action&gt;<br />&lt;action path="/anotherAction"<br />    type="somePackage.someOtherActionClass"&gt;"<br />    name="someOtherForm"<br />    input="someOtherJSP.jsp"<br />    &lt;forward name="successful" path="someResultJSP.jsp"/&gt;<br />&lt;/action&gt;</p><p>这个组合方式跟前一种在流程上没有太大区别，只是我们现在对于两个action分别提供了form，于是代码看上去更加清晰。于是我们可以分别处理WEB应用程序的输入和输出。值得注意的是，后一个action同样会尝试往form中写入那些参数，不过我们可以这样处理：a) 在后一个form中使用另一套属性名；b) 只提供getter而不提供setter。</p><p>大致的处理是这样：<br />前一个action接收输入、验证、然后将数据写入业务层或持久层，重定向到后一个action，后一个action手动的从业务层/持久层取出数据，写入form（通过其他方式），交给前台JSP显示。</p><p>这样做的好处是不必保留输入form中的值，因此可以使用redirect而不是forward。这样就降低了两个action之间的耦合度，同时也避免了不必要的重复提交。<br /><br /></p></span><br /><div style="FONT-SIZE: 14px; LINE-HEIGHT: 25px"><strong>作者Blog：</strong><a id="ArticleContent1_ArticleContent1_AuthorBlogLink" href="http://blog.csdn.net/sean_gao/" target="_blank">http://blog.csdn.net/sean_gao/</a></div><img src ="http://www.blogjava.net/franlk/aggbug/82797.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-11-22 15:57 <a href="http://www.blogjava.net/franlk/articles/82797.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]CVSNT在Windows下的安装和使用</title><link>http://www.blogjava.net/franlk/articles/79979.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Wed, 08 Nov 2006 15:06:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/79979.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/79979.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/79979.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/79979.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/79979.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://fns.blog.hexun.com/1664381_d.html">http://fns.blog.hexun.com/1664381_d.html</a><br /><br /><table cellspacing="0" cellpadding="0" width="447" border="0"><tbody><tr><td style="COLOR: #ff9900" colspan="2" height="29"><p style="COLOR: #ff9900"><strong>CVSNT在Windows下的安装和使用</strong></p></td></tr><tr><td style="COLOR: #ff9900; WORD-BREAK: break-all" colspan="2">先说下CVSNT的用户验证方式，CVSNT的用户验证方式分两种：Windows系统用户与CVSNT用户共存的混合验证方式，及CVSNT用户 单一验证方式，默认工作在混合验证方式下，当然使用单一验证方式对用户的管理肯定比较方便一点，因此下面的配置就是围绕该方式进行的。各个资源库所使用的 验证方式及用户配置由其目录下CVSROOT里的配置文件决定，其中有几个比较重要的文件。<br /><br /><br /><br /><br />1、config文件<br /><br />控制CVSNT的验证工作方式的就是config文件，注意该文件最前面的两行：<br /><br />#Set this to `no" if pserver shouldn"t check system users/passwords<br />#SystemAuth=yes<br /><br />第二行就是我们要修改的内容，默认状态是被注释掉的，SystemAuth有两个值yes和no：<br /><br />yes：pserver将使用Windows系统用户和CVSNT用户来共同验证（若CVSNT用户未定义，则用Windows系统用户来进行验证），默认为yes，CVSNT用户在后面将要介绍的passwd文件中定义。<br /><br />no：只使用CVSNT用户来进行验证。<br /><br />该文件可以在客户端进行修改，因此我们可以将其checkout出来将第二行改为SystemAuth=no，并commit到CVSNT上就可以启用单一验证方式了，注意启用单一验证方式后原来的Windows系统用户将变为无效，因此要注意执行该步骤的时机。<br /><br />2、 admin文件<br /><br />该文件保存CVSNT管理员用户列表，内容很简单，形式如下：<br />User1<br />User2<br />User3<br />每一行定义一个管理 员用户，默认时没有该文件，但你可以在客户端自己添加并add上去，再commit到CVSNT上，但是光有这个文件还是不会生效的，还要将其添加到 checklist文件中，使CVSNT能够读取该文件的内容，在checklist中添加文件列表的格式为：<br />[空格]文件名 出错信息<br />其中文件名前的空格必须要有的，不然会出错。<br />我们可以先添加admin文件到CVSNT中，再修改checklist文件commit，就可以使admin文件生效了。<br />3、passwd文件<br />服务器工作在CVSNT用户单一验证方式下的时候，这个文件定义了CVSNT的用户信息，这里面保存着用户名，用户密码，以及别名信息。默认状态下 没有该文件，但是我们可以在CVSNT还工作在混合验证方式下时，用系统管理员登录，通过添加用户命令来让CVSNT自动建立一个passwd文件。<br />添加用户的命令的示例:<br />cvs passwd –r administrator –a cvsadmin<br />之后系统提示输入密码，输入后服务器会新建一个passwd文件。<br />该文件的内容很简单，形式如下：<br />cvsadmin:fqr1fS4gDghrt:administrator<br />kid:aTXRfS31Bm6JA<br />mystique:Yna4QcXz9dEqd<br />以第一行为例：cvsadmin为用户名，fqr1fS4gDghrt为CVS使用UNIX标准加密函数对密码进行加密后的结果，administrator为该用户的别名，当使用混合验证方式时对应Windows系统用户名。<br />注意：这个文件是不能在客户端进行修改的，不能checkout出来。<br />4、group文件<br />该文件定义CVSNT中组信息，同组里的用户拥有一样的权限，对组权限的修改和对用户权限的修改一样。<br />group文件的内容为<br />administrators:cvsadmin kid mystique<br />users:User1 User2 User3<br />可以看到该文件的内容也很简单，组名：用户名，多个用户名之间用空格隔开。<br />Group文件可以在客户端修改，不用修改checkoutlist这个文件，系统会自动使其生效。<br />作为组里面的特定成员可以赋给特定的权限。<br />了解了以上内容，下面我说一下我自己的配置步骤，我没有使用WinCVS进行操作，是直接使用命令行进行修改的，觉得这样思路比较清晰：<br />1、添加系统变量CVSROOT=E:/CVSNT/Repository，并把E:\CVSNT加入到系统Path路径。<br />2、进入命令提示符，因为此时为混合验证模式，可以不用不用登陆直接进行checkout。可以建立一个工作目录，在该目录下进行操作，我这里为E:/CVSNT/Works。<br /> 检出CVSROOT目录：<br />  cvs co CVSROOT<br />3、添加CVSNT系统管理员用户，此时会提示设置用户密码：<br /> cvs passwd –r administrator –a cvsadmin<br />4、修改CVSROOT访问权限：<br />cd CVSROOT<br /> cvs chown cvsadmin   //更改所有者为cvsadmin<br /> cvs chacl default:n   //默认权限为n<br /> cvs chacl cvsadmin:rwc  //添加cvsadmin<br />5、修改config文件，按上面的方法修改后commit：<br /> cvs ci</td></tr></tbody></table>6、此时单一验证方式已经启用了，也就是只能使用刚才添加的cvsadmin进行登录，此时可以把CVSNT控制面板上的Use local users for pserver authentication instead of domain users关掉。登录前还要改一下系统变量CVSROOT，关闭命令提示符窗口，修改CVSROOT为：<br /> :pserver:cvsadmin@192.168.0.1:4021/CVSNT/Repository<br /><br />这里的192.168.0.1是服务器的IP地址，/CVSNT/Repository就是前面设置Repository时设置的Name，可以改为你机器上的配置。修改系统变量之后以下的步骤在任何与服务器相连的机器上进行，当然该机器上应该有CVSNT的可执行文件。<br />7、如果为了避免出现错误，先重启一下CVSNT服务器，再启动命令提示符来到E:/CVSNT/Works，因为已经启用单一验证方式，先要进行登录。<br /><br /> cvs login<br /> <br /> 输入密码，此时就是以cvsadmin登录了。<br /> <br />8、添加admin文件，首先将CVSROOT检出，在CVSROOT下新建admin文件，内容为<br /> <br /> cvsadmin<br /> <br /> 执行命令：<br /> <br /> cvs add admin<br /> cvs ci<br /> <br />9、修改checklist文件，在该文件末尾添加一行：<br /><br /> [空格]admin  error message<br /> <br /> 注意：admin前的空格不能少。<br /> <br /> 执行命令：<br /> <br /> cvs ci<br /> <br />经过以上步骤，可以说用户配置已经基本完成了，CVSNT可以很好的工作在单一验证方式下。进一步的管理可使用以下命令：<br /><br />添加用户： cvs passwd -a username，使用时不必理会需要添加别名的提示。<br /><br />修改用户权限：cvs chacl username:r|w|c|n，（r：Read w：write c：control n：none）<br /><br />要添加组管理，只需同添加admin步骤一样，按照格式要求新建group文件即可。 <img src ="http://www.blogjava.net/franlk/aggbug/79979.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-11-08 23:06 <a href="http://www.blogjava.net/franlk/articles/79979.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]cvsNT 2.0.58a+tortoisecvs配置点滴</title><link>http://www.blogjava.net/franlk/articles/79969.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Wed, 08 Nov 2006 14:54:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/79969.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/79969.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/79969.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/79969.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/79969.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://dev.csdn.net/article/42/42024.shtm">http://dev.csdn.net/article/42/42024.shtm</a><br /><br /><p>因为需要跨网络合作开发，公司决定使用CVS作为配置库管理工具。由于本人以前没有使用过CVS，而公司服务器又使用的是Window2003系统，所以上网开始找资料。<br />经过搜索后，决定使用cvsNT+tortoisecvs来实现。<br />从<a href="http://www.cvsnt.org/">www.cvsnt.org</a> 下了最新版CvsNT，默认只有2.0.58版的，其他版本找不到。<br />从<a href="http://sourceforge.net/project/showfiles.php?group_id=48103">sourceforge.net </a>下了最新版的tortoisecvs<br />然后从网上找了很多相关的资料，就开始安装了。<br /><br />其中经过若干尝试之后。还是无法正常使用。<br /><br />第二天，无意中把端口号去掉之后，竟然调用成功。<br /><br />现在把配置过程罗列如下：<br /><strong>CvsNT设置</strong><br />1.安装CvsNT，并重新启动<br />2.打开Service Control Panel<br />3.设置Advabced-&gt;Temporary为任意一个空目录<br />   钩选上所有选项<br />   设置Lock地址为Localhost ，其他选项不要改动<br />4.添加Repositories <br />   点击Add按钮，选择一个准备好的空目录如Location= C:/cvsAdmin   ;Name =/cvsAdmin<br />   系统会提示是否初始化，点确定<br />5.如果CvsService或CvsLock服务没有启动，请先启动他们<br /><br /><strong>测试服务器<br /></strong>1.开始菜单-run-cmd,进入命令行环境<br />2.输入Cvs ，会出现相应的帮助，如果没出现，说明环境变量中的Path值没有设置，你可以手动设置到你的Cvs.exe文件所在的目录<br />3.set cvsroot=:sspi:localhost:/cvsAdmin<br />4.输入cvs version ,显示当前CvsNt版本号<br />  Client: Concurrent Versions System (CVSNT) 2.0.58a (client/server<br />  Server: Concurrent Versions System (CVS) 1.11.2 (client/server)<br />5.cvs login<br />   输入你的Windows登陆密码<br /> 6.cvs ls<br />    显示所以module，至少会有一个CVSROOT<br /> 7.如果以上步骤都没有错误，说明CVSNT配置成功<br /><br /><strong>添加用户<br /></strong>1.使用cvs passwd命令可以添加用户和修改密码<br />2.可以修改 C:/cvsAdmin/cvsroot目录下的passwd文件，如果没有的话，可以自己建一个<br />   添加 test:,这样就添加了一个密码为空的test用户了。<br />3.添加用户后可以使用:pserver:test@localhost:/cvsAdmin登录了<br /><br /><strong>tortoisecvs设置<br /></strong>1.安装<strong>tortoisecvs</strong>选择完全安装<br />2.重新启动计算机<br />3.新建一个文件夹如（c:\test），右击，创建新模块，使用pserver协议输入机器IP地址和用户名（不要输入端口号，我可深受其害），<br />   Repositories folder为/cvsAdmin<br />如果不出意外的话，一个新的模块test就建立了<br />4.测试Checkout功能：右键菜单-〉cvs-&gt;checkout 选择一个模块名test,如果不知道的话，可以使用获取列表的功能<br />5.ok,提示cvs操作成功，但是我们什么都没看到，自己查看输出信息，其中包含了cannot open CVS/Entries for reading: No such file or directory，什么意思呢，原来cvs中的模块为空时，它无法取得任何实体，就什么都不生成了，解决的方法很简单，就是在新建的模块中添加一个文件，并提交，再测试一下，果然，cvsAdmin自动为我们生成了。哎，这一点，可把我给害苦了。<br /><br />先写到这里吧！希望对大家有所帮助。</p><img src ="http://www.blogjava.net/franlk/aggbug/79969.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-11-08 22:54 <a href="http://www.blogjava.net/franlk/articles/79969.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>抽象类与接口</title><link>http://www.blogjava.net/franlk/articles/72118.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Tue, 26 Sep 2006 13:15:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/72118.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/72118.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/72118.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/72118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/72118.html</trackback:ping><description><![CDATA[
		<strong>
				<font style="BACKGROUND-COLOR: #ff0000">Abstract：<br /></font>
		</strong>
		<br />public abstract class AbstractClass {<br /> public void method1(){}; //可以有方法体<br /> public abstract void method2(); <br />}<br /><br /><font style="BACKGROUND-COLOR: #ff0000"><strong>Interface</strong><br /></font><br />public interface InterfaceTest {<br />abstract void method1();<br />void method2();//没有方法体<br />}<img src ="http://www.blogjava.net/franlk/aggbug/72118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-09-26 21:15 <a href="http://www.blogjava.net/franlk/articles/72118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]Java抽象类和接口的区别 </title><link>http://www.blogjava.net/franlk/articles/72116.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Tue, 26 Sep 2006 13:07:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/72116.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/72116.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/72116.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/72116.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/72116.html</trackback:ping><description><![CDATA[作者：jackyrong 来源：<a href="http://www.cjsdn.com/" target="_blank">http://www.cjsdn.com/</a> <br /> <br />abstract class和interface是Java语言中对于抽象类定义进行支持的两种机制，正是由于这两种机制的存在，才赋予了Java强大的面向对象能力。abstract class和interface之间在对于抽象类定义的支持方面具有很大的相似性，甚至可以相互替换，因此很多开发者在进行抽象类定义时对于abstract class和interface的选择显得比较随意。其实，两者之间还是有很大的区别的，对于它们的选择甚至反映出对于问题领域本质的理解、对于设计意图的理解是否正确、合理。本文将对它们之间的区别进行一番剖析，试图给开发者提供一个在二者之间进行选择的依据。  <br /><br />理解抽象类  <br /><br />abstract class和interface在Java语言中都是用来进行抽象类（本文中的抽象类并非从abstract class翻译而来，它表示的是一个抽象体，而abstract class为Java语言中用于定义抽象类的一种方法，请读者注意区分）定义的，那么什么是抽象类，使用抽象类能为我们带来什么好处呢？  <br /><br />在面向对象的概念中，我们知道所有的对象都是通过类来描绘的，但是反过来却不是这样。并不是所有的类都是用来描绘对象的，如果一个类中没有包含足够的信息来描绘一个具体的对象，这样的类就是抽象类。抽象类往往用来表征我们在对问题领域进行分析、设计中得出的抽象概念，是对一系列看上去不同，但是本质上相同的具体概念的抽象。比如：如果我们进行一个图形编辑软件的开发，就会发现问题领域存在着圆、三角形这样一些具体概念，它们是不同的，但是它们又都属于形状这样一个概念，形状这个概念在问题领域是不存在的，它就是一个抽象概念。正是因为抽象的概念在问题领域没有对应的具体概念，所以用以表征抽象概念的抽象类是不能够实例化的。  <br /><br />在面向对象领域，抽象类主要用来进行类型隐藏。我们可以构造出一个固定的一组行为的抽象描述，但是这组行为却能够有任意个可能的具体实现方式。这个抽象描述就是抽象类，而这一组任意个可能的具体实现则表现为所有可能的派生类。模块可以操作一个抽象体。由于模块依赖于一个固定的抽象体，因此它可以是不允许修改的；同时，通过从这个抽象体派生，也可扩展此模块的行为功能。熟悉OCP的读者一定知道，为了能够实现面向对象设计的一个最核心的原则OCP(Open-Closed Principle)，抽象类是其中的关键所在。  <br /><br /><br />从语法定义层面看abstract class和interface  <br /><br />在语法层面，Java语言对于abstract class和interface给出了不同的定义方式，下面以定义一个名为Demo的抽象类为例来说明这种不同。  <br /><br />使用abstract class的方式定义Demo抽象类的方式如下：  <br /><br />abstract class Demo ｛  <br /> abstract void method1();  <br /> abstract void method2();  <br /> …  <br />｝  <br /><br />使用interface的方式定义Demo抽象类的方式如下：  <br /><br />interface Demo {  <br /> void method1();  <br /> void method2();  <br /> …  <br />}  <br /><br />在abstract class方式中，Demo可以有自己的数据成员，也可以有非abstarct的成员方法，而在interface方式的实现中，Demo只能够有静态的不能被修改的数据成员（也就是必须是static final的，不过在interface中一般不定义数据成员），所有的成员方法都是abstract的。从某种意义上说，interface是一种特殊形式的abstract class。  <br /><br />      从编程的角度来看，abstract class和interface都可以用来实现"design by contract"的思想。但是在具体的使用上面还是有一些区别的。  <br /><br />首先，abstract class在Java语言中表示的是一种继承关系，一个类只能使用一次继承关系。但是，一个类却可以实现多个interface。也许，这是Java语言的设计者在考虑Java对于多重继承的支持方面的一种折中考虑吧。  <br /><br />其次，在abstract class的定义中，我们可以赋予方法的默认行为。但是在interface的定义中，方法却不能拥有默认行为，为了绕过这个限制，必须使用委托，但是这会 增加一些复杂性，有时会造成很大的麻烦。  <br /><br />在抽象类中不能定义默认行为还存在另一个比较严重的问题，那就是可能会造成维护上的麻烦。因为如果后来想修改类的界面（一般通过abstract class或者interface来表示）以适应新的情况（比如，添加新的方法或者给已用的方法中添加新的参数）时，就会非常的麻烦，可能要花费很多的时间（对于派生类很多的情况，尤为如此）。但是如果界面是通过abstract class来实现的，那么可能就只需要修改定义在abstract class中的默认行为就可以了。  <br /><br />同样，如果不能在抽象类中定义默认行为，就会导致同样的方法实现出现在该抽象类的每一个派生类中，违反了"one rule，one place"原则，造成代码重复，同样不利于以后的维护。因此，在abstract class和interface间进行选择时要非常的小心。  <br /><br /><br />从设计理念层面看abstract class和interface  <br /><br />上面主要从语法定义和编程的角度论述了abstract class和interface的区别，这些层面的区别是比较低层次的、非本质的。本小节将从另一个层面：abstract class和interface所反映出的设计理念，来分析一下二者的区别。作者认为，从这个层面进行分析才能理解二者概念的本质所在。  <br /><br />前面已经提到过，abstarct class在Java语言中体现了一种继承关系，要想使得继承关系合理，父类和派生类之间必须存在"is a"关系，即父类和派生类在概念本质上应该是相同的（参考文献〔3〕中有关于"is a"关系的大篇幅深入的论述，有兴趣的读者可以参考）。对于interface 来说则不然，并不要求interface的实现者和interface定义在概念本质上是一致的，仅仅是实现了interface定义的契约而已。为了使论述便于理解，下面将通过一个简单的实例进行说明。  <br /><br />考虑这样一个例子，假设在我们的问题领域中有一个关于Door的抽象概念，该Door具有执行两个动作open和close，此时我们可以通过abstract class或者interface来定义一个表示该抽象概念的类型，定义方式分别如下所示：  <br /><br />使用abstract class方式定义Door：  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()；  <br />}  <br /><br />   <br />使用interface方式定义Door：  <br /><br /><br />interface Door {  <br /> void open();  <br /> void close();  <br />}  <br /><br />   <br />其他具体的Door类型可以extends使用abstract class方式定义的Door或者implements使用interface方式定义的Door。看起来好像使用abstract class和interface没有大的区别。  <br /><br />如果现在要求Door还要具有报警的功能。我们该如何设计针对该例子的类结构呢（在本例中，主要是为了展示abstract class和interface反映在设计理念上的区别，其他方面无关的问题都做了简化或者忽略）？下面将罗列出可能的解决方案，并从设计理念层面对这些不同的方案进行分析。  <br /><br />解决方案一：  <br /><br />简单的在Door的定义中增加一个alarm方法，如下：  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()；  <br /> abstract void alarm();  <br />}  <br /><br />   <br />或者  <br /><br />interface Door {  <br /> void open();  <br /> void close();  <br /> void alarm();  <br />}  <br /><br />   <br />那么具有报警功能的AlarmDoor的定义方式如下：  <br /><br />class AlarmDoor extends Door {  <br /> void open() { … }  <br /> void close() { … }  <br /> void alarm() { … }  <br />}  <br /><br />   <br />或者  <br /><br />class AlarmDoor implements Door ｛  <br /> void open() { … }  <br /> void close() { … }  <br /> void alarm() { … }  <br />｝  <br /><br />这种方法违反了面向对象设计中的一个核心原则ISP（Interface Segregation Priciple），在Door的定义中把Door概念本身固有的行为方法和另外一个概念"报警器"的行为方法混在了一起。这样引起的一个问题是那些仅仅依赖于Door这个概念的模块会因为"报警器"这个概念的改变（比如：修改alarm方法的参数）而改变，反之依然。  <br /><br />解决方案二：  <br /><br />既然open、close和alarm属于两个不同的概念，根据ISP原则应该把它们分别定义在代表这两个概念的抽象类中。定义方式有：这两个概念都使用abstract class方式定义；两个概念都使用interface方式定义；一个概念使用abstract class方式定义，另一个概念使用interface方式定义。  <br /><br />显然，由于Java语言不支持多重继承，所以两个概念都使用abstract class方式定义是不可行的。后面两种方式都是可行的，但是对于它们的选择却反映出对于问题领域中的概念本质的理解、对于设计意图的反映是否正确、合理。我们一一来分析、说明。  <br /><br />如果两个概念都使用interface方式来定义，那么就反映出两个问题：1、我们可能没有理解清楚问题领域，AlarmDoor在概念本质上到底是Door还是报警器？2、如果我们对于问题领域的理解没有问题，比如：我们通过对于问题领域的分析发现AlarmDoor在概念本质上和Door是一致的，那么我们在实现时就没有能够正确的揭示我们的设计意图，因为在这两个概念的定义上（均使用interface方式定义）反映不出上述含义。  <br /><br />如果我们对于问题领域的理解是：AlarmDoor在概念本质上是Door，同时它有具有报警的功能。我们该如何来设计、实现来明确的反映出我们的意思呢？前面已经说过，abstract class在Java语言中表示一种继承关系，而继承关系在本质上是"is a"关系。所以对于Door这个概念，我们应该使用abstarct class方式来定义。另外，AlarmDoor又具有报警功能，说明它又能够完成报警概念中定义的行为，所以报警概念可以通过interface方式定义。如下所示：  <br /><br />abstract class Door {  <br /> abstract void open();  <br /> abstract void close()；  <br />}  <br />interface Alarm {  <br /> void alarm();  <br />}  <br />class AlarmDoor extends Door implements Alarm {  <br /> void open() { … }  <br /> void close() { … }  <br />    void alarm() { … }  <br />}  <br /><br />   <br />这种实现方式基本上能够明确的反映出我们对于问题领域的理解，正确的揭示我们的设计意图。其实abstract class表示的是"is a"关系，interface表示的是"like a"关系，大家在选择时可以作为一个依据，当然这是建立在对问题领域的理解上的，比如：如果我们认为AlarmDoor在概念本质上是报警器，同时又具有Door的功能，那么上述的定义方式就要反过来了。 <br /><img src ="http://www.blogjava.net/franlk/aggbug/72116.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-09-26 21:07 <a href="http://www.blogjava.net/franlk/articles/72116.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>讨论一下关于java的传值还是引用</title><link>http://www.blogjava.net/franlk/articles/63775.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Tue, 15 Aug 2006 14:02:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/63775.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/63775.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/63775.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/63775.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/63775.html</trackback:ping><description><![CDATA[
		<p>class SwapClass {</p>
		<p>
				<br />public void swap(StringBuffer x,StringBuffer y){<br />x.append(y);<br />y=x;<br />}<br />public void swap(String x,String y){<br />String temp = x;<br />x = y;<br />y = temp;<br />}<br />public void swap(String[] arr,int x,int y){<br />String temp = arr[x];<br />arr[x] = arr[y];<br />arr[y] = temp;<br />}<br />public void change(String x){<br />x ="franlk";<br />}<br />public void add(ArrayList al){<br />al.add("wang");<br />}<br />}<br />public class test {</p>
		<p>/**<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />SwapClass obj = new SwapClass();<br />StringBuffer a = new StringBuffer("A");<br />StringBuffer b = new StringBuffer("B");<br />String[] arr ={"1","2"};<br />ArrayList al = new ArrayList();<br />al.add("zhang");<br />obj.swap(a,b);<br />System.out.println(a+","+b);<br />System.out.println("---------------------------------");<br />obj.swap(arr[0],arr[1]);<br />System.out.println(arr[0]+":"+arr[1]);<br />System.out.println("---------------------------------");<br />obj.swap(arr,0,1);<br />System.out.println(arr[0]+":"+arr[1]);<br />System.out.println("---------------------------------");<br />obj.change(arr[0]);<br />System.out.println(arr[0]);<br />System.out.println("---------------------------------");<br />obj.add(al);<br />System.out.println("al length======"+al.size());<br />}<br />}</p>
		<p>运行结果<br />AB,B<br />---------------------------------<br />1:2<br />---------------------------------<br />2:1<br />---------------------------------<br />2<br />---------------------------------<br />al length======2<br /><br /><br />  方法中改变引用变量指向对象不会影响方法外引用变量；<br />   方法中改变引用变量指向对象的值会影响方法外引用变量的值。</p>
<img src ="http://www.blogjava.net/franlk/aggbug/63775.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-08-15 22:02 <a href="http://www.blogjava.net/franlk/articles/63775.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]查询的优化</title><link>http://www.blogjava.net/franlk/articles/60260.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Wed, 26 Jul 2006 14:42:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/60260.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/60260.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/60260.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/60260.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/60260.html</trackback:ping><description><![CDATA[数据库系统是管理信息系统的核心，基于数据库的联机事务处理（OLTP）以及联机分析处理(OLAP)是银行、企业、政府等部门最为重要的计算机应用之一。从大多数系统的应用实例来看，查询操作在各种数据库操作中所占据的比重最大，而查询操作所基于的SELECT语句在SQL语句中又是代价最大的语句。举例来说，如果数据的量积累到一定的程度，比如一个银行的账户数据库表信息积累到上百万甚至上千万条记录，全表扫描一次往往需要数十分钟，甚至数小时。如果采用比全表扫描更好的查询策略，往往可以使查询时间降为几分钟，由此可见查询优化技术的重要性。 <br />笔者在应用项目的实施中发现，许多程序员在利用一些前端数据库开发工具（如PowerBuilder、Delphi等）开发数据库应用程序时，只注重用户界面的华丽，并不重视查询语句的效率问题，导致所开发出来的应用系统效率低下，资源浪费严重。因此，如何设计高效合理的查询语句就显得非常重要。本文以应用实例为基础，结合数据库理论，介绍查询优化技术在现实系统中的运用。 <br /><br />分析问题 <br /><br />许多程序员认为查询优化是DBMS（数据库管理系统）的任务，与程序员所编写的SQL语句关系不大，这是错误的。一个好的查询计划往往可以使程序性能提高数十倍。查询计划是用户所提交的SQL语句的集合，查询规划是经过优化处理之后所产生的语句集合。DBMS处理查询计划的过程是这样的：在做完查询语句的词法、语法检查之后，将语句提交给DBMS的查询优化器，优化器做完代数优化和存取路径的优化之后，由预编译模块对语句进行处理并生成查询规划，然后在合适的时间提交给系统处理执行，最后将执行结果返回给用户。在实际的数据库产品(如Oracle、Sybase等)的高版本中都是采用基于代价的优化方法，这种优化能根据从系统字典表所得到的信息来估计不同的查询规划的代价，然后选择一个较优的规划。虽然现在的数据库产品在查询优化方面已经做得越来越好，但由用户提交的SQL语句是系统优化的基础，很难设想一个原本糟糕的查询计划经过系统的优化之后会变得高效，因此用户所写语句的优劣至关重要。系统所做查询优化我们暂不讨论，下面重点说明改善用户查询计划的解决方案。  <br />解决问题 <br />下面以关系数据库系统Informix为例，介绍改善用户查询计划的方法。 <br /><br />1．合理使用索引 <br />索引是数据库中重要的数据结构，它的根本目的就是为了提高查询效率。现在大多数的数据库产品都采用IBM最先提出的ISAM索引结构。索引的使用要恰到好处，其使用原则如下： <br />●在经常进行连接，但是没有指定为外键的列上建立索引，而不经常连接的字段则由优化器自动生成索引。 <br />●在频繁进行排序或分组（即进行group by或order by操作）的列上建立索引。 <br />●在条件表达式中经常用到的不同值较多的列上建立检索，在不同值少的列上不要建立索引。比如在雇员表的“性别”列上只有“男”与“女”两个不同值，因此就无必要建立索引。如果建立索引不但不会提高查询效率，反而会严重降低更新速度。 <br />●如果待排序的列有多个，可以在这些列上建立复合索引（compound index）。 <br />●使用系统工具。如Informix数据库有一个tbcheck工具，可以在可疑的索引上进行检查。在一些数据库服务器上，索引可能失效或者因为频繁操作而使得读取效率降低，如果一个使用索引的查询不明不白地慢下来，可以试着用tbcheck工具检查索引的完整性，必要时进行修复。另外，当数据库表更新大量数据后，删除并重建索引可以提高查询速度。 <br /><br />2．避免或简化排序 <br />应当简化或避免对大型表进行重复的排序。当能够利用索引自动以适当的次序产生输出时，优化器就避免了排序的步骤。以下是一些影响因素： <br />●索引中不包括一个或几个待排序的列； <br />●group by或order by子句中列的次序与索引的次序不一样； <br />●排序的列来自不同的表。 <br />为了避免不必要的排序，就要正确地增建索引，合理地合并数据库表（尽管有时可能影响表的规范化，但相对于效率的提高是值得的）。如果排序不可避免，那么应当试图简化它，如缩小排序的列的范围等。 <br /><br />3．消除对大型表行数据的顺序存取 <br />在嵌套查询中，对表的顺序存取对查询效率可能产生致命的影响。比如采用顺序存取策略，一个嵌套3层的查询，如果每层都查询1000行，那么这个查询就要查询10亿行数据。避免这种情况的主要方法就是对连接的列进行索引。例如，两个表：学生表（学号、姓名、年龄……）和选课表（学号、课程号、成绩）。如果两个表要做连接，就要在“学号”这个连接字段上建立索引。 <br />还可以使用并集来避免顺序存取。尽管在所有的检查列上都有索引，但某些形式的where子句强迫优化器使用顺序存取。下面的查询将强迫对orders表执行顺序操作： <br />SELECT ＊ FROM orders WHERE (customer_num=104 AND order_num&gt;1001) OR order_num=1008 <br />虽然在customer_num和order_num上建有索引，但是在上面的语句中优化器还是使用顺序存取路径扫描整个表。因为这个语句要检索的是分离的行的集合，所以应该改为如下语句： <br />SELECT ＊ FROM orders WHERE customer_num=104 AND order_num&gt;1001 <br />UNION <br />SELECT ＊ FROM orders WHERE order_num=1008 <br />这样就能利用索引路径处理查询。 <br /><br />4．避免相关子查询 <br />一个列的标签同时在主查询和where子句中的查询中出现，那么很可能当主查询中的列值改变之后，子查询必须重新查询一次。查询嵌套层次越多，效率越低，因此应当尽量避免子查询。如果子查询不可避免，那么要在子查询中过滤掉尽可能多的行。 <br /><br />5．避免困难的正规表达式 <br />MATCHES和LIKE关键字支持通配符匹配，技术上叫正规表达式。但这种匹配特别耗费时间。例如：SELECT ＊ FROM customer WHERE zipcode LIKE “98_ _ _” <br />即使在zipcode字段上建立了索引，在这种情况下也还是采用顺序扫描的方式。如果把语句改为SELECT ＊ FROM customer WHERE zipcode &gt;“98000”，在执行查询时就会利用索引来查询，显然会大大提高速度。 <br />另外，还要避免非开始的子串。例如语句：SELECT ＊ FROM customer WHERE zipcode[2，3] &gt;“80”，在where子句中采用了非开始子串，因而这个语句也不会使用索引。 <br /><br /><br /><br /><br />6．使用临时表加速查询 <br />把表的一个子集进行排序并创建临时表，有时能加速查询。它有助于避免多重排序操作，而且在其他方面还能简化优化器的工作。例如： <br />SELECT cust.name，rcvbles.balance，……other columns <br />FROM cust，rcvbles <br />WHERE cust.customer_id = rcvlbes.customer_id <br />AND rcvblls.balance&gt;0 <br />AND cust.postcode&gt;“98000” <br />ORDER BY cust.name <br />如果这个查询要被执行多次而不止一次，可以把所有未付款的客户找出来放在一个临时文件中，并按客户的名字进行排序： <br />SELECT cust.name，rcvbles.balance，……other columns <br />FROM cust，rcvbles <br />WHERE cust.customer_id = rcvlbes.customer_id <br />AND rcvblls.balance&gt;0 <br />ORDER BY cust.name <br />INTO TEMP cust_with_balance <br />然后以下面的方式在临时表中查询： <br />SELECT ＊ FROM cust_with_balance <br />WHERE postcode&gt;“98000” <br />临时表中的行要比主表中的行少，而且物理顺序就是所要求的顺序，减少了磁盘I/O，所以查询工作量可以得到大幅减少。 <br />注意：临时表创建后不会反映主表的修改。在主表中数据频繁修改的情况下，注意不要丢失数据。 <br /><br />7．用排序来取代非顺序存取 <br />非顺序磁盘存取是最慢的操作，表现在磁盘存取臂的来回移动。SQL语句隐藏了这一情况，使得我们在写应用程序时很容易写出要求存取大量非顺序页的查询。 <br />有些时候，用数据库的排序能力来替代非顺序的存取能改进查询。 <br /><br />实例分析 <br /><br />下面我们举一个制造公司的例子来说明如何进行查询优化。制造公司数据库中包括3个表，模式如下所示： <br />1．part表 <br />零件号零件描述其他列 <br />（part_num）（part_desc）（other column） <br />102，032Seageat 30G disk…… <br />500，049Novel 10M network card…… <br />…… <br /><br />2．vendor表 <br />厂商号厂商名其他列 <br />（vendor _num）（vendor_name） （other column） <br />910，257Seageat Corp…… <br />523，045IBM Corp…… <br />…… <br /><br />3．parven表 <br />零件号厂商号零件数量 <br />（part_num）（vendor_num）（part_amount） <br />102，032910，2573,450,000 <br />234，423321，0014，000，000 <br />…… <br /><br />下面的查询将在这些表上定期运行，并产生关于所有零件数量的报表： <br />SELECT part_desc，vendor_name，part_amount <br />FROM part，vendor，parven <br />WHERE part.part_num=parven.part_num <br />AND parven.vendor_num = vendor.vendor_num <br />ORDER BY part.part_num <br />如果不建立索引，上述查询代码的开销将十分巨大。为此，我们在零件号和厂商号上建立索引。索引的建立避免了在嵌套中反复扫描。关于表与索引的统计信息如下： <br /><br />表行尺寸行数量每页行数量数据页数量 <br />（table）(row size)（Row count）（Rows/Pages）（Data Pages） <br />part15010，00025400 <br />Vendor1501，000 2540 <br />Parven13 15，000300 50 <br />索引键尺寸每页键数量页面数量 <br />（Indexes）(Key Size)（Keys/Page)(Leaf Pages） <br />part450020 <br />Vendor45002 <br />Parven825060 <br /><br />看起来是个相对简单的3表连接，但是其查询开销是很大的。通过查看系统表可以看到，在part_num上和vendor_num上有簇索引，因此索引是按照物理顺序存放的。parven表没有特定的存放次序。这些表的大小说明从缓冲页中非顺序存取的成功率很小。此语句的优化查询规划是：首先从part中顺序读取400页，然后再对parven表非顺序存取1万次，每次2页（一个索引页、一个数据页），总计2万个磁盘页，最后对vendor表非顺序存取1.5万次，合3万个磁盘页。可以看出在这个索引好的连接上花费的磁盘存取为5.04万次。 <br />实际上，我们可以通过使用临时表分3个步骤来提高查询效率： <br /><br />1．从parven表中按vendor_num的次序读数据： <br />SELECT part_num，vendor_num，price <br />FROM parven <br />ORDER BY vendor_num <br />INTO temp pv_by_vn <br />这个语句顺序读parven（50页），写一个临时表（50页），并排序。假定排序的开销为200页，总共是300页。 <br /><br />2．把临时表和vendor表连接，把结果输出到一个临时表，并按part_num排序： <br />SELECT pv_by_vn，＊ vendor.vendor_num <br />FROM pv_by_vn，vendor <br />WHERE pv_by_vn.vendor_num=vendor.vendor_num <br />ORDER BY pv_by_vn.part_num <br />INTO TMP pvvn_by_pn <br />DROP TABLE pv_by_vn <br />这个查询读取pv_by_vn(50页)，它通过索引存取vendor表1.5万次，但由于按vendor_num次序排列，实际上只是通过索引顺序地读vendor表（40＋2=42页），输出的表每页约95行，共160页。写并存取这些页引发5＊160=800次的读写，索引共读写892页。 <br /><br />3．把输出和part连接得到最后的结果： <br />SELECT pvvn_by_pn.＊，part.part_desc <br />FROM pvvn_by_pn，part <br />WHERE pvvn_by_pn.part_num=part.part_num <br />DROP TABLE pvvn_by_pn <br />这样，查询顺序地读pvvn_by_pn(160页)，通过索引读part表1.5万次，由于建有索引，所以实际上进行1772次磁盘读写，优化比例为30∶1。笔者在Informix Dynamic Sever上做同样的实验，发现在时间耗费上的优化比例为5∶1(如果增加数据量，比例可能会更大)。 <br /><br />小结 <br /><br />20％的代码用去了80％的时间，这是程序设计中的一个著名定律，在数据库应用程序中也同样如此。我们的优化要抓住关键问题，对于数据库应用程序来说，重点在于SQL的执行效率。查询优化的重点环节是使得数据库服务器少从磁盘中读数据以及顺序读页而不是非顺序读页。 <img src ="http://www.blogjava.net/franlk/aggbug/60260.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-07-26 22:42 <a href="http://www.blogjava.net/franlk/articles/60260.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[摘录]UML类图 </title><link>http://www.blogjava.net/franlk/articles/59716.html</link><dc:creator>见酒就晕</dc:creator><author>见酒就晕</author><pubDate>Sun, 23 Jul 2006 15:23:00 GMT</pubDate><guid>http://www.blogjava.net/franlk/articles/59716.html</guid><wfw:comment>http://www.blogjava.net/franlk/comments/59716.html</wfw:comment><comments>http://www.blogjava.net/franlk/articles/59716.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/franlk/comments/commentRss/59716.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/franlk/services/trackbacks/59716.html</trackback:ping><description><![CDATA[摘录地址：<a href="http://cnblogs.com/hobe/archive/2005/10/16/255723.aspx">http://cnblogs.com/hobe/archive/2005/10/16/255723.aspx</a><br /><br /><span><span></span><p><span>在</span><span lang="EN-US">UML</span><span>的静态机制中类图是一个重点，它不但是设计人员关心的核心，更是实现人员关注的核心。建模工具也主要根据类图来产生代码。类图在</span><span lang="EN-US">UML</span><span>的</span><span lang="EN-US">9</span><span>个图中占据了一个相当重要的地位。</span></p><p><span lang="EN-US">James Rumbaugh</span><span>对类的定义是：类是具有相似结构、行为和关系的一组对象的描述符。类是面向对象系统中最重要的构造块。类图显示了一组类、接口、协作以及他们之间的关系。在</span><span lang="EN-US">UML</span><span>中问题域最终要被逐步转化，通过类来建模，通过编程语言构建这些类从而实现系统。类加上他们之间的关系就构成了类图，类图中还可以包含接口、包等元素，也可以包括对象、链等实例。接口在类图中通过版型来表示</span><span lang="EN-US">&lt;&lt;interface&gt;&gt;</span><span>，下面的介绍将主要介绍类，接口和类类似。</span></p><p><b><span lang="EN-US">A.<span>      </span></span></b><b><span>类的</span></b><b><span lang="EN-US">UML</span></b><b><span>表示</span></b><b></b></p><p></p><p><span>类的命名尽量应用领域中的术语，应明确、无岐义，以利于相互交流和理解。类的属性、操作中的可见性使用＋、</span><span lang="EN-US">#</span><span>、－分别表示</span><span lang="EN-US">public</span><span>、</span><span lang="EN-US">protected</span><span>、</span><span lang="EN-US">private</span><span>。</span></p><p><span lang="EN-US"> <span lang="EN-US" style="FONT-SIZE: 10.5pt; FONT-FAMILY: 'Times New Roman'; mso-bidi-font-size: 12.0pt; mso-fareast-font-family: 宋体; mso-font-kerning: 1.0pt; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA"><?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /?><v:shapetype id="_x0000_t75" stroked="f" filled="f" path="m@4@5l@4@11@9@11@9@5xe" o:preferrelative="t" o:spt="75" coordsize="21600,21600"><img height="223" hspace="5" src="http://cnblogs.com/images/cnblogs_com/hobe/c1.JPG" width="330" align="baseline" /><v:stroke joinstyle="miter"></v:stroke><v:formulas><v:f eqn="if lineDrawn pixelLineWidth 0"></v:f><v:f eqn="sum @0 1 0"></v:f><v:f eqn="sum 0 0 @1"></v:f><v:f eqn="prod @2 1 2"></v:f><v:f eqn="prod @3 21600 pixelWidth"></v:f><v:f eqn="prod @3 21600 pixelHeight"></v:f><v:f eqn="sum @0 0 1"></v:f><v:f eqn="prod @6 1 2"></v:f><v:f eqn="prod @7 21600 pixelWidth"></v:f><v:f eqn="sum @8 21600 0"></v:f><v:f eqn="prod @7 21600 pixelHeight"></v:f><v:f eqn="sum @10 21600 0"></v:f></v:formulas><v:path o:connecttype="rect" gradientshapeok="t" o:extrusionok="f"></v:path><?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?><o:lock aspectratio="t" v:ext="edit"></o:lock></v:shapetype></span></span></p><h1><span lang="EN-US"><span style="FONT-SIZE: 14pt"><span lang="EN-US">B.<span>      </span><span>类之间的关系</span></span></span></span></h1><p><span>类之间的关系是类图中比较复杂的内容。有关联、聚合、组合、范化、依赖。</span></p><p><span>关联：是模型元素之间的一种语义联系，是类之间的一种很弱的联系。关联可以有方向，可以是单向关联，也可以是双向关联。可以给关联加上关联名来描述关联的作用。关联两端的类也可以以某种角色参与关联，角色可以具有多重性，表示可以有多少个对象参与关联。可以通过关联类进一步描述关联的属性、操作以及其他信息。关联类通过一条虚线与关联连接。对于关联可以加上一些约束，以加强关联的含义。如下图所示：</span></p><p><span lang="EN-US"> <img height="100" hspace="5" src="http://cnblogs.com/images/cnblogs_com/hobe/c2.JPG" width="373" align="baseline" /></span></p><p></p><p><span>聚合是一种特殊的关联，聚合表示整体与部分的关系。通常在定义一个整体类后，再去分析这个整体类的组成结构。从而找出一些组成类，该整体类和组成类之间就形成了聚合关系。例如舰队是由一系列的舰船组成。需求描述中“包含”、“组成”、“分为</span><span lang="EN-US">….</span><span>部分”等词常意味着聚合关系。</span></p><p></p><p><span>组合也是一种特殊的关联，也表示类之间整体和部分的关系，但是组合关系中部分和整体具有统一的生存期。一旦整体对象不存在，部分对象也将不存在。部分对象与整体对象之间具有共生死的关系。</span></p><p><span>聚合和组合的区别：聚合关系是“</span><span lang="EN-US">has</span><span>－</span><span lang="EN-US">a</span><span>”关系，组合关系是“</span><span lang="EN-US">contains</span><span>－</span><span lang="EN-US">a</span><span>”关系；聚合关系表示整体与部分的关系比较弱，而组合比较强；聚合关系中代表部分事物的对象与代表聚合事物的对象的生存期无关，一旦删除了聚合对象不一定就删除了代表部分事物的对象。组合中一旦删除了组合对象，同时也就删除了代表部分事物的对象。</span></p><p><span>泛化定义了一般元素和特殊元素之间的分类关系，类之间的这种泛化关系也就是继承关系。泛化关系是“</span><span lang="EN-US">a</span><span>－</span><span lang="EN-US">kind</span><span>－</span><span lang="EN-US">of</span><span>”关系，定义一般元素和特殊元素之间的分类关系。下图是一个泛化关系的例子。<br /></span></p><p></p><p><span><img height="289" hspace="5" src="http://cnblogs.com/images/cnblogs_com/hobe/c3.JPG" width="596" align="baseline" /><br />有两个元素如果修改</span><span lang="EN-US">X</span><span>的定义可能会导致对</span><span lang="EN-US">Y</span><span>的定义，则认为</span><span lang="EN-US">Y</span><span>依赖</span><span lang="EN-US">X</span><span>。依赖关系可能由各种原因引起，如一个类向另一个类发送消息，或者一个类是另一个类的数据成员类型，或者一个类是另一个类的操作的参数类型等。有时依赖关系和关联关系比较难区分。如果类</span><span lang="EN-US">A</span><span>和类</span><span lang="EN-US">B</span><span>有关联关系，它们之间必然有依赖关系。如果两个类之间有关联关系时不用再表示出这两个类之间的依赖关系。</span></p><p><span lang="EN-US"></span> </p><p></p><p><span lang="EN-US"><strong>C.<span>      </span><span>建立类图</span></strong></span></p><p><span>在软件开发不同阶段使用的类图具有不同的抽象层次，即概念层、说明层、和实现层。使用</span><span lang="EN-US">UML</span><span>进行应用建模也应该是一个迭代的过程，所以我们应该建立一个类图的层次的概念。</span></p><p><span>概念层类图描述应用领域中的概念，这些概念与实现它们的类有联系。通常没有直接的映射关系。画概念层类图时很少考虑或不考虑实现问题，因此概念层类图应独立于具体的编程语言。下面是一个概念层类的表示。<br /></span></p><p align="center"></p><p><span><img height="100" hspace="5" src="http://cnblogs.com/images/cnblogs_com/hobe/c4.JPG" width="173" align="baseline" /><br />说明层类图。此时我们考察的是类的接口部分，而不是实现部分。这个接口可能因为实现环境、运行特性等有多种不同的实现。下面是一个说明层类的表示。<br /></span></p><p align="center"></p><p><span><img height="203" hspace="5" src="http://cnblogs.com/images/cnblogs_com/hobe/c5.JPG" width="153" align="baseline" /><br />实现层类图才真正考虑类的实现问题，提供实现的细节。此时的类的概念才应该是真正的严格意义上的类。它揭示了软件实体的构成情况。实现层的类是最常用的，在很多的时候说明层的类更有助于人们对软件的理解。<br /></span></p><p align="center"></p><p><span lang="EN-US"><img height="199" hspace="5" src="http://cnblogs.com/images/cnblogs_com/hobe/c6.JPG" width="172" align="baseline" /><br />UML</span><span>的最终目标是识别出所有必须的类，并分析这些类之间的关系，类的识别贯穿于整个建模过程，分析阶段主要识别问题域相关的类，在设计阶段需要加入一些反映设计思想、方法的类以及实现问题域所需要的类，在编码实现阶段，因为语言的特点，可能需要加入一些其他的类。</span></p><p><span>建立类图的步骤：</span></p><p><span>（</span><span lang="EN-US">1</span><span>）研究分析问题领域确定系统需求。</span></p><p><span>（</span><span lang="EN-US">2</span><span>）确定类，明确类的含义和职责、确定属性和操作。</span></p><p><span>（</span><span lang="EN-US">3</span><span>）确定类之间的关系。</span></p><p><span>类的识别是一个需要大量技巧的工作，寻找类的一些技巧包括：名词识别法；根据用例描述确定类；使用</span><span lang="EN-US">CRC</span><span>分析法；根据边界类、控制类、实体类的划分来帮助分析系统中的类；参考设计模式确定类；对领域进行分析或利用已有领域分析结果得到类；利用</span><span lang="EN-US">RUP</span><span>中如何在分析和设计中寻找类的步骤。</span></p><p><span lang="EN-US">1.<span>       </span><span>名词识别法：</span></span></p><p><span>这种方法的关键是识别系统问题域中的实体。对系统进行描述，描述应该使用问题域中的概念和命名，从系统描述中标识名词及名词短语，其中的名词往往可以标识为对象，复数名词往往可以标识为类。</span></p><p><span lang="EN-US">2.<span>       </span><span>从用例中识别类：</span></span></p><p><span>用例图实质上是一种系统描述的形式，自然可以根据用例描述来识别类。针对各个用例，可以提如下的问题辅助识别：</span></p><p><span>用例描述中出现了那些实体？</span></p><p><span>用例的完成需要哪些实体合作？</span></p><p><span>用例执行过程中会产生并存储哪些信息？</span></p><p><span>用例要求与之关联的每个角色的输入是什么？</span></p><p><span>用例反馈与之关联的每个角色的输出是什么？</span></p><p><span>用例需要操作哪些硬设备？</span></p><p><span>在面向对象应用中，类之间传递的信息数据要么可以映射到发送方的某些属性，要么该信息数据本身就是一个对象。综合不同的用例识别结果，就可以得到整个系统的类，在类的基础上，我们又可以分析用例的动态特性来对用例进行动态行为建模。</span></p><p><span lang="EN-US">3.<span>       </span><span>使用</span><span lang="EN-US">CRC</span><span>分析法：</span></span></p><p><span lang="EN-US">CRC</span><span>（</span><span lang="EN-US">Class,Responsibilities,Collaboration</span><span>）卡的最大价值在于把人们从思考过程模式中脱离出来，更充分的专注于对象技术。</span><span lang="EN-US">CRC</span><span>卡允许整个项目组对设计做出贡献。参与系统设计的人越多，能够收集到的好主意也就越多。因为</span><span lang="EN-US">CRC</span><span>会议是大家全力参与的，通常只需要很少的有类名的卡片，实际上没有写出完整的卡片。</span><span lang="EN-US">CRC</span><span>会议进行中，一些人模拟系统和对象交流，把消息传给其他的对象。通过一步步处理，问题很容易地被解决。</span><span>它由三部分组成：类</span><span lang="EN-US">(Class)</span><span>、职责</span><span lang="EN-US">(Responsibility)</span><span>、协作</span><span lang="EN-US">(Collaborator)</span><span>。下面是一个</span><span lang="EN-US">CRC</span><span>卡的示例：</span></p><table cellspacing="0" cellpadding="0" border="1"><tbody><tr><td valign="top" width="252" colspan="2"><p align="center"><span>类名</span></p></td></tr><tr><td valign="top" width="120"><p><span>职责</span><span lang="EN-US">1</span></p></td><td valign="top" width="132"><p><span>职责</span><span lang="EN-US">1</span><span>的协作</span></p></td></tr><tr><td valign="top" width="120"><p><span>职责</span><span lang="EN-US">2</span></p></td><td valign="top" width="132"><p><span>职责</span><span lang="EN-US">2</span><span>的协作</span></p></td></tr><tr><td valign="top" width="120"><p><span lang="EN-US">……</span></p></td><td valign="top" width="132"><p><span lang="EN-US">……</span></p></td></tr></tbody></table><p><span>职责是类需要知道或做的任何事物。这些职责是类自身所知的知识，或类在执行时所需的知识。协作是指为获取消息，或协助执行活动的其他类。创建</span><span lang="EN-US">CRC</span><span>模型需要下面的步骤。</span></p><p><span lang="EN-US">1)<span>        </span><span>建立团队，包括客户、设计人员、分析人员和一个导引者。如果没有那么多人，那么可以是客户和你自己两个人。</span></span></p><p><span lang="EN-US">2)<span>        </span><span>找出需求中存在的名词和名词词组，特别注意复数（通常是集合），他们对应的单数才是。把你第一次想到的所有概念都写在白板或纸上。不管看起来这些概念是如何荒谬，把他们都写下来。</span></span></p><p><span lang="EN-US">3)<span>        </span><span>筛选。把对象分为三类，核心对象（必须首先实现），可选的（目前不能确定），以及不需要的对象。这之前最好确定一下你的项目范围。某些不属于本项目范围的对象可以使用轻量的</span><span lang="EN-US">adapter</span><span>或</span><span lang="EN-US">proxy</span><span>实现。这里可以加入对分析、设计模式的考虑和应用。</span></span></p><p><span lang="EN-US">4)<span>        </span><span>建卡。取出</span><span lang="EN-US">CRC</span><span>卡，把核心类写在每一张卡上，把可选的类和排除的类分别写在不同的纸上。</span></span></p><p><span lang="EN-US">5)<span>        </span><span>角色扮演。最好是一个团队执行，一个人很难做。每个人负责几个类。对每一个</span><span lang="EN-US">Use case</span><span>其中的情景。导引者指定从某一个人的类开始，某一个人看一看自己能够独立完成，如果不能完成，大家看一看手中的类，谁能完成，就站起来，宣布自己能够完成，以致继续这个过程，每个人完成自己的职责就坐下。在这过程中不断修改类的责任，并写下协作者的名字。</span></span></p><p><span lang="EN-US">4.<span>       </span><span>根据边界类、控制类、实体类帮助分析系统中的类</span></span></p><p><span lang="EN-US">UML</span><span>中类有三种主要的版型：边界类、控制类和实体类。引入边界类、控制类及实体类的概念有助于分析和设计人员确定系统中的类。</span></p><p><span>边界类位于系统与外界的交界处，窗体、报表、以及表示通讯协议的类、直接与外部设备交互的类、直接与外部系统交互的类等都是边界类。通过用例图可以确定需要的边界类，每个</span><span lang="EN-US">Actor/Use Case</span><span>对至少要一个边界类，但并非每个</span><span lang="EN-US">Actor/Use Case</span><span>对要唯一的边界类。</span></p><p><span>实体类保存要放进持久存储体的信息。持久存储体就是数据库、文件等可以永久存储数据的介质。实体类可以通过事件流和交互图发现。通常每个实体类在数据库中有相应的表，实体类中的属性对应数据库表中的字段。</span></p><p><span>控制类是控制其他类工作的类。每个用例通常有一个控制类，控制用例中的事件顺序，控制类也可以在多个用例间共用。其他类并不向控制类发送很多消息，而是由控制类发出很多消息。</span></p><p><span lang="EN-US">5.<span>       </span><span>领域进行分析</span></span></p><p><span>建立类图的过程就是对领域及其解决方案的分析和设计过程。类的获取是一个依赖个人创造力的过程，有时需要和领域专家合作，对研究领域进行仔细分析，抽象出领域中的概念，定义其含义及相互关系，分析出系统类，并用领域中的术语为类命名。领域分析是：通过对某一领域中的已有应用系统、理论、技术、开发历史等的研究，来标识、收集、组织、分析和表示领域模型及软件体系结构的过程，并得到结果。</span></p><p><span lang="EN-US"></span> </p><p><b><span lang="EN-US">D.<span>       </span></span></b><b><span>使用类图</span></b></p><p><span>类图几乎是所有面向对象方法的支柱，应该如何使用类图呢？以下提供了一些使用类图的一些建议。</span></p><p><span>不要试图在项目的初始阶段使用所有的符号，首先应该从简单概念开始。比如类的关系等等，在需要的时候才使用。在项目的不同开发阶段，应该使用不同的观点来画类图。如果处于分析阶段应该画概念层类图，当开始着手软件设计时，应该画说明层类图，当针对某个特定的技术实现时应该画实现层类图。不要为每个事物都画一个模型，应该把精力放在关键的领域。使用类图的最大危险是过早的陷入实现的细节，为了避免这个问题，应该将重点放在概念层和说明层。<br /><br /><br /><br />1．依赖： <br /><br />依赖对象通过调用被依赖对象的方法来获得服务。一种比较松散的关系，并且是短期的。我们的过程与对象往往依赖于我们的实体域对象。如在struts 的 action中调用模型层的方法。 <br /><br />2．关联 <br /><br />它使一个类指到另一个类的属性。长期的 <br /><br />3．聚合 <br /><br />聚合关系是关联关系的一种，是强的关联关系。聚合是整体和部分之间的关系。 <br /><br />4．组合 <br /><br />也叫合成关系，组成关系是关联关系的一种，是比聚合关系强的关系。对象负责代表部分的对象的生命周期。 <br /><br />注：既然聚合，组合关系属于关联关系，那么如何区分一般关联关系，聚合关系和组合关系呢？ <br /><br />一般关联：只要一个对象联系到另外一个对象就形成了关联关系。如：人和他的猫，黑豹乐队和窦魏，pc机和显示器。 <br /><br />聚合关系：一种强关联关系，它要求有部分和整体的关系，并且没有了整体部分也可以独立存在。在上面三个例子中人和它的猫显然没有部分和整体的关系，所以只能是一般的关联关系。而黑豹乐队和窦魏，窦魏等人组成了黑豹乐队即：窦魏和黑豹是整体和部分的关系。而窦魏脱离了黑豹（早就离开了）更或者黑豹不存在了那么窦魏仍然可以以音乐人的身份存在（即对象仍然可以独立存在）所以它属于聚合关系。组成关系是可以共享的。（窦魏也可以加入其他乐队）。 <br /><br />组合关系：一种更强的整体和部分的关系。它并且要求代表整体的对象负责代表部分的对象的生命周期，组成关系是不能共享的。如：pc机和显示器的关系。<br /></span></p></span><img src ="http://www.blogjava.net/franlk/aggbug/59716.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/franlk/" target="_blank">见酒就晕</a> 2006-07-23 23:23 <a href="http://www.blogjava.net/franlk/articles/59716.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>