﻿<?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-优雅天平-文章分类-JAVA基础</title><link>http://www.blogjava.net/Victor/category/1602.html</link><description>享受喧嚣 安于平静</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 10:22:48 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 10:22:48 GMT</pubDate><ttl>60</ttl><item><title>Java初学者容易混淆的几个问题</title><link>http://www.blogjava.net/Victor/articles/23755.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Wed, 14 Dec 2005 00:59:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/23755.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/23755.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/23755.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/23755.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/23755.html</trackback:ping><description><![CDATA[<DIV class=comText><FONT size=3>1.String类和StringBuffer类 <BR><BR>　　它们都是处理字符串的类,但是它们有一个最大的区别,那就是。<BR><BR></FONT><FONT size=3>　　eg1: <BR><BR></FONT><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>...... <BR>//omit some code <BR>String s1="You are hired!"; <BR>System.out.println(s1.replace(′h′,′f′));//用f把字串中的h替换了 <BR>System.out.println(s1); <BR>...... <BR>//omit some code </TD></TR></TBODY></TABLE><BR>　　运行结果: <BR><BR>　　　You are fired! <BR>　　　You are hired! <BR><BR>　　结果分析: <BR><BR>　　从结果,明显可知,s1的值并没有被改变,而第一行结果只是屏幕内容的替换. <BR><BR>　　eg2: <BR><BR><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>...... <BR>//omit some code <BR>StringBuffer s2=new StringBuffer("Hello from Java!"); <BR>s2.replace(6,10,"to"); <BR>System.out.println(s2); <BR>...... <BR>//omit some code </TD></TR></TBODY></TABLE><BR>　　运行结果: <BR><BR>　　Hello to Java! <BR><BR>　　结果分析: <BR><BR>　　显然,s2的值已改变. <BR>　<BR>　　2.位逻辑与条件逻辑 <BR><BR>　　首先声明, 为了与位逻辑更好区分开来,我把通常所说的逻辑取了个别名叫做条件逻辑. <BR><BR>　　它们都有各自的操作符,位逻辑操作符有:&amp;(与运算),^(异或运算),|(或运算);条件逻辑操作符有:&amp;&amp;(并 <BR>且),||(或者)。 <BR><BR>　　位逻辑运算通常是针对两个数而言,实行位操作;而条件逻辑运算是针对两个条件表达式而言,实行条件操作.其实,位逻辑操作符一样可以实现条件操作,但是此时有一个重要的区别:用位操作符时,不管操作符两边的条件表达式成不成立,它都要通通进行运算判断,而条件逻辑操作符不一样了,如果通过左侧的操作数就可以进行它们需要的判断,那么它就不会再计算右侧的操作数了,这种情况叫短路.废话少说!且看下例. <BR><BR>　　eg1: <BR><BR><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>...... <BR>//omit some code <BR>double value=0; <BR>if(value!=0 &amp;&amp; 1/value&lt;1000){ <BR>System.out.println("The value is not too small."); <BR>} <BR>else{ <BR>System.out.println("The value is too small."); <BR>} <BR>...... <BR>//omit some code </TD></TR></TBODY></TABLE><BR>　　运行结果: <BR><BR>　　The value is too small. <BR><BR>　　结果分析: <BR><BR>　　照理说应会出现除数为0的错误,但是我刚才说了,由于条件逻辑操作符是短路操作符,显然,value!=0不成立,立即就可作出判断应执行else后的语句,所以它就不再会运算判断1/value&lt;1000了.如果不懂请再看一 <BR>例: <BR><BR>　　 eg2: <BR><BR><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>...... <BR>//omit some code <BR>double int1=0,int2=1,int3=1; <BR>if(int1!=0 &amp; (int2=2)==1){} <BR>System.out.println("int2="+int2); <BR>if(int1!=0 &amp;&amp; (int3=2)==1){} <BR>System.out.println("int3="+int3); <BR>...... <BR>//omit some code </TD></TR></TBODY></TABLE><BR>　　运行结果: <BR><BR>　　　int2=2.0 <BR>　　　int3=1.0 <BR><BR>　　结果分析: <BR><BR>　　我想不用我分析了,你应该懂了吧. <BR><BR>　　3.实例变量与类变量 <BR><BR>　　可以通过两种方法在类中存储数据───作为实例变量和类变量.实例变量是特定于对象的,如果你有两个对象(即一个类的两个实例),每一个对象中的实例变量独立于另一个对象中的实例变量的;另一方面,两个对象的类变量均指向相同的数据,并因此面保存相同的值,换句话说,类变量被类中的所有对象共享.差点忘了,它们在形式上的区别,类变量在声明时比实例变量多一个static. <BR><BR>　　eg: <BR><BR><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>class data <BR>{ <BR>public int intdata=0;//显然,intdata在这儿是实例变量 <BR>} <BR>public class exam <BR>{ <BR>public static void main(String[] args) <BR>{ <BR>data a,b; <BR>a=new data(); <BR>b=new data(); <BR>a.intdata=1; <BR>System.out.println("b.indata="+b.intdata); <BR>} <BR>} </TD></TR></TBODY></TABLE><BR>　　运行结果: <BR><BR>　　b.intdata=0 <BR><BR>　　结果分析: <BR><BR>　　可以看出,a.intdata的值虽然变了,但并没有影响b.intdata.但是如果在data类中声明intdata时,在其前面加上static就变成类变量了(即:public static int intdata=0;),则此时运行结果会变为: <BR><BR>　　b.intdata=1 <BR><BR>　　这次a.intdata值的改变可把b.intdata影响了,事实上,对象a和b的类变量均指向相同的数据,所有值一样,这就是类变量的作用。 <BR><BR><FONT size=3>4.实例方法,类方法,构造器方法 <BR><BR>　　我们通常所说的方法系指实例方法,就像c语言中的函数一样,其具体方法我就不用说了,在这里我主要是用它来区分类方法和构造器方法.类方法与实例方法最大的区别是:在形式上类方法多一个static,在用法上, <BR>不必创建对象就可直接调用类方法(而实例方法却一定要先创建对象,再通过对象调用)。<BR><BR>　　eg: <BR><BR></FONT><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>class add <BR>{ <BR>static int addem(int op1,int op2) <BR>{ <BR>return op1+op2; <BR>} <BR>} <BR>public class xxf <BR>{ <BR>public static void main(String[] args) <BR>{ <BR>System.out.println("addem(2,2)="+add.addem(2,2)); <BR>} //直接用类名作为对象调用类方法 <BR>} </TD></TR></TBODY></TABLE><BR>　　注: 也可按通常的方法,即先创建对象,再调用方法,不过,这时static就无任何意义了。<BR><BR>　　再说说构造器方法,它是用来初始化对象中的数据的一种方法,创建很容易,只需在类中加上一个与这个类同名的方法,不需要在前面加任何访问说明符或者返回类型,另外,构造器也一样可以向方法一样传递参数. <BR><BR>　　eg: <BR><BR><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>class data <BR>{ <BR>private String data1;//事先声明 <BR><BR>data(String s) <BR>{ <BR>data1=s; /*通过接收数据来初始化变量.(注:不能在构造器内 <BR>声明变量,事先在外就要声明.)*/ <BR>} <BR><BR>public String getdata() <BR>{ <BR>return data1; <BR>} <BR>} <BR><BR>public class xxf <BR>{ <BR>public static void main(String[] args) <BR>{ <BR>System.out.println((new data("I love you")).getdata());/*通过传递参数调用构造器新建一 <BR>个对象,再通过对象调用方法得到数据*/ <BR>} <BR>} <BR></TD></TR></TBODY></TABLE><BR>　　5.接口与类 <BR><BR>　　类是对一类特定对象的规格说明,我们可以类定义创建对象,通过创建对象来组合所有属于该类的组件,而接口不能这样做.而接口实质上就是一个常量和抽象方法的集合,要使用一个接口,就需要在类中实现这个接口,然后作为类定义的一部分,编写接口中声明的每一个方法,接口中的方法永远是public,abstract,接口中的常量永远是public static和final,因此不需要为它们说明属性。<BR><BR>　　因为在Java中不支持多重继承,但是,可以用接口来实现类似的功能,这是接口的重要作用之一。<BR><BR>　　eg: <BR><BR><BR>
<TABLE width="100%" bgColor=#ffffff><BR>
<TBODY><BR>
<TR><BR>
<TD>interface anyone //定义一个接口 <BR>{ <BR>final double PI=3.1416; <BR>void setNumber(int number); <BR>int getNumber(); <BR>} <BR>interface anyother //定义另一个接口 <BR>{ <BR>void setString(String str); <BR>String getString(); <BR>} <BR><BR>class xxf implement anyone,anyother //定义一个类,并使用两个接口 <BR>{ <BR>int number; <BR>String str; <BR>public xxf(){} <BR>void setNumber(int number) <BR>{ <BR>this.number=number; <BR>} <BR>void setString(String str) <BR>{ <BR>this.str=str; <BR>} <BR>void int getNumber(){}//可以为一个空实现. <BR>void String getString(){} <BR>} <BR>//在类中必须实现接口中声明的所有方法.(当然也可不必,但是要用到适配器类或用抽象类) </TD></TR></TBODY></TABLE></DIV><img src ="http://www.blogjava.net/Victor/aggbug/23755.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-12-14 08:59 <a href="http://www.blogjava.net/Victor/articles/23755.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java读取XML文件的工具类</title><link>http://www.blogjava.net/Victor/articles/23104.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Fri, 09 Dec 2005 03:11:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/23104.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/23104.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/23104.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/23104.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/23104.html</trackback:ping><description><![CDATA[如果我们有下面的一个XML文件，可以把它想象成一个Relation Database中的Table， 这个XML文件就是一个名字为managers的关系表，而一个&lt;manager&gt;所包含的就是一条记录(Record)，而manager中的service和implementation就是一个个的栏位(Field) ！<BR><BR>
<TABLE class=CodeFormat style="BORDER-COLLAPSE: collapse" borderColor=#000000 cellSpacing=0 cellPadding=1 width=780 border=1>
<TBODY>
<TR>
<TD bgColor=#99cc99 colSpan=3>managers table<BR></TD></TR>
<TR>
<TD align=middle width=62 rowSpan=3>&nbsp;+&nbsp;</TD>
<TD width=448 bgColor=#99cc99>service</TD>
<TD width=256 bgColor=#99cc99>implementation</TD></TR>
<TR>
<TD><SPAN class=CodeFormat><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.IDBConnectionManager</SPAN><SPAN style="COLOR: rgb(0,0,255)"></SPAN></SPAN></TD>
<TD><SPAN class=CodeFormat><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.impl.DBConnectionManagerCommonImpl</SPAN></SPAN></TD></TR>
<TR>
<TD><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.IDomainIdentify</SPAN></TD>
<TD><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.impl.DomainIdentifyImpl</SPAN><SPAN style="COLOR: rgb(0,0,255)"></SPAN></TD></TR></TBODY></TABLE>
<P>所以，在程序中，可以用类似Table Query的方式来读取XML节点(Node)上面的属性值！ </P>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 cellSpacing=0 cellPadding=1 width=780 border=1>
<TBODY>
<TR>
<TD><PRE class=CodeFormat><SPAN style="COLOR: rgb(0,0,255)">&lt;?</SPAN><SPAN style="COLOR: rgb(255,0,255)">xml version="1.0" encoding="UTF-8"</SPAN><SPAN style="COLOR: rgb(0,0,255)">?&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;!</SPAN><SPAN style="COLOR: rgb(255,0,255)">DOCTYPE managers SYSTEM "manager-config.dtd"</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)"><STRONG>managers</STRONG></SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">manager </SPAN><SPAN style="COLOR: rgb(255,0,0)"><STRONG>name</STRONG></SPAN><SPAN style="COLOR: rgb(0,0,255)">="DBConnectionManager"</SPAN><SPAN style="COLOR: rgb(255,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">service</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.IDBConnectionManager</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">service</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)"><STRONG>implementation</STRONG></SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.impl.DBConnectionManagerCommonImpl</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">implementation</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">manager</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">manager </SPAN><SPAN style="COLOR: rgb(255,0,0)">name</SPAN><SPAN style="COLOR: rgb(0,0,255)">="NTAccountIdendify"</SPAN><SPAN style="COLOR: rgb(255,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>        </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">service</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.IDomainIdentify</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">service</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>        </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;</SPAN><SPAN style="COLOR: rgb(128,0,0)">implementation</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)">net.csdn.blog.xport.impl.DomainIdentifyImpl</SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">implementation</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">manager</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">&lt;/</SPAN><SPAN style="COLOR: rgb(128,0,0)">managers</SPAN><SPAN style="COLOR: rgb(0,0,255)">&gt;</SPAN></PRE></TD></TR></TBODY></TABLE>
<P>按照下面的代码读取：</P>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 cellSpacing=0 cellPadding=1 width=780 border=1>
<TBODY>
<TR>
<TD><PRE class=CodeFormat><SPAN style="COLOR: rgb(0,128,0)">//</SPAN><SPAN style="COLOR: rgb(0,128,0)"> 查找以manager作为tag标记，属性中存在name且属性值为"DBConnectionManager"的<BR></SPAN><SPAN style="COLOR: rgb(0,128,0)">//</SPAN><SPAN style="COLOR: rgb(0,128,0)"> XML节点, 并返回此节点的DOM Element对象！<BR></SPAN><SPAN style="COLOR: rgb(0,128,0)">//</SPAN><SPAN style="COLOR: rgb(0,128,0)"> 类似name字段为PK值，且name="DBConnectionManager"</SPAN><SPAN style="COLOR: rgb(0,128,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,0)">managerElement<BR>        </SPAN><SPAN style="COLOR: rgb(0,0,0)">=</SPAN><SPAN style="COLOR: rgb(0,0,0)"> XMLFileUtil.findElement(xmlDomContent.getRootElement(),<BR>                                  </SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">manager</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">,<BR>                                  </SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">name</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">,<BR>                                  </SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">DBConnectionManager</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">);<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">if</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (managerElement </SPAN><SPAN style="COLOR: rgb(0,0,0)">!=</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">) {<BR>  </SPAN><SPAN style="COLOR: rgb(0,128,0)">//</SPAN><SPAN style="COLOR: rgb(0,128,0)">取得Element中的implementation属性对象...</SPAN><SPAN style="COLOR: rgb(0,128,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,0)">  serviceImplElement </SPAN><SPAN style="COLOR: rgb(0,0,0)">=</SPAN><SPAN style="COLOR: rgb(0,0,0)"> managerElement.element(</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">implementation</SPAN><SPAN style="COLOR: rgb(0,0,0)">"</SPAN><SPAN style="COLOR: rgb(0,0,0)">);<BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">if</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (serviceImplElement </SPAN><SPAN style="COLOR: rgb(0,0,0)">!=</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">) {<BR>    </SPAN><SPAN style="COLOR: rgb(0,128,0)">//</SPAN><SPAN style="COLOR: rgb(0,128,0)">取这个属性的值...</SPAN><SPAN style="COLOR: rgb(0,128,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,0)">    serviceImplClassString </SPAN><SPAN style="COLOR: rgb(0,0,0)">=</SPAN><SPAN style="COLOR: rgb(0,0,0)"> serviceImplElement.getText();<BR>  }<BR>}</SPAN></PRE></TD></TR></TBODY></TABLE>
<P>Source of XML Utility Class：</P>
<TABLE style="BORDER-COLLAPSE: collapse" borderColor=#000000 cellSpacing=0 cellPadding=1 width=780 border=1>
<TBODY>
<TR>
<TD><PRE class=CodeFormat><SPAN style="COLOR: rgb(0,128,0)">/*</SPAN><BR><SPAN style="COLOR: rgb(0,128,0)"><BR> * @(#)XMLFileUtil.java    1.0 2004/12/20<BR> *<BR> * Copyright 2004 Shark Wang, All rights reserved.<BR> </SPAN><BR> <SPAN style="COLOR: rgb(0,128,0)">*/</SPAN><BR> <SPAN style="COLOR: rgb(0,0,0)"></SPAN><BR><SPAN style="COLOR: rgb(0,0,255)">package</SPAN><SPAN style="COLOR: rgb(0,0,0)"> net.csdn.blog.xport;<BR><BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> java.net.URL;<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> java.util.Iterator;<BR><BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> org.apache.log4j.LogManager;<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> org.apache.log4j.Logger;<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> org.dom4j.Attribute;<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> org.dom4j.Document;<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> org.dom4j.Element;<BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">import</SPAN><SPAN style="COLOR: rgb(0,0,0)"> org.dom4j.io.SAXReader;<BR><BR></SPAN><SPAN style="COLOR: rgb(0,128,0)">/**<BR> * The &lt;code&gt;XmlUtil&lt;/code&gt; class supported your code to read/write xml<BR> * data from the file. all methods in this class depend on &lt;code&gt;dom4j&lt;/code&gt;.<BR> *<BR> * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@author</SPAN><SPAN style="COLOR: rgb(0,128,0)">  Shark Wang<BR> * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@version</SPAN><SPAN style="COLOR: rgb(0,128,0)"> 1.0, 2004/12/20<BR> * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@since</SPAN><SPAN style="COLOR: rgb(0,128,0)">   Tutorial 1.0<BR> */</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR></SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">class</SPAN><SPAN style="COLOR: rgb(0,0,0)"> XMLFileUtil {<BR><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">private</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">static</SPAN><SPAN style="COLOR: rgb(0,0,0)"> Logger logger = LogManager.getLogger(XMLFileUtil.</SPAN><SPAN style="COLOR: rgb(0,0,255)">class</SPAN><SPAN style="COLOR: rgb(0,0,0)">);<BR><BR>  </SPAN><SPAN style="COLOR: rgb(0,128,0)">/**<BR>   * read xml content from some file, and load xml data into the<BR>   * Document object.<BR>   *<BR>   * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@param</SPAN><SPAN style="COLOR: rgb(0,128,0)"> filePath String<BR>   * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@return</SPAN><SPAN style="COLOR: rgb(0,128,0)"> Document<BR>   */</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">static</SPAN><SPAN style="COLOR: rgb(0,0,0)"> Document LoadXmlFile(String filePath) {<BR><BR>    </SPAN><SPAN style="COLOR: rgb(0,128,0)">/* marked by Shark Wang<BR>     *****************************************************************<BR>       //get resolver to ignore the DTD validation<BR>       EntityResolver resolver = new EntityResolver() {<BR>           public InputSource resolveEntity(String publicId,<BR>                                            String systemId) {<BR>               return new InputSource(new StringBufferInputStream(""));<BR>           }<BR>       };<BR>       //create reader<BR>       SAXReader reader = new SAXReader();<BR>       //set reader attribute to ignore DTD validation<BR>       reader.setEntityResolver(resolver);<BR>       reader.setValidation(false);<BR>       reader.setIncludeExternalDTDDeclarations(false);<BR>       reader.setIncludeInternalDTDDeclarations(false);<BR>     *******************************************************************<BR>     */</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>    SAXReader reader = </SPAN><SPAN style="COLOR: rgb(0,0,255)">new</SPAN><SPAN style="COLOR: rgb(0,0,0)"> SAXReader();<BR>    </SPAN><SPAN style="COLOR: rgb(0,128,0)">//try to load xml data into Document object<BR></SPAN><SPAN style="COLOR: rgb(0,0,0)">    Document doc = </SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">try</SPAN><SPAN style="COLOR: rgb(0,0,0)"> {<BR>      String urlString = </SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR>      </SPAN><SPAN style="COLOR: rgb(0,0,255)">if</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (filePath.startsWith("/")) {<BR>        urlString = "file://" + filePath;<BR>      }<BR>      </SPAN><SPAN style="COLOR: rgb(0,0,255)">else</SPAN><SPAN style="COLOR: rgb(0,0,0)"> {<BR>        urlString = "file:///" + filePath;<BR>      }<BR>      logger.debug("XML File's URL :" + urlString);<BR>      doc = reader.read(</SPAN><SPAN style="COLOR: rgb(0,0,255)">new</SPAN><SPAN style="COLOR: rgb(0,0,0)"> URL(urlString));<BR>    }<BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">catch</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (Exception ex) {<BR>      logger.info("Can not load " + filePath);<BR>      logger.debug(ex.getMessage(), ex);<BR>    }<BR>    </SPAN><SPAN style="COLOR: rgb(0,128,0)">//return Document object<BR></SPAN><SPAN style="COLOR: rgb(0,0,0)">    </SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)"> doc;<BR>  }<BR><BR>  </SPAN><SPAN style="COLOR: rgb(0,128,0)">/**<BR>   * Get attribute value by name for some xml element.<BR>   *<BR>   * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@param</SPAN><SPAN style="COLOR: rgb(0,128,0)"> element Element<BR>   * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@param</SPAN><SPAN style="COLOR: rgb(0,128,0)"> attributeName String<BR>   * </SPAN><SPAN style="COLOR: rgb(128,128,128)">@return</SPAN><SPAN style="COLOR: rgb(0,128,0)"> String<BR>   */</SPAN><SPAN style="COLOR: rgb(0,0,0)"><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">static</SPAN><SPAN style="COLOR: rgb(0,0,0)"> String getAttributeValue(Element element,<BR>                                         String attributeName) {<BR>    String attributeValue = </SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">for</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (Iterator i = element.attributeIterator(); i.hasNext(); ) {<BR>      Attribute attribute = (Attribute) i.next();<BR>      </SPAN><SPAN style="COLOR: rgb(0,0,255)">if</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (attribute.getName().equals(attributeName)) {<BR>        attributeValue = (String) attribute.getData();<BR>        </SPAN><SPAN style="COLOR: rgb(0,0,255)">break</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR>      }<BR>    }<BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)"> attributeValue;<BR>  }<BR><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">public</SPAN><SPAN style="COLOR: rgb(0,0,0)"> </SPAN><SPAN style="COLOR: rgb(0,0,255)">static</SPAN><SPAN style="COLOR: rgb(0,0,0)"> Element findElement(Element searchedElement,<BR>                                    String targetNodePrefix,<BR>                                    String targetNodeAttributeName,<BR>                                    String targetNodeAttributeValue) {<BR>    Element elementTarget = </SPAN><SPAN style="COLOR: rgb(0,0,255)">null</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">for</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (Iterator i = searchedElement.elementIterator(targetNodePrefix);<BR>         i.hasNext(); ) {<BR>      Element element = (Element) i.next();<BR>      String strManagerName =<BR>          XMLFileUtil.getAttributeValue(element,<BR>                                        targetNodeAttributeName);<BR>      </SPAN><SPAN style="COLOR: rgb(0,0,255)">if</SPAN><SPAN style="COLOR: rgb(0,0,0)"> (strManagerName.equals(targetNodeAttributeValue)) {<BR>        elementTarget = element;<BR>        </SPAN><SPAN style="COLOR: rgb(0,0,255)">break</SPAN><SPAN style="COLOR: rgb(0,0,0)">;<BR>      }<BR>    }<BR>    </SPAN><SPAN style="COLOR: rgb(0,0,255)">return</SPAN><SPAN style="COLOR: rgb(0,0,0)"> elementTarget;<BR>  }<BR><BR>  </SPAN><SPAN style="COLOR: rgb(0,0,255)">private</SPAN><SPAN style="COLOR: rgb(0,0,0)"> XMLFileUtil() {<BR>  }<BR>}</SPAN></PRE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/Victor/aggbug/23104.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-12-09 11:11 <a href="http://www.blogjava.net/Victor/articles/23104.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP中早就有了类似.Net DataSet那样的离线数据访问了，抛弃ResultSet，拥抱Result吧！ </title><link>http://www.blogjava.net/Victor/articles/23102.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Fri, 09 Dec 2005 03:08:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/23102.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/23102.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/23102.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/23102.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/23102.html</trackback:ping><description><![CDATA[<P>微软的.NET平台上面的数据访问有一个特点，就是数据查询的结果，可以放在内存中，以XML格式进行描述，不需要一直与数据库保持在线连接，用DataSet + Data Adapter来实现！<BR><BR>而在JDBC中，我们通常使用javax.sql.ResultSet类来存放放回的数据，它的流程和生命周期如下： </P>
<TABLE style="FONT-SIZE: 10pt; FONT-FAMILY: courier new; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=2 bgColor=#cccc99 border=1>
<TBODY>
<TR>
<TD align=middle colSpan=8>使用ResultSet来返回数据库查询结果</TD></TR>
<TR bgColor=#cccccc>
<TD>Client</TD>
<TD>--&gt;</TD>
<TD>Connection</TD>
<TD>--&gt;</TD>
<TD>Statement</TD>
<TD>--&gt;</TD>
<TD>JDBC Driver </TD>
<TD>--+</TD></TR>
<TR>
<TD colSpan=7>&nbsp;</TD>
<TD bgColor=#cccccc>Database</TD></TR>
<TR bgColor=#cccccc>
<TD>Client</TD>
<TD>&lt;--</TD>
<TD>Parsing</TD>
<TD>&lt;--</TD>
<TD>ResultSet</TD>
<TD>&lt;--</TD>
<TD>JDBC Driver</TD>
<TD>--+</TD></TR>
<TR>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD>
<TD>&nbsp;</TD></TR>
<TR>
<TD colSpan=2>&nbsp;</TD>
<TD bgColor=#99ccff colSpan=6>Connection lifecycle</TD></TR>
<TR>
<TD colSpan=7>&nbsp;</TD>
<TD bgColor=#99ccff>&nbsp;</TD></TR>
<TR>
<TD colSpan=2>&nbsp;</TD>
<TD bgColor=#99ccff colSpan=6>&nbsp;</TD></TR>
<TR>
<TD colSpan=8>&nbsp;</TD></TR>
<TR>
<TD colSpan=2>&nbsp;</TD>
<TD bgColor=#99ccff colSpan=3>ResultSet lifecycle</TD>
<TD colSpan=3>&nbsp;</TD></TR>
<TR>
<TD colSpan=8>&nbsp;</TD></TR></TBODY></TABLE>
<P>我们可以看到，这样会长期占用数据库连接的资源，是一个有点不爽的问题...</P>
<P>其实，在JSTL中提供了另外一种机制，让我们在返回查询结果到表示层的时候，可以做到离线使用！它就是javax.servlet.jsp.jstl.sql.Result类！</P>
<TABLE style="FONT-SIZE: 9pt; FONT-FAMILY: courier new; BORDER-COLLAPSE: collapse" cellSpacing=0 cellPadding=2 width=780 bgColor=#cccc99 border=1>
<TBODY>
<TR>
<TD colSpan=8><PRE style="FONT-SIZE: 10pt; FONT-FAMILY: courier new; BORDER-COLLAPSE: collapse"><A name=line1> 1</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>taglib</FONT> <FONT color=#2040a0>uri</FONT><FONT color=#4444ff>=</FONT><FONT color=#008000>"http://java.sun.com/jsp/jstl/core"</FONT> <FONT color=#2040a0>prefix</FONT><FONT color=#4444ff>=</FONT><FONT color=#008000>"c"</FONT><FONT color=#4444ff>%</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line2> 2</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#2040a0>contentType</FONT><FONT color=#4444ff>=</FONT><FONT color=#008000>"text/html; charset=UTF-8"</FONT><FONT color=#4444ff>%</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line3> 3</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="java.sql.Connection"%&gt;</STRONG></FONT><BR><A name=line4> 4</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="java.sql.DriverManager"%&gt;</STRONG></FONT><BR><A name=line5> 5</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="java.sql.ResultSet"%&gt;</STRONG></FONT><BR><A name=line6> 6</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="java.sql.SQLException"%&gt;</STRONG></FONT><BR><A name=line7> 7</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="java.sql.Statement"%&gt;</STRONG></FONT><BR><A name=line8> 8</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="javax.servlet.jsp.jstl.sql.Result"%&gt;</STRONG></FONT><BR><A name=line9> 9</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT>@<FONT color=#2040a0>page</FONT> <FONT color=#0000ff><STRONG>import="javax.servlet.jsp.jstl.sql.ResultSupport"%&gt;</STRONG></FONT><BR><A name=line10>10</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#4444ff>%</FONT><BR><A name=line11>11</A>   <FONT color=#444444>// 暂且把这个下面的内容看作多层架构中的DAO好了，我偷懒了! </FONT><BR><A name=line12>12</A>   <FONT color=#2040a0>Connection</FONT> <FONT color=#2040a0>conn</FONT> <FONT color=#4444ff>=</FONT> <STRONG>null</STRONG><FONT color=#4444ff>;</FONT><BR><A name=line13>13</A>   <FONT color=#2040a0>Statement</FONT> <FONT color=#2040a0>stmt</FONT> <FONT color=#4444ff>=</FONT> <STRONG>null</STRONG><FONT color=#4444ff>;</FONT><BR><A name=line14>14</A>   <FONT color=#2040a0>ResultSet</FONT> <FONT color=#2040a0>rs</FONT> <FONT color=#4444ff>=</FONT> <STRONG>null</STRONG><FONT color=#4444ff>;</FONT><BR><A name=line15>15</A>   <FONT color=#2040a0>String</FONT> <FONT color=#2040a0>strDbUrl</FONT><BR><A name=line16>16</A>       <FONT color=#4444ff>=</FONT> <FONT color=#008000>"jdbc:mysql://localhost/tutorial?user=tutorial&amp;password=tutpwd"</FONT><FONT color=#4444ff>;</FONT><BR><A name=line17>17</A>   <STRONG>try</STRONG> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line18>18</A>     <FONT color=#444444>//开始与数据库作查询</FONT><BR><A name=line19>19</A>     <FONT color=#2040a0>Class</FONT>.<FONT color=#2040a0>forName</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#008000>"com.mysql.jdbc.Driver"</FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT>.<FONT color=#2040a0>newInstance</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line20>20</A>     <FONT color=#2040a0>conn</FONT> <FONT color=#4444ff>=</FONT> <FONT color=#2040a0>DriverManager</FONT>.<FONT color=#2040a0>getConnection</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>strDbUrl</FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line21>21</A>     <FONT color=#2040a0>stmt</FONT> <FONT color=#4444ff>=</FONT> <FONT color=#2040a0>conn</FONT>.<FONT color=#2040a0>createStatement</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line22>22</A>     <FONT color=#2040a0>String</FONT> <FONT color=#2040a0>strSql</FONT> <FONT color=#4444ff>=</FONT> <FONT color=#008000>"SELECT * FROM R_TUT_USERS"</FONT><FONT color=#4444ff>;</FONT><BR><A name=line23>23</A>     <FONT color=#2040a0>rs</FONT> <FONT color=#4444ff>=</FONT> <FONT color=#2040a0>stmt</FONT>.<FONT color=#2040a0>executeQuery</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>strSql</FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line24>24</A>     <FONT color=#444444>//把ResultSet转化成Result</FONT><BR><A name=line25>25</A>     <STRONG><SPAN class=style1>Result</SPAN> <SPAN class=style1>userData</SPAN> <FONT color=#4444ff>=</FONT> <SPAN class=style1>ResultSupport.toResult</SPAN><FONT color=#4444ff>(</FONT><SPAN class=style1>rs</SPAN><FONT color=#4444ff>);</FONT></STRONG><BR><A name=line26>26</A>     <FONT color=#444444>//当我们把结果放到某个Model bean后，就可以关闭数据库连接了.</FONT><BR><A name=line27>27</A>     <FONT color=#444444>//为了简化，我们暂且把pageContext看作Model Bean好了！</FONT><BR><A name=line28>28</A>     <FONT color=#2040a0>pageContext</FONT>.<FONT color=#2040a0>setAttribute</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#008000>"userData"</FONT>, <FONT color=#2040a0>userData</FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line29>29</A>   <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line30>30</A>   <STRONG>catch</STRONG> <FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>Exception</FONT> <FONT color=#2040a0>ex</FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line31>31</A>     <FONT color=#444444>// handle any errors</FONT><BR><A name=line32>32</A>     <FONT color=#2040a0>System</FONT>.<FONT color=#2040a0>out</FONT>.<FONT color=#2040a0>println</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#008000>"SQLException: "</FONT> <FONT color=#4444ff>+</FONT> <FONT color=#2040a0>ex</FONT>.<FONT color=#2040a0>getMessage</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line33>33</A>   <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line34>34</A>   <STRONG>finally</STRONG> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line35>35</A>     <STRONG>try</STRONG> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line36>36</A>       <STRONG>if</STRONG> <FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>rs</FONT> <FONT color=#4444ff>!</FONT><FONT color=#4444ff>=</FONT> <STRONG>null</STRONG><FONT color=#4444ff><STRONG>)</STRONG></FONT> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line37>37</A>         <FONT color=#2040a0>rs</FONT>.<FONT color=#2040a0>close</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line38>38</A>       <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line39>39</A>       <STRONG>if</STRONG> <FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>stmt</FONT> <FONT color=#4444ff>!</FONT><FONT color=#4444ff>=</FONT> <STRONG>null</STRONG><FONT color=#4444ff><STRONG>)</STRONG></FONT> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line40>40</A>         <FONT color=#2040a0>stmt</FONT>.<FONT color=#2040a0>close</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line41>41</A>       <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line42>42</A>       <STRONG>if</STRONG> <FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>conn</FONT> <FONT color=#4444ff>!</FONT><FONT color=#4444ff>=</FONT> <STRONG>null</STRONG><FONT color=#4444ff><STRONG>)</STRONG></FONT> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line43>43</A>         <FONT color=#2040a0>conn</FONT>.<FONT color=#2040a0>close</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line44>44</A>       <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line45>45</A>     <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line46>46</A>     <STRONG>catch</STRONG> <FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#2040a0>SQLException</FONT> <FONT color=#2040a0>ex</FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT> <FONT color=#4444ff><STRONG>{</STRONG></FONT><BR><A name=line47>47</A>       <FONT color=#2040a0>System</FONT>.<FONT color=#2040a0>out</FONT>.<FONT color=#2040a0>println</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#008000>"SQL Exception: "</FONT> <FONT color=#4444ff>+</FONT> <FONT color=#2040a0>ex</FONT>.<FONT color=#2040a0>getMessage</FONT><FONT color=#4444ff><STRONG>(</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff><STRONG>)</STRONG></FONT><FONT color=#4444ff>;</FONT><BR><A name=line48>48</A>     <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line49>49</A>   <FONT color=#4444ff><STRONG>}</STRONG></FONT><BR><A name=line50>50</A>   <FONT color=#444444>//DAO的逻辑结束</FONT><BR><A name=line51>51</A> <FONT color=#4444ff>%</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line52>52</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#2040a0>html</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line53>53</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#2040a0>head</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line54>54</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#2040a0>title</FONT><FONT color=#4444ff>&gt;</FONT><FONT color=#2040a0>test</FONT><FONT color=#4444ff>&lt;</FONT>/<FONT color=#2040a0>title</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line55>55</A> <FONT color=#4444ff>&lt;</FONT>/<FONT color=#2040a0>head</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line56>56</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#2040a0>body</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line57>57</A> <FONT color=#444444>&lt;!--// 下面当作是表示层吧 //--&gt;</FONT><BR><A name=line58>58</A> <FONT color=#4444ff>&lt;</FONT><FONT color=#2040a0>c</FONT><FONT color=#4444ff>:</FONT><FONT color=#2040a0>forEach</FONT> <FONT color=#2040a0>items</FONT><FONT color=#4444ff>=</FONT><FONT color=#008000>"${userData.rows}"</FONT> <FONT color=#2040a0>var</FONT><FONT color=#4444ff>=</FONT><FONT color=#008000>"user"</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line59>59</A>   <FONT color=#4444ff>&lt;</FONT><FONT color=#2040a0>c</FONT><FONT color=#4444ff>:</FONT><FONT color=#2040a0>out</FONT> <FONT color=#2040a0>value</FONT><FONT color=#4444ff>=</FONT><FONT color=#008000>'${user.name}'</FONT>/<FONT color=#4444ff>&gt;</FONT><BR><A name=line60>60</A> <FONT color=#4444ff>&lt;</FONT>/<FONT color=#2040a0>c</FONT><FONT color=#4444ff>:</FONT><FONT color=#2040a0>forEach</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line61>61</A> <FONT color=#4444ff>&lt;</FONT>/<FONT color=#2040a0>body</FONT><FONT color=#4444ff>&gt;</FONT><BR><A name=line62>62</A> <FONT color=#4444ff>&lt;</FONT>/<FONT color=#2040a0>html</FONT><FONT color=#4444ff>&gt;</FONT>
</PRE></TD></TR></TBODY></TABLE><img src ="http://www.blogjava.net/Victor/aggbug/23102.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-12-09 11:08 <a href="http://www.blogjava.net/Victor/articles/23102.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java中文问题详解(转)</title><link>http://www.blogjava.net/Victor/articles/22876.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Wed, 07 Dec 2005 07:38:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/22876.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/22876.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/22876.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/22876.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/22876.html</trackback:ping><description><![CDATA[我来说一下tomcat如何实现jsp的你就明白了。 <BR>预备知识： <BR>　1.字节和unicode <BR>　　java内核是unicode的，就连class文件也是，但是很多媒体，包括文件/流的保存方式 <BR>　　是使用字节流的。 因此java要对这些字节流经行转化。char是unicode的，而byte是字节. <BR>　　java中byte/char互转的函数在sun.io的包中间有。其中bytetocharconverter类是中调度， <BR>　　可以用来告诉你，你用的convertor。其中两个很常用的静态函数是 <BR>　　 public static bytetocharconverter getdefault() ; <BR>　　 public static bytetocharconverter getconverter(string encoding); <BR>　　如果你不指定converter，则系统会自动使用当前的encoding,gb平台上用gbk,en平台上用 <BR>　　8859_1 <BR>　　 <BR>　　我们来就一个简单的例子： <BR>　　　　　"你"的gb码是：0xc4e3 ,unicode是0x4f60 <BR>　　　　　你用: <BR>　　　　　--encoding="gb2312"; <BR>　　　　　--byte b[]={(byte)'\u00c4',(byte)'\u00e3'}; <BR>　　　　　--convertor=bytetocharconverter.getconverter(encoding); <BR>　　　　　--char [] c=converter.convertall(b); <BR>　　　　　--for(int i=0;i　　　　　--{ <BR>　　　　　-- system.out.println(integer.tohexstring(c[i])); <BR>　　　　　--} <BR>　　　　　--打印出来是0x4f60 <BR>　　　　　--但是如果使用8859_1的编码，打印出来是 <BR>　　　　　--0x00c4,0x00e3 <BR>　　　　　----例１ <BR>　　　　 反过来： <BR>　　　　 --encoding="gb2312"; <BR>　　　　 　　　char c[]={'\u4f60'}; <BR>　　　　　　　 convertor=bytetocharconverter.getconverter(encoding); <BR>　　　　　--byte [] b=converter.convertall(c); <BR>　　　　　--for(int i=0;i　　　　　--{ <BR>　　　　　-- system.out.println(integer.tohexstring(b[i])); <BR>　　　　　--} <BR>　　　　　　--打印出来是：0xc4,0xe3 <BR>　　　　　　----例２ <BR>　　　　　　--如果用8859_1就是0x3f，?号，表示无法转化　　　　　　-- <BR>　　　　　 很多中文问题就是从这两个最简单的类派生出来的。而却有很多类　　 <BR>　　不直接支持把encoding输入，这给我们带来诸多不便。很多程序难得用encoding <BR>　　了，直接用default的encoding，这就给我们移植带来了很多困难 <BR>　　-- <BR>　　2.utf-8 <BR>　　--utf-8是和unicode一一对应的，其实现很简单 <BR>　　-- <BR>　　 -- 7位的unicode: 0 _ _ _ _ _ _ _ <BR>　　--11位的unicode: 1 1 0 _ _ _ _ _ 1 0 _ _ _ _ _ _ <BR>　　--16位的unicode: 1 1 1 0 _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <BR>　　--21位的unicode: 1 1 1 1 0 _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ 1 0 _ _ _ _ _ _ <BR>　　--大多数情况是只使用到16位以下的unicode: <BR>　　--"你"的gb码是：0xc4e3 ,unicode是0x4f60 <BR>　　--我们还是用上面的例子 <BR>　　--　　--例１：0xc4e3的二进制： <BR>　　--　　--　　　 1 1 0 0 0 1 0 0 1 1 1 0 0 0 1 1 <BR>　　--　　--　　　 由于只有两位我们按照两位的编码来排，但是我们发现这行不通， <BR>　　--　　--　　　 因为第７位不是0因此，返回"?" <BR>　　--　　--　　　 <BR>　　--　　--例２：0x4f60的二进制： <BR>　　--　　--　　　 0 1 0 0 1 1 1 1 0 1 1 0 0 0 0 0 <BR>　　--　　--　　　 我们用utf-8补齐，变成： <BR>　　--　　--　　　 11100100 10111101 10100000 <BR>　　--　　--　　　 e4--bd-- a0 <BR>　　--　　--　　　 于是返回0xe4,0xbd,0xa0 <BR>　　--　　-- <BR>　　3.string和byte[] <BR>　　--string其实核心是char[],然而要把byte转化成string，必须经过编码。 <BR>　　--string.length()其实就是char数组的长度，如果使用不同的编码，很可 <BR>　　--能会错分，造成散字和乱码。 <BR>　　--例： <BR>　　----byte [] b={(byte)'\u00c4',(byte)'\u00e3'}; <BR>　　----string str=new string(b,encoding);　　---- <BR>　　----如果encoding=8859_1，会有两个字，但是encoding=gb2312只有一个字　　---- <BR>　　--这个问题在处理分页是经常发生 <BR>　　4.reader,writer/inputstream,outputstream <BR>　　--reader和writer核心是char，inputstream和outputstream核心是byte。 <BR>　　--但是reader和writer的主要目的是要把char读/写inputstream/outputstream <BR>--一个reader的例子： <BR>--文件test.txt只有一个"你"字，0xc4,0xe3-- <BR>--string encoding=; <BR>--inputstreamreader reader=new inputstreamreader( <BR>----new fileinputstream("text.txt"),encoding); <BR>--char []c=new char[10]; <BR>--int length=reader.read(c); <BR>--for(int i=0;i----system.out.println(c[i]); <BR>　　--如果encoding是gb2312，则只有一个字符，如果encoding=8859_1，则有两个字符 <BR>　　-------- <BR>-- <BR>-- <BR>　　 <BR>　　 ---- <BR>　2.我们要对java的编译器有所了解： <BR>　--javac -encoding <BR>　 我们常常没有用到encoding这个参数。其实encoding这个参数对于跨平台的操作是很重要的。 <BR>　 如果没有指定encoding，则按照系统的默认encoding,gb平台上是gb2312，英文平台上是iso8859_1。　 <BR>　--java的编译器实际上是调用sun.tools.javac.main的类，对文件进行编译，这个类　-- <BR>　有compile函数中间有一个encoding的变量,-encoding的参数其实直接传给encoding变量。 <BR>　编译器就是根据这个变量来读取java文件的，然后把用utf-8形式编译成class文件。 <BR>　一个例子： <BR>　--public void test() <BR>　--{ <BR>　----string str="你"; <BR>　----filewriter write=new filewriter("test.txt"); <BR>　----write.write(str); <BR>　----write.close(); <BR>　--} <BR>　----例３ <BR>--如果用gb2312编译，你会找到e4 bd a0的字段 <BR>-- <BR>--如果用8859_1编译， <BR>--00c4 00e3的二进制： <BR>--00000000 11000100 00000000 11100011-- <BR>--因为每个字符都大于7位，因此用11位编码： <BR>--11000001 10000100 11000011 10100011 <BR>--c1-- 84--　c3--　 a3 <BR>--你会找到c1 84 c3 a3 -- <BR>　　　　 <BR>　　但是我们往往忽略掉这个参数，因此这样往往会有跨平台的问题： <BR>　　--　　例３在中文平台上编译，生成zhclass <BR>　　--　　例３在英文平台上编译，输出enclass <BR>　　--1.　 zhclass在中文平台上执行ok,但是在英文平台上不行 <BR>　　--2.　 enclass在英文平台上执行ok,但是在中文平台上不行 <BR>　　原因： <BR>　--1.在中文平台上编译后，其实str在运行态的char[]是0x4f60,　---- <BR>　--在中文平台上运行，filewriter的缺省编码是gb2312,因此 <BR>　--chartobyteconverter会自动用调用gb2312的converter,把str转化 <BR>　--成byte输入到fileoutputstream中，于是0xc4,0xe3放进了文件。 <BR>　--但是如果是在英文平台下，chartobyteconverter的缺省值是8859_1, <BR>　--filewriter会自动调用8859_1去转化str,但是他无法解释，因此他会 <BR>　--输出"?"　---- <BR>　--2.　在英文平台上编译后，其实str在运行态的char[]是0x00c4 0x00e3,　---- <BR>　--在中文平台上运行，中文无法识别，因此会出现?? <BR>　--　　在英文平台上，0x00c4--&gt;0xc4,0x00e3-&gt;0xe3，因此0xc4,0xe3被放进了 <BR>　--文件 <BR>---- <BR>1.对于jsp正文的解释： <BR>--tomcat首先看一下你的叶面中有没有" <BR><BR><BR>http://localhost/test/test.jsp?value=你 <BR><BR>结果:你好你 <BR><BR>但这种方法局限性较大，比如对上传的文章分段，这样的做法是死定的，最好的 <BR>解决方案是用这种方案： <BR><BR><BR>你好 <BR><BR><BR><BR>必读好文,但解决方案不敢恭维 <BR>发言者：小熊 <BR>时 间：2000/10/17 17:21:31 来 自：www.javaunion.org <BR><BR><BR>-------------------------------------------------------------------------------- <BR><BR>1.网页传参数不提倡用get方法,而且用户可以调整是否用utf-8发送 <BR>2.建议jsp中最好不要用,实际上加不加这句都有实现中文正常显示的方案,我认为不加方便些,至少不用写这些代码,如下的配置我认为可以使中文正常显示: <BR>a.所有的javabean用iso8859-1编译 <BR>b.jsp文件中不要写以上charset=gb2312的语句(写了反而错) <BR><BR>在tomcat情况下注意以上2点就行---了,等等,对于其他有可能不行的jsp服务器,加上以下 <BR>c.服务器上的操作系统语言设为英文(像没有装类似bluepoint中文系统的linux一般本来就是英文) <BR>就行---了 <BR><BR>谁要是还不对,请报告.... <BR><BR><BR>re：必读好文,但解决方案不敢恭维 <BR>发言者：congling <BR>时 间：2000/10/17 21:06:23 来 自：www.javaunion.org <BR><BR><BR>-------------------------------------------------------------------------------- <BR><BR>tomcat的参数问题无论是get或是post方式都是用8859_1编码的。这个可以看tomcat servlet实现的源代码: <BR>a) 对于post方法 <BR>　javax.servlet.http.httputils的parsepostdata方法： (对于post的form数据) <BR>　string postedbody = new string(postedbytes, 0, len, "8859_1");)这里是没有问题的因为中文都会用%来说明。但是parsename这个函数，却没有把是中文的东西整合起来，他只是简单的拼凑，因此可以认定他是使用8859_1的编码规则 <BR>　 sb.append((char) integer.parseint(s.substring(i+1, i+3), 16)); <BR>----　　i += 2; <BR>-- <BR>b) 对于get方法 <BR>　org.apache.tomcat.service.http.httprequestadapter <BR>　　　--　line=new string(buf, 0, count, <BR>　　　　　　 constants.characterencoding.default); <BR>----constants.characterencoding.default=8859_1 <BR>　这段代码不好跟踪，千万不要被一些假象迷惑住。httprequestadapter是从requestimpl中派生的。但是，实际上用8080端口的server并没有直接用到requestimpl，而是用了httprequestadapter来获得querystring <BR><BR>对于加不加encoding，我保留我的意见，因为如果要解决上传文件分页问题，必须要用他来编码。而且编码能保证在一些beans当中的传递性。 <BR><BR>看来我要在这里说明一下了 <BR>发言者：小熊 <BR>时 间：1970/01/01 07:59:59 来 自：www.javaunion.org <BR><BR><BR>-------------------------------------------------------------------------------- <BR><BR>tomcat仅仅是一个对jsp1.1,servlet2.2的一个标准的实现,我们不应该要求这个免费软件在细致末节上和性能上都面面俱到,它主要考虑的英文用户,这也是为什么不作特殊转换我们的汉字用url方法传递有问题的原因,我们大部分浏览器ie其高级设置中始终以utf-8发送url的选项缺省是选上的,如果说这是tomcat的bug也是可以的,另外tomcat不管当前的操作系统是什么语言,好像都按iso8859去编译jsp,我觉得也有点欠妥,但是不管怎么说,新标准的实现和热门的软件在语言的支持方面永远都是先考虑英文 <BR><BR>我的方案什么说要好一些呢 <BR>1.还是那句话,英文国家的软件永远都是先考虑英文,java虚拟机的规范中要求虚拟机内部必须实现iso8859,unicode,utf-8三种,其他的不作要求,我们用的jdk中的虚拟机就是这样,嵌入式的就更不用说了,也就是说其他的encode都很可能不是java虚拟机内部直接支持的,我们的中文自然也不在其列,需要外部的包支持转换,sun jdk应该在i18n.jar中,用iso8859速度最快,不需要其它调用和交换什么的,更没有读包的io操作 <BR>2.至少少写了代码,没有额外操作,简洁的风格谁不喜欢 <BR>3.所写的jsp页面国际性化好,我才写了一个jsp+javabeans的聊天室软件(没有用到servlet,jsp真的确实很好),同样的程序美国人用他们的浏览器进入就是英文界面,中文进入就是中文界面,如果加上charset=gb2312至少很麻烦 <BR>4.限定了gb2312,如果用户要用gbk,怎么办,不加更好,不管什么的字符集,只要我当前浏览器设定的是,我就能显示出来 <BR><BR>总结:无论从速度上,开发效率上,和可扩展性上考虑,我的方案都比你的好,另外,我找不到你的方案比我的好的地方 <BR><BR><FONT color=green>中华技术网整理发布 <A href="http://www.asfocus.com/">http://www.asfocus.com</A></FONT><BR><img src ="http://www.blogjava.net/Victor/aggbug/22876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-12-07 15:38 <a href="http://www.blogjava.net/Victor/articles/22876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最安全的加密算法 (摘自温少的blog)</title><link>http://www.blogjava.net/Victor/articles/21922.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Wed, 30 Nov 2005 02:50:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/21922.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/21922.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/21922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/21922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/21922.html</trackback:ping><description><![CDATA[在密码学里，有一种理想的加密方案，叫做一次一密乱码本（one-time pad）。<BR><BR>one-time pad的算法有以下要求：<BR>1、密钥必须随机产生<BR>2、密钥不能重复使用<BR>3、密钥和密文的长度是一样的。<BR><BR>one-time pad是最安全的加密算法，双方一旦安全交换了密钥，之后交换信息的过程就是绝对安全的啦。这种算法一直在一些要求高度机密的场合使用，据说美国和前苏联之间的热线电话、前苏联的间谍都是使用One-time pad的方式加密的。不管超级计算机工作多久，也不管多少人，用什么方法和技术，具有多大的计算能力，都不可能破解。<BR><BR>一次一密的一种实现方式，如下：<BR>
<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: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG id=Codehighlighter1_28_356_Open_Image onclick="this.style.display='none'; Codehighlighter1_28_356_Open_Text.style.display='none'; Codehighlighter1_28_356_Closed_Image.style.display='inline'; Codehighlighter1_28_356_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_28_356_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_28_356_Closed_Text.style.display='none'; Codehighlighter1_28_356_Open_Image.style.display='inline'; Codehighlighter1_28_356_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align=top><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">&nbsp;OneTimePadUtil&nbsp;</SPAN><SPAN id=Codehighlighter1_28_356_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"><IMG alt="" src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_28_356_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG id=Codehighlighter1_87_354_Open_Image onclick="this.style.display='none'; Codehighlighter1_87_354_Open_Text.style.display='none'; Codehighlighter1_87_354_Closed_Image.style.display='inline'; Codehighlighter1_87_354_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_87_354_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_87_354_Closed_Text.style.display='none'; Codehighlighter1_87_354_Open_Image.style.display='inline'; Codehighlighter1_87_354_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;xor(</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;bytes,&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;keyBytes)&nbsp;</SPAN><SPAN id=Codehighlighter1_87_354_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"><IMG alt="" src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_87_354_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG id=Codehighlighter1_128_173_Open_Image onclick="this.style.display='none'; Codehighlighter1_128_173_Open_Text.style.display='none'; Codehighlighter1_128_173_Closed_Image.style.display='inline'; Codehighlighter1_128_173_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_128_173_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_128_173_Closed_Text.style.display='none'; Codehighlighter1_128_173_Open_Image.style.display='inline'; Codehighlighter1_128_173_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(keyBytes.length&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;bytes.length)&nbsp;</SPAN><SPAN id=Codehighlighter1_128_173_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"><IMG alt="" src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_128_173_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throw</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;IllegalArgumentException();<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;resultBytes&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[bytes.length];<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_271_328_Open_Image onclick="this.style.display='none'; Codehighlighter1_271_328_Open_Text.style.display='none'; Codehighlighter1_271_328_Closed_Image.style.display='inline'; Codehighlighter1_271_328_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_271_328_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_271_328_Closed_Text.style.display='none'; Codehighlighter1_271_328_Open_Image.style.display='inline'; Codehighlighter1_271_328_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">for</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">;&nbsp;i&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;resultBytes.length;&nbsp;</SPAN><SPAN style="COLOR: #000000">++</SPAN><SPAN style="COLOR: #000000">i)&nbsp;</SPAN><SPAN id=Codehighlighter1_271_328_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"><IMG alt="" src="http://www.cnblogs.com/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_271_328_Open_Text><SPAN style="COLOR: #000000">{<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resultBytes[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">)&nbsp;(keyBytes[i]&nbsp;</SPAN><SPAN style="COLOR: #000000">^</SPAN><SPAN style="COLOR: #000000">&nbsp;bytes[i]);<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;resultBytes;<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000"><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</SPAN></SPAN></DIV></DIV><BR>使用例子：<BR>
<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: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid">
<DIV><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">String&nbsp;plainText&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">温少</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">;<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>String&nbsp;keyText&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">密码</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">;<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;plainBytes&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;plainText.getBytes();<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;keyBytes&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;keyText.getBytes();<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top>assert&nbsp;plainBytes.length&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;keyBytes.length;<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">加密</SPAN><SPAN style="COLOR: #008000"><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;cipherBytes&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;OneTimePadUtil.xor(plainBytes,&nbsp;keyBytes);<BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">解密</SPAN><SPAN style="COLOR: #008000"><BR><IMG alt="" src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;cipherPlainBytes&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;OneTimePadUtil.xor(cipherBytes,&nbsp;keyBytes);</SPAN></DIV></DIV>
<P><BR>这是最简单的加密算法，但也是最安全的机密算法。前天和朋友讨论到了这个问题，所以写了这篇文章。</P><img src ="http://www.blogjava.net/Victor/aggbug/21922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-11-30 10:50 <a href="http://www.blogjava.net/Victor/articles/21922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP编程进度条设计实例(转)</title><link>http://www.blogjava.net/Victor/articles/6293.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Fri, 17 Jun 2005 07:44:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/6293.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/6293.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/6293.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/6293.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/6293.html</trackback:ping><description><![CDATA[许多Web应用、企业应用涉及到长时间的操作，例如复杂的数据库查询或繁重的<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/XML">XML</A>处理等，虽然这些任务主要由数据库系统或中间件完成，但任务执行的结果仍旧要借助<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>才能发送给用户。本文介绍了一种通过改进前端表现层来改善用户感觉、减轻服务器负载的办法。 
<P>　　当<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>调用一个必须长时间运行的操作，且该操作的结果不能（在服务器端）缓冲，用户每次请求该页面时都必须长时间等待。很多时候，用户会失去耐心，接着尝试点击浏览器的刷新按钮，最终失望地离开。</P>
<P>　　本文介绍的技术是把繁重的计算任务分离开来，由一个独立的线程运行，从而解决上述问题。当用户调用<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>页面时，<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>页面会立即返回，并提示用户任务已经启动且正在执行<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>页面自动刷新自己，报告在独立线程中运行的繁重计算任务的当前进度，直至任务完成。</P>
<P>一、模拟任务</P>
<P>　　首先我们设计一个TaskBean类，它实现java.lang.Runnable接口，其run()方法在一个由<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>页面（start.jsp）启动的独立线程中运行。终止run()方法执行由另一个<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>页面stop.jsp负责。TaskBean类还实现了java.io.Serializable接口，这样<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP">JSP</A>页面就可以将它作为<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java">Java</A>Bean调用：<BR>package test.barBean;<BR>import java.io.Serializable;</P><BR>
<P>public class TaskBean implements Runnable, Serializable {<BR>private int counter;<BR>private int sum;<BR>private boolean started;<BR>private boolean running;<BR>private int sleep;</P><BR>
<P>public TaskBean() {<BR>counter = 0;<BR>sum = 0;<BR>started = false;<BR>running = false;<BR>sleep = 100;<BR>}<BR>}</P><BR>
<P>　　TaskBean包含的“繁重任务”是计算1+2+3…+100的值，不过它不通过100*(100+1)/2=5050公式计算，而是由run()方法调用work()方法100次完成计算。work()方法的代码如下所示，其中调用Thread.sleep()是为了确保任务总耗时约10秒。 </P><BR>
<P>protected void work() {<BR>try {<BR>Thread.sleep(sleep);<BR>counter++;<BR>sum += counter;<BR>} catch (InterruptedException e) {<BR>setRunning(false);<BR>}<BR>}<BR><BR>　　status.jsp页面通过调用下面的getPercent()方法获得任务的完成状况： </P><BR>
<P>public synchronized int getPercent() {<BR>return counter;<BR>}<BR><BR>如果任务已经启动，isStarted()方法将返回true： <BR></P>
<P>public synchronized boolean isStarted() {<BR>return started;<BR>}<BR></P>
<P><BR></P>
<P>　　如果任务已经完成，isCompleted()方法将返回true： </P>
<P><BR></P>
<P>public synchronized boolean isCompleted() {<BR>return counter == 100;<BR>}<BR></P>
<P><BR></P>
<P>　　如果任务正在运行，isRunning()方法将返回true： </P>
<P><BR></P>
<P>public synchronized boolean isRunning() {<BR>return running;<BR>}</P>
<P><BR></P>
<P><BR>　　SetRunning()方法由start.jsp或stop.jsp调用，当running参数是true时。SetRunning()方法还要将任务标记为“已经启动”。调用setRunning(false)表示要求run()方法停止执行。 </P>
<P><BR></P>
<P>public synchronized void setRunning(boolean running) {<BR>this.running = running;<BR>if (running)<BR>started = true;<BR>}<BR><BR>　　任务执行完毕后，调用getResult()方法返回计算结果如果任务尚未执行完毕，它返回null： </P>
<P><BR></P>
<P>public synchronized Object getResult() {<BR>if (isCompleted())<BR>return new Integer(sum);<BR>else<BR>return null;<BR>}<BR><BR>　　当running标记为true、completed标记为false时，run()方法调用work()。在实际应用中，run()方法也许要执行复杂的SQL查询、解析大型<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/XML"><FONT color=#002c99>XML</FONT></A>文档，或者调用消耗大量<A class=Channel_KeyLink href="http://www.intodigi.com/Hard/DIY/CPUMemory"><FONT color=#002c99>CPU</FONT></A>时间的EJB方法。注意“繁重的任务”可能要在远程服务器上执行。报告结果的<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面有两种选择：或者等待任务结束，或者使用一个进度条。 </P>
<P><BR></P>
<P>public void run() {<BR>try {<BR>setRunning(true);<BR>while (isRunning() &amp;&amp; !isCompleted())<BR>work();<BR>} finally {<BR>setRunning(false);<BR>}<BR>}</P>
<P>二、启动任务 <BR></P>
<P></P>
<P><BR></P>
<P>　　start.jsp是web.xml部署描述符中声明的欢迎页面，web.xml的内容是： </P>
<P><BR></P>
<P>&lt;?xml version="1.0" encoding="GB2312"?&gt;</P>
<P><BR></P>
<P>&lt;!DOCTYPE web-app<BR>PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"<BR>"http://java.sun.com/dtd/web-app_2_3.dtd"&gt;</P>
<P><BR></P>
<P>&lt;web-app&gt;<BR>&lt;welcome-file-list&gt;<BR>&lt;welcome-file&gt;start.jsp&lt;/welcome-file&gt;<BR>&lt;/welcome-file-list&gt;<BR>&lt;/web-app&gt;</P>
<P><BR></P>
<P>　　start.jsp启动一个专用的线程来运行“繁重的任务”，然后把HTTP请求传递给status.jsp。</P>
<P><BR></P>
<P>　　start.jsp页面利用&lt;jsp:useBean&gt;标记创建一个TaskBean的实例，将scope属性定义为session使得对于来自同一浏览器的HTTP请求，其他页面也能提取到同一个Bean对象。start.jsp通过调用session.removeAttribute("task")确保&lt;jsp:useBean&gt;创建了一个新的Bean对象，而不是提取一个旧对象（例如，同一个用户会话中更早的<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面所创建的Bean对象）。 </P>
<P><BR></P>
<P>　　下面是start.jsp页面的代码清单： </P>
<P><BR></P>
<P>&lt;% session.removeAttribute("task"); %&gt;</P>
<P><BR></P>
<P>&lt;jsp:useBean id="task" scope="session" <BR>class="test.barBean.TaskBean"/&gt;</P>
<P><BR></P>
<P>&lt;% task.setRunning(true); %&gt;<BR>&lt;% new Thread(task).start(); %&gt;<BR>&lt;jsp:forward page="status.jsp"/&gt;<BR><BR>　　start.jsp创建并设置好TaskBean对象之后，接着创建一个Thread，并将Bean对象作为一个Runnable实例传入。调用start()方法时新创建的线程将执行TaskBean对象的run()方法。 </P>
<P><BR></P>
<P>　　现在有两个线程在并发执行：执行<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面的线程（称之为“<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>线程”），由<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面创建的线程（称之为“任务线程”）。接下来，start.jsp利用调用status.jsp，status.jsp显示出进度条以及任务的执行情况。注意status.jsp和start.jsp在同一个<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>线程中运行。 </P>
<P><BR></P>
<P>　　start.jsp在创建线程之前就把TaskBean的running标记设置成了true，这样，即使当<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>线程已开始执行status.jsp而任务线程的run()方法尚未启动，也能够确保用户会得到“任务已开始运行”的状态报告。 </P>
<P><BR></P>
<P>　　将running标记设置成true、启动任务线程这两行代码可以移入TaskBean构成一个新的方法，然后由<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面调用这个新方法。一般而言，<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面应当尽量少用<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>代码，即我们应当尽可能地把<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>代码放入<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>类。不过本例中我们不遵从这一规则，把new Thread(task).start()直接放入start.jsp突出表明<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>线程创建并启动了任务线程。 </P>
<P><BR></P>
<P>　　在<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面中操作多线程必须谨慎，注意<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>线程和其他线程实际上是并发执行的，就象在桌面应用程序中，我们用一个线程来处理GUI事件，另外再用一个或多个线程来处理后台任务。不过在<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>环境中，考虑到多个用户同时请求某一个页面的情况，同一个<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面可能会在多个线程中同时运行另外，有时同一个用户可能会向同一个页面发出多个请求，虽然这些请求来自同一个用户，它们也会导致服务器同时运行一个<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面的多个线程。 <BR clear=all></P>
<P>三、任务进度 <BR></P>
<P>　　status.jsp页面利用一个<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Website/HTMLCSS"><FONT color=#002c99>HTML</FONT></A>进度条向用户显示任务的执行情况。首先，status.jsp利用&lt;jsp:useBean&gt;标记获得start.jsp页面创建的Bean对象： </P>
<P><BR></P>
<P>&lt;jsp:useBean id="task" scope="session"<BR>class="test.barBean.TaskBean"/&gt;</P>
<P><BR></P>
<P>　　为了及时反映任务执行进度，status.jsp会自动刷新。<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>Script代码setTimeout("location='status.jsp'", 1000)将每隔1000毫秒刷新页面，重新请求status.jsp，不需要用户干预。 </P>
<P><BR></P>
<P>&lt;<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Website/HTMLCSS"><FONT color=#002c99>HTML</FONT></A>&gt;</P>
<P><BR></P>
<P>&lt;HEAD&gt;<BR>&lt;TITLE&gt;<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>进度条&lt;/TITLE&gt;<BR>&lt;% if (task.isRunning()) { %&gt;<BR>&lt;SCRIPT LANGUAGE="<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>Script"&gt;<BR>setTimeout("location='status.jsp'", 1000);<BR>&lt;/SCRIPT&gt;<BR>&lt;% } %&gt;<BR>&lt;/HEAD&gt;</P>
<P><BR></P>
<P>&lt;ODY&gt;</P>
<P><BR></P>
<P>　　进度条实际上是一个<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Website/HTMLCSS"><FONT color=#002c99>HTML</FONT></A>表格，包含10个单元——即每个单元代表任务总体的10%进度。 </P>
<P><BR></P>
<P>&lt;H1 ALIGN="CENTER"&gt;<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>进度条&lt;/H1&gt;</P>
<P><BR></P>
<P>&lt;H2 ALIGN="CENTER"&gt;<BR>结果: &lt;%= task.getResult() %&gt;&lt;BR&gt;<BR>&lt;% int percent = task.getPercent(); %&gt;<BR>&lt;%= percent %&gt;%<BR>&lt;/H2&gt;</P>
<P><BR></P>
<P>&lt;TABLE WIDTH="60%" ALIGN="CENTER"<BR>BORDER=1 CELLPADDING=0 CELLSPACING=2&gt;<BR>&lt;TR&gt;<BR>&lt;% for (int i = 10; i &lt;= percent; i += 10) { %&gt;<BR>&lt;TD WIDTH="10%" BGCOLOR="#000080"&gt;&amp;nbsp;&lt;/TD&gt;<BR>&lt;% } %&gt;<BR>&lt;% for (int i = 100; i &gt; percent; i -= 10) { %&gt;<BR>&lt;TD WIDTH="10%"&gt;&amp;nbsp;&lt;/TD&gt;<BR>&lt;% } %&gt;<BR>&lt;/TR&gt;<BR>&lt;/TABLE&gt;<BR><BR>　　任务执行情况分下面几种状态：正在执行，已完成，尚未开始，已停止： </P>
<P><BR></P>
<P>&lt;TABLE WIDTH="100%" BORDER=0 CELLPADDING=0 CELLSPACING=0&gt;<BR>&lt;TR&gt;<BR>&lt;TD ALIGN="CENTER"&gt;<BR>&lt;% if (task.isRunning()) { %&gt;<BR>正在执行<BR>&lt;% } else { %&gt;<BR>&lt;% if (task.isCompleted()) { %&gt;<BR>完成<BR>&lt;% } else if (!task.isStarted()) { %&gt;<BR>尚未开始<BR>&lt;% } else { %&gt;<BR>已停止<BR>&lt;% } %&gt;<BR>&lt;% } %&gt;<BR>&lt;/TD&gt;<BR>&lt;/TR&gt;<BR><BR>页面底部提供了一个按钮，用户可以用它来停止或重新启动任务： </P>
<P></P>
<P><BR></P>
<P>&lt;TR&gt;<BR>&lt;TD ALIGN="CENTER"&gt;<BR>&lt;BR&gt;<BR>&lt;% if (task.isRunning()) { %&gt;<BR>&lt;FORM METHOD="GET" ACTION="stop.jsp"&gt;<BR>&lt;INPUT TYPE="SUBMIT" VALUE="停止"&gt;<BR>&lt;/FORM&gt;<BR>&lt;% } else { %&gt;<BR>&lt;FORM METHOD="GET" ACTION="start.jsp"&gt;<BR>&lt;INPUT TYPE="SUBMIT" VALUE="开始"&gt;<BR>&lt;/FORM&gt;<BR>&lt;% } %&gt;<BR>&lt;/TD&gt;<BR>&lt;/TR&gt;<BR>&lt;/TABLE&gt;<BR>&lt;/BODY&gt;&lt;/<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Website/HTMLCSS"><FONT color=#002c99>HTML</FONT></A>&gt;</P>
<P><BR></P>
<P>　　只要不停止任务，约10秒后浏览器将显示出计算结果5050： </P>
<P><BR></P>
<P>　　四、停止任务 </P>
<P><BR></P>
<P>　　stop.jsp页面把running标记设置成false，从而停止当前的计算任务： </P>
<P><BR></P>
<P>&lt;jsp:useBean id="task" scope="session"<BR>class="test.barBean.TaskBean"/&gt;</P>
<P><BR></P>
<P>&lt;% task.setRunning(false); %&gt;<BR>&lt;jsp:forward page="status.jsp"/&gt;<BR><BR>　　注意最早的<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>版本提供了Thread.stop方法，但JDK从1.2版开始已经不赞成使用Thread.stop方法，所以我们不能直接调用Thread.stop()。 </P>
<P><BR></P>
<P>　　第一次运行本文程序的时候，你会看到任务的启动有点延迟同样地，第一次点击“停止”按钮时也可以看到任务并没有立即停止运行（特别是如果机器配置较低的话，延迟的感觉更加明显），这些延迟都是由于编译<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面导致的。编译好<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>页面之后，应答速度就要快多了。 </P>
<P><BR></P>
<P>　　五、实际应用 </P>
<P><BR></P>
<P>　　进度条不仅使得用户界面更加友好，而且对服务器的性能也有好处，因为进度条会不断地告诉用户当前的执行进度，用户不会再频繁地停止并重新启动（刷新）当前的任务。另一方面，创建单独的线程来执行后台任务也会消耗不少资源，必要时可考虑通过一个线程池来实现Thread对象的重用。另外，频繁地刷新进度页面也增加了<A class=Channel_KeyLink href="http://www.intodigi.com/net"><FONT color=#002c99>网络</FONT></A>通信开销，所以务必保持进度页面简洁短小。 </P>
<P><BR></P>
<P>　　在实际应用中，后台执行的繁重任务可能不允许停止，或者它不能提供详细的执行进度数据。例如，查找或更新关系数据库时，SQL命令执行期间不允许中途停止——不过如果用户表示他想要停止或中止任务，程序可以在SQL命令执行完毕后回退事务。 </P>
<P><BR></P>
<P>　　解析<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/XML"><FONT color=#002c99>XML</FONT></A>文档的时候，我们没有办法获知已解析内容精确的百分比。如果用DOM解析<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/XML"><FONT color=#002c99>XML</FONT></A>文档，直到解析完成后才得到整个文档树如果用SAX，虽然可以知道当前解析的内容，但通常不能确定还有多少内容需要解析。在这些场合，任务的执行进度只能靠估计得到。 </P>
<P><BR></P>
<P>　　估计一个任务需要多少执行时间通常是很困难的，因为它涉及到许多因素，即使用实际测试的办法也无法得到可靠的结论，因为服务器的负载随时都在变化之中。一种简单的办法是测量任务每次执行所需时间，然后根据最后几次执行的平均时间估算。如果要提高估计时间的精确度，应当考虑实现一种针对应用特点的算法，综合考虑多种因素，例如要执行的SQL语句类型、要解析的<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/XML"><FONT color=#002c99>XML</FONT></A>模式的复杂程度，等等。 </P>
<P><BR></P>
<P>　　结束语：本文例子显示出用<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/JSP"><FONT color=#002c99>JSP</FONT></A>、<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>、<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Website/HTMLCSS"><FONT color=#002c99>HTML</FONT></A>和<A class=Channel_KeyLink href="http://www.intodigi.com/net/Website/Program/Java"><FONT color=#002c99>Java</FONT></A>Script构造进度条是相当容易的，真正困难的是如何将它用到实际应用之中，特别是获得后台任务的进度信息，但这个问题没有通用的答案，每一种后台执行的任务都有它自己的特点，必须按照具体情况具体分析。 </P>
<P><BR></P><img src ="http://www.blogjava.net/Victor/aggbug/6293.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-06-17 15:44 <a href="http://www.blogjava.net/Victor/articles/6293.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 编程技术中汉字问题的分析及解决(转)</title><link>http://www.blogjava.net/Victor/articles/5553.html</link><dc:creator>Victor</dc:creator><author>Victor</author><pubDate>Sat, 04 Jun 2005 03:44:00 GMT</pubDate><guid>http://www.blogjava.net/Victor/articles/5553.html</guid><wfw:comment>http://www.blogjava.net/Victor/comments/5553.html</wfw:comment><comments>http://www.blogjava.net/Victor/articles/5553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/Victor/comments/commentRss/5553.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/Victor/services/trackbacks/5553.html</trackback:ping><description><![CDATA[<DIV>
<P>段明辉<BR>自由撰稿人<BR>2000 年 11月 8日</P><!-- END title and author lines--><!-- Editor #5: Begin Table of Contents--><BR><!-- End Table of Contents--><!-- comments #6: html content of the paper-->
<P><CITE>在基于 Java 语言的编程中，我们经常碰到汉字的处理及显示的问题。一大堆看不懂的乱码肯定不是我们愿意看到的显示效果，怎样才能够让那些汉字正确显示呢？Java 语言默认的编码方式是UNICODE ，而我们中国人通常使用的文件和数据库都是基于 GB2312 或者 BIG5 等方式编码的，怎样才能够恰当地选择汉字编码方式并正确地处理汉字的编码呢？本文将从汉字编码的常识入手，结合 Java 编程实例，分析以上两个问题并提出解决它们的方案。</CITE></P><BR><BR>
<P>现在 Java 编程语言已经广泛应用于互联网世界，早在 Sun 公司开发 Java 语言的时候，就已经考虑到对非英文字符的支持了。Sun 公司公布的 Java 运行环境（JRE）本身就分英文版和国际版，但只有国际版才支持非英文字符。不过在 Java 编程语言的应用中，对中文字符的支持并非如同 Java Soft 的标准规范中所宣称的那样完美，因为中文字符集不只一个，而且不同的操作系统对中文字符的支持也不尽相同，所以会有许多和汉字编码处理有关的问题在我们进行应用开发中困扰着我们。有很多关于这些问题的解答，但都比较琐碎，并不能够满足大家迫切解决问题的愿望，关于 Java 中文问题的系统研究并不多，本文从汉字编码常识出发，分析 Java 中文问题，希望对大家解决这个问题有所帮助。</P><A id=1 name=1></A>
<P align=left><B>汉字编码的常识</B></P>
<P>我们知道，英文字符一般是以一个字节来表示的，最常用的编码方法是 ASCII 。但一个字节最多只能区分256个字符，而汉字成千上万，所以现在都以双字节来表示汉字，为了能够与英文字符分开，每个字节的最高位一定为1，这样双字节最多可以表示64K格字符。我们经常碰到的编码方式有 GB2312、BIG5、UNICODE 等。关于具体编码方式的详细资料，有兴趣的读者可以查阅相关资料。我肤浅谈一下和我们关系密切的 GB2312 和 UNICODE。GB2312 码，中华人民共和国国家标准汉字信息交换用编码，是一个由中华人民共和国国家标准总局发布的关于简化汉字的编码，通行于中国大陆地区及新加坡，简称国标码。两个字节中，第一个字节（高字节）的值为区号值加32（20H），第二个字节（低字节）的值为位号值加32（20H），用这两个值来表示一个汉字的编码。UNICODE 码是微软提出的解决多国字符问题的多字节等长编码，它对英文字符采取前面加“0”字节的策略实现等长兼容。如 “A” 的 ASCII 码为0x41，UNICODE 就为0x00，0x41。利用特殊的工具各种编码之间可以互相转换。</P><A id=2 name=2></A>
<P><B>Java 中文问题的初步认识</B></P>
<P>我们基于 Java 编程语言进行应用开发时，不可避免地要处理中文。Java 编程语言默认的编码方式是 UNICODE，而我们通常使用的数据库及文件都是基于 GB2312 编码的，我们经常碰到这样的情况：浏览基于 JSP 技术的网站看到的是乱码，文件打开后看到的也是乱码，被 Java 修改过的数据库的内容在别的场合应用时无法继续正确地提供信息。</P>
<P>String sEnglish = “apple”;</P>
<P>String sChinese = “苹果”;</P>
<P>String s = “苹果 apple ”;</P>
<P>sEnglish 的长度是5，sChinese的长度是4，而 s 默认的长度是14。对于 sEnglish来说， Java 中的各个类都支持得非常好，肯定能够正确显示。但对于 sChinese 和 s 来说，虽然 Java Soft 声明 Java 的基本类已经考虑到对多国字符的支持（默认 UNICODE 编码），但是如果操作系统的默认编码不是 UNICODE ，而是国标码等。从 Java 源代码到得到正确的结果，要经过 “Java 源代码-&gt; Java 字节码-&gt; ;虚拟机-&gt;操作系统-&gt;显示设备”的过程。在上述过程中的每一步骤，我们都必须正确地处理汉字的编码，才能够使最终的显示结果正确。</P>
<P>“ Java 源代码-&gt; Java 字节码”，标准的 Java 编译器 javac 使用的字符集是系统默认的字符集，比如在中文 Windows 操作系统上就是 GBK ,而在 Linux 操作系统上就是ISO-8859-1，所以大家会发现在 Linux 操作系统上编译的类中源文件中的中文字符都出了问题，解决的办法就是在编译的时候添加 encoding 参数，这样才能够与平台无关。用法是</P>
<P>javac –encoding GBK。</P>
<P>“ Java 字节码-&gt;虚拟机-&gt;操作系统”， Java 运行环境 （JRE） 分英文版和国际版，但只有国际版才支持非英文字符。 Java 开发工具包 （JDK） 肯定支持多国字符，但并非所有的计算机用户都安装了 JDK 。很多操作系统及应用软件为了能够更好的支持 Java ，都内嵌了 JRE 的国际版本，为自己支持多国字符提供了方便。</P>
<P>“操作系统-&gt;显示设备”，对于汉字来说，操作系统必须支持并能够显示它。英文操作系统如果不搭配特殊的应用软件的话，是肯定不能够显示中文的。</P>
<P>还有一个问题，就是在 Java 编程过程中，对中文字符进行正确的编码转换。例如，向网页输出中文字符串的时候，不论你是用</P>
<P>out.println(string);还是用</P>
<P>&lt;%=string%&gt;，都必须作 UNICODE 到 GBK 的转换，或者手动，或者自动。在 JSP 1.0中，可以定义输出字符集，从而实现内码的自动转换。用法是</P>
<P>&lt;%@page contentType=”text/html;charset=gb2312” %&gt;</P>
<P>但是在一些 JSP 版本中并没有提供对输出字符集的支持，（例如 JSP 0.92），这就需要手动编码输出了，方法非常多。最常用的方法是</P>
<P>String s1 = request.getParameter(“keyword”);</P>
<P>String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);</P>
<P>getBytes 方法用于将中文字符以“ISO-8859-1”编码方式转化成字节数组，而“GBK” 是目标编码方式。我们从以ISO-8859-1方式编码的数据库中读出中文字符串 s1 ，经过上述转换过程，在支持 GBK 字符集的操作系统和应用软件中就能够正确显示中文字符串 s2 。</P><A id=3 name=3></A>
<P><B>Java 中文问题的表层分析及处理</B></P>
<DIV align=center>
<TABLE cellSpacing=0 cellPadding=0 width="80%" border=1>
<TBODY>
<TR>
<TD width="100%" colSpan=4>
<P align=center>背景</P></TD></TR>
<TR>
<TD width="25%">
<P align=center>开发环境</P></TD>
<TD width="25%">
<P align=center>JDK1.15</P></TD>
<TD width="25%">
<P align=center>Vcafe2.0</P></TD>
<TD width="25%">
<P align=center>JPadPro</P></TD></TR>
<TR>
<TD width="25%">
<P align=center>服务器端</P></TD>
<TD width="25%">
<P align=center>NT IIS</P></TD>
<TD width="25%">
<P align=center>Sybase System</P></TD>
<TD width="25%">
<P align=center>Jconnect（JDBC）</P></TD></TR>
<TR>
<TD width="25%">
<P align=center>客户端</P></TD>
<TD width="25%">
<P align=center>IE5.0</P></TD>
<TD width="25%">
<P align=center>Pwin98</P></TD>
<TD width="25%">
<P align=center>?span &gt;</P></TD></TR></TBODY></TABLE></DIV>
<P>.CLASS 文件存放在服务器端，由客户端的浏览器运行 APPLET ， APPLET 只起调入 FRAME 类等主程序的作用。界面包括 Textfield ，TextArea，List，Choice 等。</P>
<P>I.用 JDBC 执行 SELECT 语句从服务器端读取数据（中文）后，将数据用 APPEND 方法加到 TextArea（TA） ，不能正确显示。但加到 List 中时，大部分汉字却可正确显示。</P>
<P>将数据按“ISO-8859-1” 编码方式转化为字节数组，再按系统缺省编码方式 （Default Character Encoding） 转化为 STRING ，即可在 TA 和 List 中正确显示。</P>
<P>程序段如下：</P>
<P>dbstr2 = results.getString(1);</P>
<P>//After reading the result from DB server，converting it to string.</P>
<P>dbbyte1 = dbstr2.getBytes(“iso-8859-1”);</P>
<P>dbstr1 = new String(dbbyte1);</P>
<P>在转换字符串时不采用系统默认编码方式，而直接采用“ GBK” 或者 “GB2312” ,在 A 和 B 两种情况下，从数据库取数据都没有问题。</P>
<P>II.处理方式与“取中文”相逆，先将 SQL 语句按系统缺省编码方式转化为字节数组，再按“ISO-8859-1”编码方式转化为 STRING ，最后送去执行，则中文信息可正确写入数据库。</P>
<P>程序段如下：</P>
<P>sqlstmt = tf_input.getText();</P>
<P>//Before sending statement to DB server，converting it to sql statement.</P>
<P>dbbyte1 = sqlstmt.getBytes();</P>
<P>sqlstmt = newString(dbbyte1,”iso-8859-1”);</P>
<P>_stmt = _con.createStatement();</P>
<P>_stmt.executeUpdate(sqlstmt);</P>
<P>……</P>
<P>问题：如果客户机上存在 CLASSPATH 指向 JDK 的 CLASSES.ZIP 时（称为 A 情况），上述程序代码可正确执行。但是如果客户机只有浏览器，而没有 JDK 和 CLASSPATH 时（称为 B 情况），则汉字无法正确转换。</P>
<P>我们的分析：</P>
<P>1.经过测试，在 A 情况下，程序运行时系统的缺省编码方式为 GBK 或者 GB2312 。在 B 情况下，程序启动时浏览器的 JAVA 控制台中出现如下错误信息：</P>
<P>Can't find resource for sun.awt.windows.awtLocalization_zh_CN</P>
<P>然后系统的缺省编码方式为“8859-1”。</P>
<P>2.如果在转换字符串时不采用系统缺省编码方式，而是直接采用 “GBK” 或“GB2312”，则在 A 情况下程序仍然可正常运行，在 B 情况下，系统出现错误：</P>
<P>UnsupportedEncodingException。</P>
<P>3.在客户机上，把 JDK 的 CLASSES.ZIP 解压后，放在另一个目录中， CLASSPATH 只包含该目录。然后一边逐步删除该目录中的 .CLASS 文件，另一边运行测试程序，最后发现在一千多个 CLASS 文件中，只有一个是必不可少的，该文件是：</P>
<P>sun.io.CharToByteDoubleByte.class。</P>
<P>将该文件拷到服务器端和其它的类放在一起，并在程序的开头 IMPORT 它，在 B 情况下程序仍然无法正常运行。</P>
<P>4.在 A 情况下，如果在 CLASSPTH 中去掉 sun.io.CharToByteDoubleByte.class ，则程序运行时测得默认编码方式为“8859-1”，否则为 “GBK” 或 “GB2312” 。</P>
<P>如果 JDK 的版本为1.2以上的话，在 B 情况下遇到的问题得到了很好的解决，测试的步骤同上，有兴趣的读者可以尝试一下。</P><A id=4 name=4></A>
<P><B>Java 中文问题的根源分析及解决</B></P>
<P>在简体中文 MS Windows 98 + JDK 1.3 下，可以用 System.getProperties() 得到 Java 运行环境的一些基本属性，类 PoorChinese 可以帮助我们得到这些属性。</P>
<P>类 PoorChinese 的源代码：</P>
<P>public class PoorChinese {</P>
<P>}</P>
<P>执行 java PoorChinese 后，我们会得到:</P>
<P>系统变量 file.encoding 的值为 GBK ，user.language 的值为 zh ， user.region 的值为 CN ，这些系统变量的值决定了系统默认的编码方式是 GBK 。</P>
<P>在上述系统中，下面的代码将 GB2312 文件转换成 Big5 文件，它们能够帮助我们理解 Java 中汉字编码的转化:</P>
<P>?</P>
<P>import java.io.*;</P>
<P>import java.util.*;</P>
<P>?</P>
<P>public class gb2big5 {</P>
<P>?</P>
<P>static int iCharNum=0;</P>
<P>?</P>
<P>public static void main(String[] args) {</P>
<P>System.out.println("Input GB2312 file, output Big5 file.");</P>
<P>if (args.length!=2) {</P>
<P>System.err.println("Usage: jview gb2big5 gbfile big5file");</P>
<P>System.exit(1);</P>
<P>String inputString = readInput(args[0]);</P>
<P>writeOutput(inputString,args[1]);</P>
<P>System.out.println("Number of Characters in file: "+iCharNum+".");</P>
<P>}</P>
<P>?</P>
<P>static void writeOutput(String str, String strOutFile) {</P>
<P>try {</P>
<P>FileOutputStream fos = new FileOutputStream(strOutFile);</P>
<P>Writer out = new OutputStreamWriter(fos, "Big5");</P>
<P>out.write(str);</P>
<P>out.close();</P>
<P>}</P>
<P>catch (IOException e) {</P>
<P>e.printStackTrace();</P>
<P>e.printStackTrace();</P>
<P>}</P>
<P>}</P>
<P>?</P>
<P>static String readInput(String strInFile) {</P>
<P>StringBuffer buffer = new StringBuffer();</P>
<P>try {</P>
<P>FileInputStream fis = new FileInputStream(strInFile);</P>
<P>InputStreamReader isr = new InputStreamReader(fis, "GB2312");</P>
<P>Reader in = new BufferedReader(isr);</P>
<P>int ch;</P>
<P>while ((ch = in.read()) &gt; -1) {</P>
<P>iCharNum += 1;</P>
<P>buffer.append((char)ch);</P>
<P>}</P>
<P>in.close();</P>
<P>return buffer.toString();</P>
<P>}</P>
<P>catch (IOException e) {</P>
<P>e.printStackTrace();</P>
<P>return null;</P>
<P>}</P>
<P>}</P>
<P>}</P>
<P>?</P>
<P>编码转化的过程如下：</P>
<P>GB2312------------------&gt;Unicode-------------&gt;Big5</P>
<P>执行 java gb2big5 gb.txt big5.txt ，如果 gb.txt 的内容是“今天星期三”，则得到的文件 big5.txt 中的字符能够正确显示；而如果 gb.txt 的内容是“情人节快乐”，则得到的文件 big5.txt 中对应于“节”和“乐”的字符都是符号“？”（0x3F），可见 sun.io.ByteToCharGB2312 和 sun.io.CharToByteBig5 这两个基本类并没有编好。</P><A id=5 name=5></A>
<P>正如上例一样， Java 的基本类也可能存在问题。由于国际化的工作并不是在国内完成的，所以在这些基本类发布之前，没有经过严格的测试，所以对中文字符的支持并不像 Java Soft 所声称的那样完美。前不久，我的一位技术上的朋友发信给我说，他终于找到了 <B>Java Servlet 中文问题的根源</B>。两周以来，他一直为 Java Servlet 的中文问题所困扰，因为每面对一个含有中文字符的字符串都必须进行强制转换才能够得到正确的结果（这好象是大家公认的唯一的解决办法）。后来，他确实不想如此继续安分下去了，因为这样的事情确实不应该是高级程序员所要做的工作，他就找出 Servlet 解码的源代码进行分析，因为他怀疑问题就出在解码这部分。经过四个小时的奋斗，他终于找到了问题的根源所在。原来他的怀疑是正确的， Servlet 的解码部分完全没有考虑双字节，直接把 %XX 当作一个字符。（原来 Java Soft 也会犯这幺低级的错误！）</P>
<P>如果你对这个问题有兴趣或者遇到了同样的烦恼的话，你可以按照他的步骤<B>对</B><B>Servlet.jar 进行修改</B>：</P><A id=6 name=6></A>
<P>找到源代码 HttpUtils 中的 static private String parseName ，在返回前将 sb（StringBuffer） 复制成 byte bs[] ，然后 return new String(bs,”GB2312”)。作上述修改后就需要自己解码了：</P>
<P>HashTable form=HttpUtils .parseQueryString(request.getQueryString())或者</P>
<P>form=HttpUtils.parsePostData(……)</P>
<P>千万别忘了编译后放到 Servlet.jar 里面。</P>
<P>五、 关于 Java 中文问题的总结</P>
<P>Java 编程语言成长于网络世界，这就要求 Java 对多国字符有很好的支持。 Java 编程语言适应了计算的网络化的需求，为它能够在网络世界迅速成长奠定了坚实的基础。 Java 的缔造者 （Java Soft） 已经考虑到 Java 编程语言对多国字符的支持，只是现在的解决方案有很多缺陷在里面，需要我们付诸一些补偿性的措施。而世界标准化组织也在努力把人类所有的文字统一在一种编码之中，其中一种方案是 ISO10646 ，它用四个字节来表示一个字符。当然，在这种方案未被采用之前，还是希望 Java Soft 能够严格地测试它的产品，为用户带来更多的方便。</P></DIV><img src ="http://www.blogjava.net/Victor/aggbug/5553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/Victor/" target="_blank">Victor</a> 2005-06-04 11:44 <a href="http://www.blogjava.net/Victor/articles/5553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>