﻿<?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-Tom-随笔</title><link>http://www.blogjava.net/43880800/</link><description /><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 01:16:41 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 01:16:41 GMT</pubDate><ttl>60</ttl><item><title>Java反射学习</title><link>http://www.blogjava.net/43880800/archive/2007/12/04/165045.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Mon, 03 Dec 2007 16:55:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/12/04/165045.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/165045.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/12/04/165045.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/165045.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/165045.html</trackback:ping><description><![CDATA[<div class="postTitle"><a class="postTitle2" id="viewpost1_TitleUrl" href="http://www.blogjava.net/lcwlv929/articles/125646.html"><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">Java反射学习</span></span></span></a><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000"> </span></span></span></div>
<span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;所谓反射，可以理解为在运行时期获取对象类型信息的操作。传统的编程方法要求程序员在编译阶段决定使用的类型，但是在反射的帮助下，编程人员可以动态获取这些信息，从而编写更加具有可移植性的代码。严格地说，反射并非编程语言的特性，因为在任何一种语言都可以实现反射机制，但是如果编程语言本身支持反射，那么反射的实现就会方便很多。 </span></span></span>
<p><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">1，获得类型类<br />
&nbsp;&nbsp;&nbsp; 我们知道在Java中一切都是对象，我们一般所使用的对象都直接或间接继承自Object类。Object类中包含一个方法名叫getClass，利用这个方法就可以获得一个实例的类型类。类型类指的是代表一个类型的类，因为一切皆是对象，类型也不例外，在Java使用类型类来表示一个类型。所有的类型类都是Class类的实例。例如，有如下一段代码：<br />
A a = new A();<br />
if(a.getClass()==A.class)<br />
&nbsp;&nbsp;&nbsp; System.out.println("equal");<br />
else System.out.println("unequal");</span></span></span></p>
<p><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">&nbsp;&nbsp;&nbsp; 可以看到，对象a是A的一个实例，A某一个类，在if语句中使用a.getClass()返回的结果正是A的类型类，在Java中表示一个特定类型的类型类可以用&#8220;类型.class&#8221;的方式获得，因为a.getClass()获得是A的类型类，也就是A.class，因此上面的代码执行的结果就是打印出&#8220;equal&#8221;。特别注意的是，类型类是一一对应的，父类的类型类和子类的类型类是不同的，因此，假设A是B的子类，那么如下的代码将得到&#8220;unequal&#8221;的输出：<br />
A a = new A();<br />
if(a.getClass()==B.class)<br />
&nbsp;&nbsp;&nbsp; System.out.println("equal");<br />
else System.out.println("unequal");</span></span></span></p>
<p><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">&nbsp;&nbsp;&nbsp; 因此，如果你知道一个实例，那么你可以通过实例的&#8220;getClass()&#8221;方法获得该对象的类型类，如果你知道一个类型，那么你可以使用&#8220;.class&#8221;的方法获得该类型的类型类。<br />
&nbsp;&nbsp;&nbsp; <br />
2，获得类型的信息<br />
&nbsp;&nbsp;&nbsp; 在获得类型类之后，你就可以调用其中的一些方法获得类型的信息了，主要的方法有：<br />
getName():String：获得该类型的全称名称。<br />
getSuperClass():Class：获得该类型的直接父类，如果该类型没有直接父类，那么返回null。<br />
getInterfaces():Class[]：获得该类型实现的所有接口。<br />
isArray():boolean：判断该类型是否是数组。<br />
isEnum():boolean：判断该类型是否是枚举类型。<br />
isInterface():boolean：判断该类型是否是接口。<br />
isPrimitive():boolean：判断该类型是否是基本类型，即是否是int，boolean，double等等。<br />
isAssignableFrom(Class cls):boolean：判断这个类型是否是类型cls的父（祖先）类或父（祖先）接口。<br />
getComponentType():Class：如果该类型是一个数组，那么返回该数组的组件类型。<br />
此外还可以进行类型转换这类的操作，主要方法有：<br />
asSubclass(Class clazz):Class：将这个类型转换至clazz，如果可以转换，那么总是返回clazz这个引用，否则抛出异常。<br />
cast(Object obj):Object：将obj强制转换为这个类型类代表的类型，不能转换的话将抛出异常。</span></span></span></p>
<p><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">&nbsp;&nbsp;&nbsp; 除了这些以外，利用类型类还可以反射该类型中的所有属性和方法。在Java中所有的属性信息都用Field表示，所有的方法信息都用Method表示，这辆各类都是java.lang.reflect包中的类。在Class中提供了4个相关的方法获得类型的属性：<br />
getField(String name):Field<br />
getFields():Field[]<br />
getDeclaredField(String name):Field<br />
getDeclaredFields():Field[]<br />
其中getField用于返回一个指定名称的属性，但是这个属性必须是公有的，这个属性可以在父类中定义。如果是私有属性或者是保护属性，那么都会抛出异常提示找不到这个属性。getFields则是返回类型中的所有公有属性，所有的私有属性和保护属性都找不到。getDeclaredField获得在这个类型的声明中定义的指定名称的属性，这个属性必须是在这个类型的声明中定义，但可以使私有和保护的。getDeclaredFields获得在这个类型的声明中定义的所有属性，包括私有和保护的属性都会被返回，但是所有父类的属性都不会被返回。举个例子，先考虑下面两个类的声明：<br />
class A extends B {<br />
&nbsp;&nbsp;&nbsp; public int a1;<br />
&nbsp;&nbsp;&nbsp; private int a2;<br />
}<br />
class B {<br />
&nbsp;public int b1;<br />
&nbsp;private int b2;<br />
}<br />
如果利用A的类型类调用getFields，那么会返回a1和b1两个属性，如果调用getField("a2")则会报错；如果调用getDeclaredFields则会返回a1和a2，如果调用getDeclaredField("b1")则会报错。</span></span></span></p>
<p><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">&nbsp;&nbsp;&nbsp; 对于方法也有类似的函数即：<br />
getMethods():Method[]<br />
getMethod(String name, Class ... parameterTypes):Method<br />
getDeclaredMethods():Method[]<br />
getDeclaredMethod(Strubg name, Class ...parameterTypes):Method<br />
不定长参数...是JDK5.0以后新加入的语法。这几个方法的用法和上面的类似，只是在获得特定方法时，除了要告知方法的名字，还需要告知方法的参数，如果没有参数，那么可以传递null，或者空数组，但是最好的方法就是什么都不写，编译器会自行解决不定长参数问题。<br />
&nbsp;&nbsp;&nbsp; 如果要获得所有的属性（方法），包括公有和私有的，那么就必须利用getDeclareFields（getDeclareMethods）方法，然后再利用getSuperClass的方法获得父类，然后递归下去。<br />
&nbsp;&nbsp;&nbsp; <br />
3，属性和方法<br />
&nbsp;&nbsp;&nbsp; 所有的属性都使用Field表示，所有的方法都使用Method表示。利用Field和Method可以获得属性和方法的信息，甚至执行是获取、修改属性值和调用方法。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 对于属性，主要有以下方法可以使用：<br />
getType():Class：获得该属性的类型。<br />
getName():String：获得属性名称。<br />
isAccessible():boolean：判断该属性是否是可以访问的，通常私有和保护的类型都是不可以访问的。<br />
get(Object obj):Object：获得实例obj的属性值，如果该实例的类型中不包含这个属性，那么就会报错。<br />
set(Object obj, Object value)：设置该实例的属性值<br />
setAccessible(boolean flag)：设置该属性是否可以访问，如果你调用get和set方法，那么有可能会引发访问权限的错误，这个时候你可以调用setAccessible方法使得该属性可以访问。例如下面的代码：<br />
A a = new A();<br />
Field f = A.class.getDeclaredField("a2");<br />
f.setAccessibe(true);<br />
System.out.println(f.get(a));<br />
f.set(a,12);<br />
System.out.println(f.get(a));<br />
如果移出中间的f.setAccessibe(true);那么代码会报错，反之输出0 12。<br />
&nbsp;&nbsp;&nbsp; 对于属性而言，如果该属性的类型是基本类型，那么还可以使用一些便捷的set和get操作，例如getInt，setInt什么的，你可以根据自己的需要调用相应的方法。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 对于方法，可以有以下的方法：<br />
getName():String：获得方法的名字。<br />
getReturnType():Class：获得方法的返回值类型。<br />
getParameterTypes():Class[]：获得方法的参数类型。<br />
isAccessible():boolean：判断该方法是否是可以访问的。<br />
setAccessible(boolean flag)：设置该方法是否可以访问。<br />
invoke(Object obj, Object... args):Object：调用实例obj的相应方法，其参数由args给定，如果没有参数那么可以什么都不写。<br />
getExceptionTypes():Class[]：获得该方法可能抛出的异常类类型。<br />
这几个方法的含义和用法都和Field的类似，这里不再赘述。</span></span></span></p>
<p><span style="color: #ff6600"><span style="color: #ffcc00"><span style="color: #008000">4，创建实例<br />
&nbsp;&nbsp;&nbsp; 利用Class对象可以创建一个类型的实例。如果一个类型拥有无参数的构造函数，那么可以简单地调用Class.newInstance()方法创建一个实例。如果该类型没有无参数的构造函数，或者你希望是用某个有参数的构造函数，那么可以首先使用getConstructors()、getConstructor(Class[] parameterTypes)和getDeclaredConstructors()、getDeclaredConstructor(Class[] parameterTypes)获得构造函数，这两个方法的返回值都使Constructor类型。特别注意的是，构造函数不能继承，因此你调用getConstructor也只能返回这个类型中定义的所有公有构造函数。<br />
&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; Constructor的使用方法和Method的类似，它也存在getParameterTypes()方法和getExceptionTypes()方法，不同的是，它使用newInstance(Object... args)来调用一个构造函数，注意newInstance不需要实例对象，因为这个时候你还没创建出来这个实例呢。</span></span></span></p>
<img src ="http://www.blogjava.net/43880800/aggbug/165045.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-12-04 00:55 <a href="http://www.blogjava.net/43880800/archive/2007/12/04/165045.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ORACLE查询树型关系</title><link>http://www.blogjava.net/43880800/archive/2007/11/30/164248.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Fri, 30 Nov 2007 05:51:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/11/30/164248.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/164248.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/11/30/164248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/164248.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/164248.html</trackback:ping><description><![CDATA[<h3>ORACLE查询树型关系（connect by prior start with） </h3>
<table class="blog-content">
    <tbody>
        <tr>
            <td>
            <p>以下内容来自<a href="http://hi.baidu.com/suofang/blog/item/a58bdd5829d5e583800a1812.html" target="_blank">http://hi.baidu.com/suofang/blog/item/a58bdd5829d5e583800a1812.html</a>（其中的图片可到这个地址查看） <br />
            connect by prior start with 经常会被用到一个表中存在递归关系的时候。比如我们经常会将一个比较复杂的目录树存储到一个表中。或者将一些部门存储到一个表中，而这些部门互相有隶属关系。这个时候你就会用到connect by prior start with。 <br />
            典型的使用方法就是： <br />
            select * from table connect by prior cur_id=parent_id start with cur_id=??? <br />
            例如： <br />
            a &nbsp; b <br />
            1 &nbsp; 0 <br />
            2 &nbsp; 1 <br />
            3 &nbsp; 1 <br />
            4 &nbsp; 2 <br />
            5 &nbsp; 3 <br />
            如果想查找a=2及其下面的所有数据，则： <br />
            select * from table connect by prior a=b start with a=2 <br />
            a &nbsp; b <br />
            2 &nbsp; 1 <br />
            4 &nbsp; 2 <br />
            这些只是基础，皮毛。其实只要你灵活的构造查询语句。可以得出意想不到的结果。比如生成树每一个路径。 <br />
            但是这些记录组成的树必须正常才可以。如果有互为父子的情况，就会出现循环错误！ <br />
            示例： <br />
            <br />
            <div align="center"><img src="http://hiphotos.baidu.com/suofang/pic/item/4417de1b539427ddad6e7515.jpg" onload="if(this.width  alt="" />'800')this.width='800';if(this.height>'600')this.height='600';" border=0></div>
            <div align="center">表结构图</div>
            <div align="center"><img src="http://hiphotos.baidu.com/suofang/pic/item/9442dd130493be0a5aaf5310.jpg" onload="if(this.width  alt="" />'800')this.width='800';if(this.height>'600')this.height='600';" border=0></div>
            <div align="center">表数据</div>
            select * from tb_cus_area_cde <br />
            --子取父 <br />
            select * from tb_cus_area_cde a &nbsp; <br />
            CONNECT BY PRIOR &nbsp; a.c_snr_area=a.c_area_cde START WITH a.c_area_cde='1040101' <br />
            --父取子 <br />
            select * from tb_cus_area_cde a &nbsp; <br />
            CONNECT BY PRIOR &nbsp; a.c_area_cde=a.c_snr_area START WITH a.c_snr_area is null <br />
            <br />
            *************************自己总结 还是看CSDN吧，赛迪总是不好用<a href="http://writeblog.csdn.net/PostList.aspx" target="_blank">http://writeblog.csdn.net/PostList.aspx</a>********************************* <br />
            <div align="center"><font size="3"><font face='\"times\"'>ORACLE</font><font face='\"宋体\"'>查询树型关系（</font><font face='\"times\"'>connect by prior start with</font><font face='\"宋体\"'>）</font> <br />
            </font></div>
            <font face="宋体"><font size="3">有如下表结构：</font></font> <br />
            <font face="times"><font size="3">create table TVideoSort </font></font><br />
            <font face="times"><font size="3">(</font></font> <br />
            <font size="3"><font face='\"times\"'>FsysId &nbsp; &nbsp; &nbsp; NVARCHAR2(32 char) &nbsp; &nbsp; &nbsp; not null,</font></font> <br />
            <font size="3"><font face='\"times\"'>FSortName &nbsp; &nbsp; &nbsp; NVARCHAR2(32 char),</font></font> <br />
            <font size="3"><font face='\"times\"'>FSortTopId &nbsp; &nbsp; NVARCHAR2(32 char),</font></font> <br />
            <font size="3"><font face='\"times\"'>FSortAddress &nbsp; &nbsp; number,</font></font> <br />
            <font size="3"><font face='\"times\"'>FSortIsList &nbsp; &nbsp; char(1),</font></font> <br />
            <font size="3"><font face='\"times\"'>constraint PK_TVIDEOSORT primary key (FsysId)</font></font> <br />
            <font face="times"><font size="3">);</font></font> <br />
            <br />
            <font face="times"><br />
            </font><br />
            <font face="times"><font size="3"></font><br />
            <br />
            <font face='\"宋体\"'>数据如下：</font></font> <br />
            <font size="3"><br />
            <font face='\"times\"'></font></font><br />
            <br />
            <font size="3"><font face='\"times\"'>--</font><font face='\"宋体\"'>子查父（通过子节点向根节点追朔</font><font face='\"times\"'>.</font><font face='\"宋体\"'>）</font></font> <br />
            <font face="宋体"><font size="3">查询〔特下边〕的父节点</font></font> <br />
            <strong><font face="courier">select</font></strong><font face="courier"> FsysId,FSortName,FSortTopId,FSortAddress,FSortIsList <strong>from</strong> TVideoSort <br />
            <strong>start</strong> <strong>with</strong> FsysId=</font><font face="courier">'3703E5CD81E48D6BE040007F01001254'--</font><font face="宋体">这个是特下边的</font><font face="courier">fsysid</font><font face="courier"> <br />
            <strong>connect</strong> <strong>by</strong> <strong>prior</strong> </font><font face="courier">FSortTopId=FsysId </font><font face="courier"><br />
            <strong>order</strong> <strong>by</strong> FsortAddress <br />
            </font><br />
            <font face="宋体">结果</font><font face="courier"> <br />
            </font><br />
            <br />
            <font face="times"><font size="3"></font><br />
            <br />
            <font face='\"宋体\"'>――父查子（通过根节点遍历子节点</font><font face='\"times\"'>.</font><font face='\"宋体\"'>）</font></font> <br />
            <font face="宋体"><font size="3">查询〔特下边〕的子节点：结果</font></font> <br />
            <strong><font face="courier">select</font></strong><font face="courier"> FsysId,FSortName,FSortTopId,FSortAddress,FSortIsList <br />
            <strong>from</strong> TVideoSort <strong>start</strong> <strong>with</strong> FsysId=</font><font face="courier">'3703E5CD81E48D6BE040007F01001254'</font><font face="courier"> </font><font face="courier">--</font><font face="宋体">这个是特下边的</font><font face="courier">fsysid</font><font face="courier"> <br />
            <strong>connect</strong> <strong>by</strong> <strong>prior</strong> FsysId=FSortTopId <strong>order</strong> <strong>by</strong> FsortAddress <br />
            </font><br />
            <font face="courier"><br />
            </font><br />
            <font face="宋体"><font size="3">查询〔特长练习〕的子节点：结果</font></font> <br />
            <strong><font face="courier">select</font></strong><font face="courier"> FsysId,FSortName,FSortTopId,FSortAddress,FSortIsList <br />
            <strong>from</strong> TVideoSort <strong>start</strong> <strong>with</strong> FsysId=</font><font face="courier">'36AE4D68EC7D364CE040007F01000CA5'</font><font face="courier"> <br />
            <strong>connect</strong> <strong>by</strong> <strong>prior</strong> </font><font face="courier">FsysId=FSortTopId </font><strong><font face="courier">order</font></strong><font face="courier"> <strong>by</strong> FsortAddress</font> <br />
            <font face="courier"><br />
            </font><br />
            <br />
            <font face="times"><font size="3"></font><br />
            <br />
            <font face='\"宋体\"'>特别注意，两个查询只是</font></font><font face="courier">FsysId=FSortTopId</font><font size="3"><font face='\"宋体\"'>不同而已，即子查父则把</font><font face='\"courier\"'>FSortTopId</font><font face='\"宋体\"'>做为主表放前面，父查子则把</font><font face='\"courier\"'>FsysId</font><font face='\"宋体\"'>放前面作主表</font></font> <br />
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/43880800/aggbug/164248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-11-30 13:51 <a href="http://www.blogjava.net/43880800/archive/2007/11/30/164248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows下安装配置集成Trac </title><link>http://www.blogjava.net/43880800/archive/2007/11/29/163938.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Thu, 29 Nov 2007 02:48:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/11/29/163938.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/163938.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/11/29/163938.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/163938.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/163938.html</trackback:ping><description><![CDATA[<p>安装Trac简单吗？看到Trac复杂的安装步骤，大多数人会感到迷失，不过当我这一次安装成功后发现，原来一切都那么自然，我甚至为没有看到那么多困难感到奇怪，好的不说废话了，看看我的安装步骤。</p>
<h3 dir="ltr" style="margin-right: 0px">1，下载程序</h3>
<p>经过这次安装，发现下载正确的程序就完成了工作的80%，因为很多安装都是完全自动的，而配置又非常的简单。本文的所有下载都是针对<span style="color: rgb(255,0,0)">Subversion1.4.2</span>，不要搞错阿，下面是要下载的程序：</p>
<p>Python： <a href="http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi">http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi</a><br />
Trac： <a href="http://ftp.edgewall.com/pub/trac/trac-0.10.2.win32.exe">http://ftp.edgewall.com/pub/trac/trac-0.10.2.win32.exe</a><br />
Clearsilver： <a href="http://www.clearsilver.net/downloads/win32/clearsilver-0.9.14.win32-py2.4.exe">http://www.clearsilver.net/downloads/win32/clearsilver-0.9.14.win32-py2.4.exe</a><br />
Pysqlite： <a href="http://initd.org/pub/software/pysqlite/releases/2.3/2.3.2/pysqlite-2.3.2.win32-py2.4.exe">http://initd.org/pub/software/pysqlite/releases/2.3/2.3.2/pysqlite-2.3.2.win32-py2.4.exe</a><br />
svn-python： <a href="http://subversion.tigris.org/downloads/svn-python-1.4.2.win32-py2.4.exe">http://subversion.tigris.org/downloads/svn-python-1.4.2.win32-py2.4.exe</a></p>
<p>Python是必须的运行环境，Trac自然要下载，Clearsilver是Trac需要的页面显示框架，Pysqlite是访问sqlite数据库的程序包，而svn-python是访问Subversion的程序包。</p>
<h3><br />
2, 安装程序</h3>
<p>首先安装Python，然后其他几个安装程序能够自动识别Python的安装，从而只需要按照默认安装即可。</p>
<h3>3，配置Trac</h3>
<p>我的Python安装在&#8220;D:\Python24&#8221;，我们在D盘创建了一个目录trac，作为trac环境存放的目录，然后在&#8220;D:\Python24\Scripts&#8221;下运行（&#8220;&gt;&#8221;后的为实际输入的内容，后面相同）：</p>
<blockquote dir="ltr" style="margin-right: 0px">
<p>D:\Python24\Scripts&gt;..\python.exe trac-admin d:\trac initenv</p>
</blockquote>
<p>然后提示输入Project的名字，我们输入自己喜欢的名字，这里我输入tractest，回车；然后询问使用何种数据库，为了教程的简单，这里使用默认的sqlite数据库，直接回车即可，数据库会存放在环境存放的目录；然后会询问版本库的类型，默认即可；然后会询问版本库的路径，在这个例子里我输入的是&#8220;d:\svnroot\project2&#8221;，这个目录里就是我的一个版本库；然后提示使用何种模版，回车默认即可。最后回车，如果没有问题，trac配置环境就建立起来了，现在启动服务器即可，运行：</p>
<blockquote dir="ltr" style="margin-right: 0px">
<p>D:\Python24\Scripts&gt;..\python.exe tracd --port 8000 d:\trac</p>
</blockquote>
<p>然后在浏览器打开&#8220;http://localhost:8000/trac&#8221; ，如果看到有内容，应该就是安装成功了，恭喜！</p>
<address>提示：关于Trac中版本库中文显示的问题，我看了一下，Trac处理文件编码是通过D:\trac\conf（刚才设置trac环境目录的配置目录）中的trac.ini文件的default_charset实现的，例如下面的配置：</address>
<blockquote dir="ltr" style="margin-right: 0px">
<p>default_charset = UTF-8</p>
</blockquote>
<p>则在版本库中的文本文件如果是UTF-8编码的，则其中的中文字显示非常正常，当然如果是GBK（其实就是ISO88591）的文件，显示的中文是乱码。要想完全解决这个问题，不是单纯Trac能解决的，需要考虑更全面的方式解决。</p>
<h3><br />
总结</h3>
<p>大家如果还有什么其他需求，可以继续探索。其实Trac的安装过程并不复杂，只是因为同时要描述多种可能，所以让人摸不着头脑。在本文介绍的基础上，你还可以有很多选择，例如使用MySQL数据库（要安装MySQL和MySQL的Python库），或者使用Apache（需要安装Apache和对应的Python集成工具）。</p>
<img src ="http://www.blogjava.net/43880800/aggbug/163938.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-11-29 10:48 <a href="http://www.blogjava.net/43880800/archive/2007/11/29/163938.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>月亮之上</title><link>http://www.blogjava.net/43880800/archive/2007/11/18/161477.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Sun, 18 Nov 2007 15:50:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/11/18/161477.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/161477.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/11/18/161477.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/161477.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/161477.html</trackback:ping><description><![CDATA[　　我在遥望,市场之上<br />
　　有多少东西在自由的上涨<br />
　　昨天已忘,掏干钱囊<br />
　　我要和你重逢在借钱的路上<br />
　　手头越来越紧,只能回想<br />
　　有钱的日子,像在天堂<br />
　　呕也,呕也,呕也..<br />
　　谁在呼唤,工资快涨<br />
　　昂贵的猪肉像白云在飘荡<br />
　　东边借钱,西边还帐<br />
　　一摞摞的钞票,就送到银行<br />
　　在工资没涨的沧桑中<br />
　　致富的路在何方<br />
　　再紧紧裤带,来碗面汤<br />
　　呕也,呕也,呕也 <br />
　　呕也,呕也,呕也
<img src ="http://www.blogjava.net/43880800/aggbug/161477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-11-18 23:50 <a href="http://www.blogjava.net/43880800/archive/2007/11/18/161477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>扼腕叹息者，华为之倏然兴衰也</title><link>http://www.blogjava.net/43880800/archive/2007/09/23/147554.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Sun, 23 Sep 2007 05:43:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/09/23/147554.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/147554.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/09/23/147554.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/147554.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/147554.html</trackback:ping><description><![CDATA[<span style="color: #ff0000">　&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;&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 />
<br />
　　　　自八八年崛起，至九六年鼎盛，从零二年功成，到如今而名颓：凡二十年，水益深，火益热，薪益低，德益损，信益失。而当局者放于利而行，民声民怨，置若罔闻，不同之言，恍若未见。规令滋彰，败纪乱纲，虚言教化，狗屁文章；口号漫天，奇事滋长：有人身被完美累，有人名因欺世彰。二十年兴衰事，读来掩卷长叹：<br />
　　　　至如任某&#215;&#215;，行伍出身，刚愎自用，质胜于文；乃翁天下马上得，驱驰自依行军策；军人重功轻生死，拼死争得盛世来：时至一九九八，聚得利润大把；衣轻裘，乘宝马，多而均，富且安；军有财，士皆来，军有赏，士争往；军心大振，累死无怨；使近者悦，远者归，门庭若市，显赫一时。<br />
　　　　也信盛衰人间道，不堪反复太匆匆。<br />
　　　　盛时不长，盛事不再；成由萧何，不知谁败？颜渊弃世，名垂青史；去病早夭，功振千古；精卫叛国，名颓身辱；王莽盗器，老而不死。可怜当初不国殇，老来糊涂留短长：玩刀弄笔，不知所以，信口虚谈，不知所言；岗薪不配，前后不一；寡而不均，贫且不安；军已来，削其财；军已往，减其赏；耕牛夜犁无宿草，仓鼠昼寝有余粮；使近者怨，远者惧；侯门一入深似海，鸡肋埋身难出来。<br />
　　　　若乃产品飘洲越洋，固守陈陋主张；技术稍逊一筹，可以身体相抗；阔别半个世纪，重回朝鲜战场。烈士地下有知，必定黯然神伤：&#8220;我昔弃身沙场，只为儿久女长；早知子孙还战，隐身市井熙攘。&#8221;呜呼，月子弯弯照九州，几人欢乐几人愁，几人春宵满罗帐，几人拼死谋稻梁，几人豪宴论行赏，几人悲歌掩惆怅：&#8220;莫叹将军逼，将军要却敌，城高功亦高，尔命何足惜。&#8221;<br />
　　　　至于胡君新宇，生不逢地；煤矿淘金，殚精竭力；薪未起兮已寿终，棺已盖兮未正寝。念其生前催人泪，观其身后寒人心。呜呼，一杯清酒诗一篇，胡君昨日列神仙；玉帝若问人间事，乱世能使命换钱！<br />
　　　　念及胡家严慈，白发送子，人能换钱，钱难赎命；列钱灵堂，一屋悲怆，陈钱桌上，满堂凄凉；夜深人静，悲来填膺，半夜三更，泣不成声；泪眼相对，端坐待明，千秋万岁，为哀难胜；枯指十扣，人逐时瘦，万岁千秋，致死方休。<br />
　　　　再看上下领导，开会辟谣，依恃丰厚之赔偿，姿态得意而洋洋，欢聚于一堂，激情而开讲：仁义华为，出手百万，胡家不赔，华为没赚，外界谣传，要有主见，艰苦奋斗作风，不由胡某存殁隐现！呜呼，我见此事已叹息，又闻此语重唧唧：始信锦衣裹禽兽，终知狼能着羊皮；同是天涯沦落人，长歌此时哭兄弟；同时天地父母生，同根相煎何太急！<br />
　　酸楚酸辛三百天，易岗易薪一周年，一年三百六十日，都在岗薪匹配中；员工至今未被泽，领导月月有绩效；行政供奉厚黑学，华电弥漫拖字诀；负人负己负天下，丧德丧信丧民心。于是乎，贱买应届学生，自谓源远流长，庙小妖气笼罩，偏爱外来和尚；年年坝上插新秧，为他人做嫁衣裳；平原满目离离苗，移植他处好成长；子胥旋即归吴国，马童不日随刘邦；大厦将倾寻栋梁，栋梁都在别家忙；寡人何力回天？不死以待时亡。<br />
　　　　及夫每到年末，聚会奇多，千里逢迎，白丁满座；有附庸风雅之土人，多自诩高雅之文盲，马戏开幕，粉墨登场，莫笑平常不知书，嘴上吐出黄金屋：洋洋洒洒上千篇，两个黄鹂鸣脆柳，洒洒洋洋数万言，一行白鹭上青天；可怜中华文化上下五千年，千篇万言不堪看，篇篇抗战，句句亮剑，与会者成百上千，宁无一个有新意，宁无一人有己见？清明祭坟，新春追远，溯祖只到三七年？子孙如此多娇，羞死虞舜，气折唐尧。<br />
　　　　故公司之道，曰：骗人，自骗，把人骗，员工之铭，是：欺人，自欺，被人欺；弄智失信，玩人丧德，无德富贵，不知其可；万人质疑，惭言雷锋，千夫所指，愧对诚信；冷眼旁观，效走傅军，热心企盼，再起一男；春江水暖，老鸭先知，大树未倒，猢狲先散，大旗衰落，近在眼前，祸起萧墙，为期不远。<br />
　　　　至于笔者，拼命挣钱，养家糊口，深知其难；感知遇恩，低调收尾贵发一言，恨欺人甚，大路不平终需人铲；敢竭鄙城，针砭所见，曲突徙薪，为时不晚，焦头烂额，盛世可接；迷途知返，还能中兴，亡羊补牢，尚可华为！</span> 
<img src ="http://www.blogjava.net/43880800/aggbug/147554.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-09-23 13:43 <a href="http://www.blogjava.net/43880800/archive/2007/09/23/147554.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 栈与堆 de 区别</title><link>http://www.blogjava.net/43880800/archive/2007/08/30/141443.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Thu, 30 Aug 2007 09:11:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/08/30/141443.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/141443.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/08/30/141443.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/141443.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/141443.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 栈与堆都是Java用来在Ram中存放数据的地方。与C++不同，Java自动管理栈和堆，程序员不能直接地设置栈或堆。 <br>&nbsp; &nbsp; &nbsp;Java的堆是一个运行时数据区,类的对象从中分配空间。这些对象通过new、newarray、anewarray和multianewarray等指令建立，它们不需要程序代码来显式的释放。堆是由垃圾回收来负责的，堆的优势是可以动态地分配内存大小，生存期也不必事先告诉编译器，因为它是在运行时动态分配内存的，Java的垃圾收集器会自动收走这些不再使用的数据。但缺点是，由于要在运行时动态分配内存，存取速度较慢。 <br>&nbsp; &nbsp; &nbsp;栈的优势是，存取速度比堆要快，仅次于寄存器，栈数据可以共享。但缺点是，存在栈中的数据大小与生存期必须是确定的，缺乏灵活性。栈中主要存放一些基本类型的变量（,int, short, long, byte, float, double, boolean, char）和对象句柄。 <br>栈有一个很重要的特殊性，就是存在栈中的数据可以共享。假设我们同时定义： <br>int a = 3; <br>int b = 3； <br>&nbsp; &nbsp; &nbsp; 编译器先处理int a = 3；首先它会在栈中创建一个变量为a的引用，然后查找栈中是否有3这个值，如果没找到，就将3存放进来，然后将a指向3。接着处理int b = 3；在创建完b的引用变量后，因为在栈中已经有3这个值，便将b直接指向3。这样，就出现了a与b同时均指向3的情况。 <br>&nbsp; &nbsp; &nbsp; 这时，如果再令a=4；那么编译器会重新搜索栈中是否有4值，如果没有，则将4存放进来，并令a指向4；如果已经有了，则直接将a指向这个地址。因此a值的改变不会影响到b的值。 <br>&nbsp; &nbsp; &nbsp; 要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的，因为这种情况a的修改并不会影响到b, 它是由编译器完成的，它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态，会影响到另一个对象引用变量。 <br>String是一个特殊的包装类数据。可以用： <br>String str = new String("abc"); <br>String str = "abc"; <br>&nbsp; &nbsp; &nbsp; 两种的形式来创建，第一种是用new()来新建对象的，它会在存放于堆中。每调用一次就会创建一个新的对象。而第二种是先在栈中创建一个对String类的对象引用变量str，然后查找栈中有没有存放"abc"，如果没有，则将"abc"存放进栈，并令str指向&#8221;abc&#8221;，如果已经有&#8221;abc&#8221; 则直接令str指向&#8220;abc&#8221;。 <br>比较类里面的数值是否相等时，用equals()方法；当测试两个包装类的引用是否指向同一个对象时，用==，下面用例子说明上面的理论。 <br>String str1 = "abc"; <br>String str2 = "abc"; <br>System.out.println(str1==str2); //true <br>可以看出str1和str2是指向同一个对象的。 <br>String str1 =new String ("abc"); <br>String str2 =new String ("abc"); <br>System.out.println(str1==str2); // false <br>用new的方式是生成不同的对象。每一次生成一个。 <br>&nbsp; &nbsp; &nbsp;因此用第二种方式创建多个&#8221;abc&#8221;字符串,在内存中其实只存在一个对象而已. 这种写法有利与节省内存空间. 同时它可以在一定程度上提高程序的运行速度，因为JVM会自动根据栈中数据的实际情况来决定是否有必要创建新对象。而对于String str = new String("abc")；的代码，则一概在堆中创建新对象，而不管其字符串值是否相等，是否有必要创建新对象，从而加重了程序的负担。 <br>&nbsp; &nbsp; &nbsp; 另一方面, 要注意: 我们在使用诸如String str = "abc"；的格式定义类时，总是想当然地认为，创建了String类的对象str。担心陷阱！对象可能并没有被创建！而可能只是指向一个先前已经创建的对象。只有通过new()方法才能保证每次都创建一个新的对象。 <br>由于String类的immutable性质，当String变量需要经常变换其值时，应该考虑使用StringBuffer类，以提高程序效率。 
<img src ="http://www.blogjava.net/43880800/aggbug/141443.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-08-30 17:11 <a href="http://www.blogjava.net/43880800/archive/2007/08/30/141443.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP 中 AJAX 的表单提交中文问题的简单解决方案 - GBK 版本(引用) </title><link>http://www.blogjava.net/43880800/archive/2007/07/25/132313.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Wed, 25 Jul 2007 07:01:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/07/25/132313.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/132313.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/07/25/132313.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/132313.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/132313.html</trackback:ping><description><![CDATA[<div style="FONT-SIZE: 10pt"><a id=viewpost1_TitleUrl href="http://www.blogjava.net/beansoft/archive/2006/12/31/91144.html">JSP 中 AJAX 的表单提交中文问题的简单解决方案 - GBK 版本(引用)</a> </div>
<p style="FONT-SIZE: 10pt">作者: <a href="&#109;&#97;&#105;&#108;&#116;&#111;&#58;&#98;&#101;&#97;&#110;&#115;&#111;&#102;&#116;&#64;&#49;&#50;&#54;&#46;&#99;&#111;&#109;">beansoft@126.com</a> 2007.01.03</p>
<p style="FONT-SIZE: 10pt">下载本文源码: <a href="http://www.blogjava.net/Files/beansoft/ajaxform_gbk.zip">ajaxform_gbk.zip</a> 6KB<br></p>
转载请注明原创作者, 尊重他人劳动成果.
<p style="FONT-SIZE: 10pt">更新:<br>2007-01-03<br>修复了 AJAXFormer 中第二个参数 resultDiv 处理不当的问题;<br>增加了从服务器端返回脚本并加以执行的功能;<br>增加了表单提交后网络出错的错误显示功能.<br>这些新功能都已经放在示例页面中了.</p>
<p style="FONT-SIZE: 10pt">测试通过: Resin 3.0.18, Tomcat 5.0.30, 5.5.20; 浏览器: IE 6/Firefox 2.0.<br></p>
<p style="FONT-SIZE: 10pt">上一篇文章 <a href="http://www.blogjava.net/beansoft/archive/2006/12/25/89835.html">JSP 中 AJAX 的表单提交中文问题的简单解决方案</a> 主要是针对 UTF-8 版本的进行处理的, 鉴于中国大陆地区大部分还是用 GBK 编码写 JSP, 因此本文就针对 GBK 的实践结果进行介绍.</p>
<p style="FONT-SIZE: 10pt">有朋友提到 <a href="http://www.blogjava.net/errorfun/archive/2006/12/30/91000.html">当AJAX遭遇GBK的尴尬</a> 里说当 AJAX 使用 GBK 编码后, 表单提交将出现乱码. 如前文所述, 只要全部采用 UTF-8 编码, 是没有任何问题的. 那么都用 GBK 呢?</p>
<p style="FONT-SIZE: 10pt">首先要讲的是我们的文章还是一样的原则: 尽可能少的改动原来的代码来解决中文乱码问题. 所以本文的示例没有用过滤器等方法.</p>
<p style="FONT-SIZE: 10pt">那么使用 GBK 编码到底有没有乱码问题呢?</p>
<p style="FONT-SIZE: 10pt">第一个关键点就是 AJAX 的表单提交代码必须正确的按照 HTTP 规范实现, 即要保持原来的 GET/POST 方式不变, 也要保持里面的内容和浏览器提交的内容一摸一样. 以下内容摘自我编写的内部培训教材:</p>
<p style="FONT-SIZE: 10pt">----------------- 引用开始 -----------------</p>
<p style="FONT-SIZE: 10pt">首先必须要介绍一下 HTTP 协议和 GET, POST 的工作方式.</p>
<p style="FONT-SIZE: 10pt">当用户在Web浏览器地址栏中输入一个带有http://前缀的URL并按下Enter后,或者在Web页面中某个以http://开头的超链接上单击鼠标,HTTP事务处理的第一个阶段--建立连接阶段就开始了.HTTP的默认端口是80.<br>随着连接的建立,HTTP就进入了客户向服务器发送请求的阶段.客户向服务器发送的请求是一个有特定格式的ASCII消息,其语法规则为:</p>
<table>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt">6KB<br></td>
        </tr>
    </tbody>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt" width="100%">&lt; Method &gt; &lt; URL &gt; &lt; HTTP Version &gt; &lt;\n&gt;<br>{ &lt;Header&gt;:&lt;Value&gt; &lt;\n&gt;}*<br>&lt;\n&gt;<br>{ Entity Body }</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">请求消息的顶端是请求行,用于指定方法,URL和HTTP协议的版本,请求行的最后是回车换行.方法有GET,POST,HEAD,PUT,DELETE等.<br>在请求行之后是若干个报头(Header)行.每个报头行都是由一个报头和一个取值构成的二元对,报头和取值之间以":"分隔;报头行的最后是回车换行. 常见的报头有Accept(指定MIME媒体类型),Accept_Charset(响应消息的编码方式),Accept_Encoding(响应消息的字符集),User_Agent(用户的浏览器信息)等.<br>在请求消息的报头行之后是一个回车换行,表明请求消息的报头部分结束.在这个\n之后是请求消息的消息实体(Entity Body).<br>Web服务器在收到客户请求并作出处理之后,要向客户发送应答消息.与请求消息一样,应答消息的语法规则为:</p>
<table borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt" width="100%">&lt; HTTP Version&gt; &lt;Status Code&gt; [&lt;Message&gt;]&lt;\n&gt;<br>{ &lt;Header&gt;:&lt;Value&gt; &lt;\n&gt; } *<br>&lt;\n&gt;<br>{ Entity Body }</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">应答消息的第一行为状态行,其中包括了HTTP版本号,状态码和对状态码进行简短解释的消息;状态行的最后是回车换行.状态码由3位数字组成,有5类:<br></p>
<ul>
    <li>1XX 保留
    <li>2XX 表示成功
    <li>3XX 表示URL已经被移走
    <li>4XX 表示客户错误
    <li>5XX 表示服务器错误</li>
</ul>
<p style="FONT-SIZE: 10pt">例如:415,表示不支持改媒体类型;503,表示服务器不能访问.最常见的是200,表示成功.常见的报头有:Last_Modified(最后修改时间),Content_Type(消息内容的MIME类型),Content_Length(内容长度)等.<br>在报头行之后也是一个回车换行,用以表示应答消息的报头部分的结束,以及应答消息实体的开始.<br>下面是一个应答消息的例子:</p>
<table borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt" width="100%">HTTP/1.0 200 OK<br>Date: Moday,07-Apr-97 21:13:02 GMT<br>Server:NCSA/1.1<br>MIME_Version:1.0<br>Content_Type:text/html<br>Last_Modified:Thu Dec 5 09:28:01 1996<br>Coentent_Length:3107<br><br>&lt;HTML&gt;&lt;HEAD&gt;&lt;TITLE&gt;...&lt;/HTML&gt;</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">那么 GET 和 POST 有什么区别? 区别就是一个在 URL 请求里面附带了表单参数和值, 一个是在 HTTP 请求的消息实体中. 用下面的例子可以很容易的看到同样的数据通过GET和POST来发送的区别, 发送的数据是 username=张三 :</p>
<p style="FONT-SIZE: 10pt">　GET 方式, 浏览器键入 http://localhost?username=张三<br></p>
<table borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt" width="100%">GET /?username=%E5%BC%A0%E4%B8%89 HTTP/1.1<br>Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*<br>Accept-Language: zh-cn<br>Accept-Encoding: gzip, deflate<br>User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)<br>Host: localhost<br>Connection: Keep-Alive</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">POST 方式:</p>
<table borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt" width="100%">POST / HTTP/1.1<br>Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/vnd.ms-powerpoint, application/vnd.ms-excel, application/msword, */*<br>Accept-Language: zh-cn<br>Content-Type: application/x-www-form-urlencoded<br>Accept-Encoding: gzip, deflate<br>User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322)<br>Host: localhost<br>Content-Length: 28<br>Connection: Keep-Alive<br><br>username=%E5%BC%A0%E4%B8%89</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">比较一下上面的两段文字, 您会发现 GET 方式把表单内容放在前面的请求头中, 而 POST 则把这些内容放在请求的主体中了, 同时 POST 中把请求的 Content-Type 头设置为 application/x-www-form-urlencoded. 而发送的正文都是一样的, 可以这样来构造一个表单提交正文:</p>
<p style="FONT-SIZE: 10pt">encodeURIComponent(arg1)=encodeURIComponent(value1)&amp;encodeURIComponent(arg2)=encodeURIComponent(value2)&amp;.....</p>
<p style="FONT-SIZE: 10pt">注: encodeURIComponent 返回一个包含了 charstring 内容的新的 String 对象（Unicode 格式）， 所有空格、标点、重音符号以及其他非 ASCII 字符都用 %xx 编码代替，其中 xx 等于表示该字符的十六进制数。 例如，空格返回的是 "%20" 。 字符的值大于 255 的用 %uxxxx 格式存储。参见 JavaScript 的 encodeURIComponent() 方法.</p>
<p style="FONT-SIZE: 10pt">下面就讨论一下如何在 JavaScript 中执行一个 GET 或者 POST 请求. 如果您用过 Java, 那么您可能熟悉下列的用 java.net.URLConnection 类进行 POST 操作的代码(参考 <a href="http://www.javaworld.com/javatips/jw-javatip34.html">Java Tip 34: POSTing via Java</a> ):<br>　</p>
<table id=table1 borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt">URL url;<br>URLConnection urlConn;<br>DataOutputStream printout;<br>// URL of CGI-Bin or jsp, asp script.<br>url = new URL ("somepage");<br>// URL connection channel.<br>urlConn = url.openConnection();<br>// ......<br>// No caching, we want the real thing.<br>urlConn.setUseCaches (false);<br>// Specify the content type.<br>urlConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");<br>// Send POST output.<br>printout = new DataOutputStream (urlConn.getOutputStream ());<br>String content = "name=" + URLEncoder.encode ("Buford Early") + "&amp;email=" + URLEncoder.encode ("buford@known-space.com");<br>printout.writeBytes (content);<br>printout.flush ();<br>printout.close ();</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">以上的代码向 somepage 发送了一次 POST 请求, 数据为 name = Buford Early, email = buford@known-space.com.<br>用JavaScript 来执行 POST/GET 请求是同样的原理, 下面的代码展示了分别用 XMLHttpRequest 对象向 somepage 用 GET 和 POST 两种方式发送和上例相同的数据的具体过程:<br>GET 方式</p>
<table id=table2 borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt">var postContent =<br>"name=" + encodeURIComponent("Buford Early") + "&amp;email=" + encodeURIComponent("buford@known-space.com");<br>xmlhttp.open("GET", "somepage" + "?" + postContent, true);<br>xmlhttp.send(null);</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">POST 方式</p>
<table id=table3 borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt">var postContent =<br>"name=" + encodeURIComponent("Buford Early") + "&amp;email=" + encodeURIComponent("buford@known-space.com");<br>xmlhttp.open("POST", "somepage", true);<br>xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");<br>xmlhttp.send(postContent);</td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">至此希望你已经能够理解如何用 JavaScript 中的 XMLHttpRequest 对象来执行 GET/POST 操作, 剩下的工作就是您如何来构造这些提交的参数了, 最后我给出一个将现有的 form 提交代码修改为异步的 AJAX 提交的代码(注意目前作者还不知道如何让 file 上传表单域也能异步上传文件). 首先请看两个 JavaScript 函数:</p>
<table id=table4 borderColor=#000000 cellPadding=0 width="100%" bgColor=#ebe9ed border=1>
    <tbody>
        <tr>
            <td style="FONT-SIZE: 10pt">
            <pre xml:space="preserve">// form - the form to submit<br>// resultDivId - the division of which to display result text in, in null, then<br>// create an element and add it to the end of the body<br>function ajaxSubmitForm(form, resultDivId) {<br>var elements = form.elements;// Enumeration the form elements<br>var element;<br>var i;<br><br>var postContent = "";// Form contents need to submit<br><br>for(i=0;i&lt;elements.length;++i) {<br>var element=elements[i];<br><br>if(element.type=="text" || element.type=="textarea" || element.type=="hidden") {<br>postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&amp;";<br>}<br>else if(element.type=="select-one"||element.type=="select-multiple") {<br>var options=element.options,j,item;<br>for(j=0;j&lt;options.length;++j){<br>item=options[j];<br>if(item.selected) {<br>postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(item.value) + "&amp;";<br>}<br>}<br>} else if(element.type=="checkbox"||element.type=="radio") {<br>if(element.checked) {<br>postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&amp;";<br>}<br>} else if(element.type=="file") {<br>if(element.value != "") {<br>postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&amp;";<br>}<br>} else {<br>postContent += encodeURIComponent(element.name) + "=" + encodeURIComponent(element.value) + "&amp;";<br>}<br>}<br><br>alert(postContent);<br><br>ajaxSubmit(form.action, form.method, postContent);<br>}<br><br>// url - the url to do submit<br>// method - "get" or "post"<br>// postContent - the string with values to be submited<br>// resultDivId - the division of which to display result text in, in null, then<br>// create an element and add it to the end of the body<br>function ajaxSubmit(url, method, postContent, resultDivId)<br>{<br>var loadingDiv = document.getElementById('loading');<br>// call in new thread to allow ui to update<br>window.setTimeout(function () {<br>loadingDiv.innerText = "Loading....";<br>loadingDiv.style.display = "";<br>}, 1);<br><br>// code for Mozilla, etc.<br>if (window.XMLHttpRequest)<br>{<br>xmlhttp=new XMLHttpRequest();<br>}<br>// code for IE<br>else if (window.ActiveXObject)<br>{<br>xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");<br>}<br><br>if(xmlhttp) {<br>xmlhttp.onreadystatechange = function() {<br>// if xmlhttp shows "loaded"<br>if (xmlhttp.readyState==4)<br>{<br>if(resultDivId) {<br>document.getElementByID(resultDivId).innerHTML = xmlhttp.responseText;<br>} else {<br>var result = document.createElement("DIV");<br>result.style.border="1px solid #363636";<br>result.innerHTML = xmlhttp.responseText;<br>document.body.appendChild(result);<br>}<br><br>loadingDiv.innerHTML =<br>"Submit finnished!";<br>}<br><br>};<br><br>if(method.toLowerCase() == "get") {<br>xmlhttp.open("GET", url + "?" + postContent, true);<br>xmlhttp.send(null);<br>} else if(method.toLowerCase() == "post") {<br>xmlhttp.open("POST", url, true);<br>xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");<br>xmlhttp.send(postContent);<br>}<br>} else {<br>loadingDiv.innerHTML =<br>"Can't create XMLHttpRequest object, please check your web browser.";<br>}<br><br>}</pre>
            </td>
        </tr>
    </tbody>
</table>
<p style="FONT-SIZE: 10pt">函数 ajaxSubmitForm 将表单要提交的内容进行封装, 然后调用 ajaxSubmit 函数来执行真正的异步提交, 表单提交后所返回的结果则显示在给定的 DIV 容器中或者没有指定参数时用 DOM 对象动态生成一个 DIV 容器来显示结果并添加到页面末尾. 这样, 对原来的表单只需要改动一个地方就可以将原来的表单提交改为异步模式, 即在 form 标签里加入: onSubmit="ajaxSubmitForm(this);return false;" 即可, return false 确保表单不会被浏览器同步提交. 完整的例子请看<a href="http://www.myjavaserver.com/%7Ebeansoft/ajax/ajax_form_submit.htm">这里</a>.</p>
<br>
<p style="FONT-SIZE: 10pt">----------------- 引用结束 -----------------</p>
<p style="FONT-SIZE: 10pt">OK, 希望至此为止您已经理解了如何用 AJAX 来正确的执行 GET/POST. 如果这个问题您解决了, 可是说后台的乱码问题就和你直接通过表单提交几乎没有区别了. 这个方法的具体封装已经在附件的 ajax_common.js 中了.</p>
<p style="FONT-SIZE: 10pt">至此也该贴出来我们的 GBK 编码的客户端页面的内容了:</p>
<br>
<div style="FONT-SIZE: 10pt">
<p style="FONT-SIZE: 10pt">&lt;html&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;head&gt;<br>&lt;meta http-equiv="Content-Type" content="text/html; charset=gbk"&gt;<br>&lt;title&gt;AJAX Form Submit Test&lt;/title&gt;<br>&lt;script src='ajax_common.js'&gt;&lt;/script&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;/head&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;body&gt;<br>本页面的编码是中文.&lt;br/&gt;<br>&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=gbk"&amp;gt;&lt;br/&gt;<br>&lt;b&gt;测试过的服务器:&lt;/b&gt;&lt;br/&gt;<br>Resin 3.0.18&lt;br/&gt;<br>Tomcat 5.5.20&lt;br/&gt;<br>Tomcat 5.0.30&lt;br/&gt;<br>&lt;h3&gt;AJAX Form Submit Test&lt;/h3&gt;<br>Fill the form and then click submit&lt;br&gt;<br>提交方式: POST&lt;br&gt;<br>&lt;form method="POST" id="form1" name="form1"<br>action="form_action.jsp"<br>onSubmit="former.ajaxSubmitForm();return false;"&gt;<br>&lt;p&gt;&lt;input type="hidden" name="hidden1" value="hiddenValue"&gt;<br>text:&lt;input type="text" name="textf&amp;1" size="20" value="text文本&amp;amp;1"&gt;<br>checkbox:&lt;input type="checkbox" name="checkbox1" value="ON" checked&gt;<br>radio:&lt;input type="radio" value="V1" checked name="radio1"&gt;<br>select:&lt;select size="1" name="select1"&gt;<br>&lt;option selected value="option1"&gt;D1&lt;/option&gt;<br>&lt;/select&gt;<br>&lt;br&gt;<br>&lt;br&gt;<br>&lt;input type="submit" name="B1" value="submit"&gt;<br>&lt;input type="reset" name="B2" value="reset"&gt;<br>&lt;/p&gt;<br>&lt;/form&gt;</p>
<p style="FONT-SIZE: 10pt">提交方式: GET&lt;br&gt;<br>&lt;form method="GET" id="form2" name="form2"<br>action="form_action.jsp"<br>onSubmit="former2.ajaxSubmitForm();return false;"&gt;<br>&lt;p&gt;&lt;input type="hidden" name="hidden1" value="hiddenValue"&gt;<br>text:&lt;input type="text" name="text文本&amp;amp;2" size="20" value="text文本&amp;amp;2"&gt;<br>checkbox:&lt;input type="checkbox" name="checkbox1" value="ON" checked&gt;<br>radio:&lt;input type="radio" value="V1" checked name="radio1"&gt;<br>select:&lt;select size="1" name="select1"&gt;<br>&lt;option selected value="option1"&gt;D1&lt;/option&gt;<br>&lt;/select&gt;<br>&lt;br&gt;<br>&lt;br&gt;<br>&lt;input type="submit" name="B1" value="submit"&gt;<br>&lt;input type="reset" name="B2" value="reset"&gt;<br>&lt;/p&gt;<br>&lt;/form&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;div id="loading" style="display:none; position:absolute;<br>border:1px solid orange; height:20px; width:600; left: 93px; top: 112px;<br>background-color: #FFFFCC; cursor:pointer;" title="Click to hide" onClick="this.style.display='none';"&gt;&lt;/div&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;div id="resultDiv" style="border:1px solid orange; background-color: #FFFFCC; cursor:pointer;" title="Click to hide" onClick="this.style.display='none';"&gt;<br>Form 1 的提交结果将会显示在这里.<br>&lt;/div&gt;</p>
<p style="FONT-SIZE: 10pt"><br>&lt;script type="text/javascript"&gt;<br>var former = new AjaxFormer($('form1'), 'resultDiv');<br>var former2 = new AjaxFormer($('form2'));<br>&lt;/script&gt;<br>&lt;/body&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;/html&gt;</p>
</div>
可以看到我们的确使用的是 GBK 编码, 浏览器打开的时候自动选择的编码也是简体中文.<br>
<p style="FONT-SIZE: 10pt">那么第二个关键点就是服务器端的表单数据读取了.这个问题跟具体的服务器有很大关系. 对于 Resin 服务器来说, 问题很少, 基本上不论是 POST 和 GET, 出乱码的概率都比较小. 但是 Tomcat 就不敢恭维了, 这大概也是开源产品和商业产品的区别, 缺乏前后一致性和兼容性, 因为开源的不需要提供技术支持. Tomcat 的 GET/POST 的编码处理方式不同的版本都不一样, 就像 Eclipse/Netbeans 新版本从来不需要兼容老版本的插件 API 一样, Hibernate/Struts/Spring 也是一样, 所以学 Java 的很累. 当然, 这就是免费/开源的代价. 跑题了. 因此我们的服务器端代码大部分都是对 Tomcat 的乱码问题的解决(POST的没有问题, 主要是 GET 方法的).<br></p>
<div style="FONT-SIZE: 10pt">
<p style="FONT-SIZE: 10pt">&lt;%@ page contentType="text/html; charset=gbk" pageEncoding="gbk"%&gt;<br>&lt;html&gt;<br>&lt;%<br>//Send some headers to keep the user's browser from caching the response.<br>response.addHeader("Expires", "Mon, 26 Jul 1997 05:00:00 GMT" );<br>response.addHeader("Last-Modified", new java.util.Date().toGMTString());<br>response.addHeader("Cache-Control", "no-cache, must-revalidate" );<br>response.addHeader("Pragma", "no-cache" );<br>// This will emulate a network delay, for 2 sec.<br>//Thread.currentThread().sleep(2000);</p>
<p style="FONT-SIZE: 10pt">request.setCharacterEncoding("utf-8");<br>%&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;%!</p>
<p style="FONT-SIZE: 10pt">/**<br>* 转换字符串的内码.<br>*<br>* @param input<br>* 输入的字符串<br>* @param sourceEncoding<br>* 源字符集名称<br>* @param targetEncoding<br>* 目标字符集名称<br>* @return 转换结果, 如果有错误发生, 则返回原来的值<br>*/<br>public static String changeEncoding(String input, String sourceEncoding,<br>String targetEncoding) {<br>if (input == null || input.equals("")) {<br>return input;<br>}</p>
<p style="FONT-SIZE: 10pt">try {<br>byte[] bytes = input.getBytes(sourceEncoding);<br>return new String(bytes, targetEncoding);<br>} catch (Exception ex) {<br>}<br>return input;<br>}</p>
<p style="FONT-SIZE: 10pt">/**<br>* 一个类似于 JavaScript 的 escape 函数的功能, 确保乱码可以正确传输.<br>*/<br>public static String escape(String src) {<br>int i;<br>char j;<br>StringBuffer tmp = new StringBuffer();<br>tmp.ensureCapacity(src.length() * 6);<br>for (i = 0; i &lt; src.length(); i++) {<br>j = src.charAt(i);<br>if (Character.isDigit(j) || Character.isLowerCase(j)<br>|| Character.isUpperCase(j))<br>tmp.append(j);<br>else if (j &lt; 256) {<br>tmp.append("%");<br>if (j &lt; 16)<br>tmp.append("0");<br>tmp.append(Integer.toString(j, 16));<br>} else {<br>tmp.append("%u");<br>tmp.append(Integer.toString(j, 16));<br>}<br>}<br>return tmp.toString();<br>}<br>%&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;head&gt;<br>&lt;title&gt;Test form action page&lt;/title&gt;<br>&lt;/head&gt;<br>&lt;body&gt;<br>这是 GBK 编码版本的后台表单提交页面.&lt;br/&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;%<br>boolean isTomcat = application.getServerInfo().toLowerCase().indexOf("tomcat") != -1;<br>%&gt;</p>
<p style="FONT-SIZE: 10pt">Form submit method:&lt;%=request.getMethod()%&gt;&lt;br/&gt;<br>The form content u send is:&lt;br/&gt;<br>&lt;%<br>java.util.Enumeration e = request.getParameterNames();</p>
<p style="FONT-SIZE: 10pt">while (e.hasMoreElements()) {<br>String name = (String)e.nextElement();<br>String value = request.getParameter(name);</p>
<p style="FONT-SIZE: 10pt">if(isTomcat &amp;&amp; request.getMethod().equalsIgnoreCase("GET")) {<br>name = changeEncoding(name, "ISO8859-1", "UTF-8");<br>value = changeEncoding(value, "ISO8859-1", "UTF-8");<br>}<br>out.println("&lt;b&gt;" + name + "&lt;/b&gt; = " + value + "&lt;br/&gt;");<br>}</p>
<p style="FONT-SIZE: 10pt">// 给前台返回一个可以执行的脚本<br>//response.addHeader("response_script", changeEncoding("alert('提交完成');", "ISO8859-1", "UTF-8"));<br>response.addHeader("response_script", escape("alert('提交完成');"));<br>%&gt;</p>
<p style="FONT-SIZE: 10pt">&lt;/body&gt;<br>&lt;/html&gt;</p>
</div>
<p style="FONT-SIZE: 10pt">booleanisTomcat=application.getServerInfo().toLowerCase().indexOf("tomcat") !=-1; 这一句主要针对 Tomcat 进行处理, 如果是 GET 方法的话, 就需要将表单参数从 ISO8859-1 转换到 UTF-8 (注意不是 GBK, 貌似 Tomcat 很喜欢 UTF-8?). 其它的地方和原来的 UTF-8 版本的没有区别. 当然如果您的站点应该用过滤器来更方便的解决这个问题.<br></p>
<p style="FONT-SIZE: 10pt">小结:<br><br>1. 使用一致的字符集很重要, 要么全是 GBK, 要么全是 UTF-8, 如果有条件, 就全部用 UTF-8, 那样工作量是最小的;<br><br>2. 用 AJAX 提交的时候一定要按照 HTTP 的规范来, 做到和浏览器尽量兼容, 尤其是 POST 的时候不要再往 URL 地址里加参数了, 你那样是违规! 后果就是有的服务器会不搭理你传递的这些参数! 还是如我所讲, 参数提交之前要用 encodeURIComponent() 来转化, 这也是为了符合浏览器的习惯做法.<br><br>3. 后台如果读取参数有乱码, 就尽量多在 ISO8859-1, GBK, UTF-8 中间多转换几次试试, 可以试试偶写的那个 changeEncoding() 方法, 把几个转换后的表单值都列出来, 一定有一个是正确的, 总是可以解决问题的. 这个本来不应该是偶们的任务, 但是写服务器的人是老美, 尤其是 Tomcat 作者, 只熟悉 ISO8859-1.<br><br>4. 鉴于 TOMCAT 读取 POST 参数的时候很少出问题, 因此建议AJAX提交表单的时候多用 POST 方法, 尽量不用 GET.<br><br>运行截屏:</p>
<p style="FONT-SIZE: 10pt"><img alt=http://www.blogjava.net/images/blogjava_net/beansoft/18680/o_AJAX%20Form%20Submit%20GBK.png src="http://www.blogjava.net/images/blogjava_net/beansoft/18680/o_AJAX%20Form%20Submit%20GBK.png"></p>
<p style="FONT-SIZE: 10pt">其它的一些资料可以参考Blogjava上的一篇原创文章: <a href="http://www.blogjava.net/errorfun/archive/2006/12/09/86584.html">[原创]struts,ajax乱码解决方案</a><br></p>
<p style="FONT-SIZE: 10pt">欢迎发表建议和更好的观点. 谢谢! 重申本文无意代替您的 AJAX 框架, 不过在你抓狂的时候可以考虑看看他们表单提交的代码, 改改它!<br><br>本人翻译的 XMLHttpRequest 对象介绍:</p>
<h2>The XMLHttpRequest Object Reference XMLHttpRequest 对象参考</h2>
<h3>Methods 方法</h3>
<table borderColor=#000000 cellPadding=0 width="100%" border=1>
    <tbody>
        <tr vAlign=top>
            <th align=left width="45%">Method 方法</th>
            <th align=left width="55%">Description 描述</th>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">abort()</td>
            <td style="FONT-SIZE: 10pt">Cancels the current request<br>取消当前请求</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">getAllResponseHeaders()</td>
            <td style="FONT-SIZE: 10pt">Returns the complete set of http headers as a string<br>将完整的 HTTP 头部做为一个字符串返回</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">getResponseHeader("headername")</td>
            <td style="FONT-SIZE: 10pt">Returns the value of the specified http header<br>返回给定的 HTTP 头的值</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">open("method","URL",async,"uname","pswd")</td>
            <td style="FONT-SIZE: 10pt">Specifies the method, URL, and other optional attributes of a request
            <p style="FONT-SIZE: 10pt">The method parameter can have a value of "GET", "POST", or "PUT" (use "GET" when requesting data and use "POST" when sending data (especially if the length of the data is greater than 512 bytes.</p>
            <p style="FONT-SIZE: 10pt">The URL parameter may be either a relative or complete URL.</p>
            <p style="FONT-SIZE: 10pt">The async parameter specifies whether the request should be handled asynchronously or not. true means that script processing carries on after the send() method, without waiting for a response. false means that the script waits for a response before continuing script processing<br>指定表单提交方法, URL, 以及请求的可选属性<br><br>method 参数可以是"GET", "POST" 或者 "PUT" 这些值中之一(使用"GET"来请求数据, 特别的, 当发送的数据长度大于512字节时使用 "POST").<br><br>URL 参数可以为相对的和完整的 URL.<br><br>async 参数指定请求是否为异步方式处理. true 意味着调用 send() 方法后脚本继续向下执行, 不需要等待响应. false 意味着脚本将等待响应之后才能继续执行</p>
            </td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">send(content)</td>
            <td style="FONT-SIZE: 10pt">Sends the request<br>发送请求</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">setRequestHeader("label","value")</td>
            <td style="FONT-SIZE: 10pt">Adds a label/value pair to the http header to be sent<br>在要发送的 HTTP 头中添加 标签/取值</td>
        </tr>
    </tbody>
</table>
<h3>Properties 属性</h3>
<table borderColor=#000000 cellPadding=0 width="100%" border=1>
    <tbody>
        <tr vAlign=top>
            <th align=left width="30%">Property 属性</th>
            <th align=left width="70%">Description 描述</th>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">onreadystatechange</td>
            <td style="FONT-SIZE: 10pt">An event handler for an event that fires at every state change<br>每次状态改变时除非的事件处理器</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">readyState</td>
            <td style="FONT-SIZE: 10pt">Returns the state of the object:
            <p style="FONT-SIZE: 10pt">0 = uninitialized<br>1 = loading<br>2 = loaded<br>3 = interactive<br>4 = complete<br>返回对象的状态<br><br>0 = 未初始化<br>1 = 载入中<br>2 = 已载入<br>3 = 交互<br>4 = 完成</p>
            </td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">responseText</td>
            <td style="FONT-SIZE: 10pt">Returns the response as a string<br>将响应做为字符串返回</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">responseXML</td>
            <td style="FONT-SIZE: 10pt">Returns the response as XML. This property returns an XML document object, which can be examined and parsed using W3C DOM node tree methods and properties<br>将响应做为XML返回. 这个属性返回一个 XML 文档对象, 可以用 W3C 的 DOM 节点树方法和属性进行检索分析</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">status</td>
            <td style="FONT-SIZE: 10pt">Returns the status as a number (e.g. 404 for "Not Found" or 200 for "OK")<br>将状态做为数字返回(例如 404 为"Not Found" 或者 200 为 "OK")</td>
        </tr>
        <tr vAlign=top>
            <td style="FONT-SIZE: 10pt">statusText</td>
            <td style="FONT-SIZE: 10pt">Returns the status as a string (e.g. "Not Found" or "OK")<br>将状态做为字符串返回(例如 "Not Found" 或者 "OK")</td>
        </tr>
    </tbody>
</table>
　<br>
<div style="FONT-SIZE: 10pt">posted on 2006-12-31 14:37 <a href="http://www.blogjava.net/beansoft/">BeanSoft</a> 阅读(2650) <a href="http://www.blogjava.net/beansoft/archive/2006/12/31/91144.aspx#Post">评论(6)</a> &nbsp;<a href="http://www.blogjava.net/beansoft/admin/EditPosts.aspx?postid=91144">编辑</a>&nbsp;<a href="http://www.blogjava.net/beansoft/AddToFavorite.aspx?id=91144">收藏</a> <a href="http://www.blogjava.net/beansoft/services/trackbacks/91144.aspx">引用</a> 所属分类: <a href="http://www.blogjava.net/beansoft/category/17587.html">Web</a> </div>
<img src ="http://www.blogjava.net/43880800/aggbug/132313.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-07-25 15:01 <a href="http://www.blogjava.net/43880800/archive/2007/07/25/132313.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HW,HW</title><link>http://www.blogjava.net/43880800/archive/2007/07/03/127951.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Tue, 03 Jul 2007 13:23:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/07/03/127951.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/127951.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/07/03/127951.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/127951.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/127951.html</trackback:ping><description><![CDATA[<p><font style="FONT-SIZE: 18pt; COLOR: red; BACKGROUND-COLOR: #d8d0c8">"板凳要坐十年冷"</font></p>
<img src ="http://www.blogjava.net/43880800/aggbug/127951.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-07-03 21:23 <a href="http://www.blogjava.net/43880800/archive/2007/07/03/127951.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Tomcat JSP调用JBoss布署的EJB远程方法</title><link>http://www.blogjava.net/43880800/archive/2007/02/09/99040.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Fri, 09 Feb 2007 08:48:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/02/09/99040.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/99040.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/02/09/99040.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/99040.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/99040.html</trackback:ping><description><![CDATA[
		<div align="center">
				<strong>Tomcat JSP调用JBoss布署的EJB远程方法</strong>
		</div>
		<div> </div>
		<div align="center">王伟东</div>
		<div align="center"> </div>
		<div>   EJB技术的基础是另外两种技术：RMI-IIOP和JNDI。要想了解EJB，一定要先了解RMI-IIOP和JNDI。</div>
		<div>
				<br />
				<strong>Java RMI-IIOP</strong>
				<br />
				<br />    Java RMI-IIOP（Java Remote Method Invocation over the Internet Inter-ORB Protocol）是J2EE的网络机制。Java RMI-IIOP允许你编写分布式对象，使得对象的通信范围能够在内存中，跨Java虚拟机，跨物理设备。<br /></div>
		<div>
				<strong>Java命名和目录接口（Java Naming and Directory Interface，JNDI）<br /></strong>
				<br />    JNDI是Java Naming and Directory Interface 的简写，中意为：Java命名及目录接口，它是为了对高级网络应用开发中的使用的目录基础结构的访问。实际上这个目录是一个特殊的数据库，提供了对存储数据的快速访问，不象传统的目录服务访问方式-你必须提供不同的API接口去访问不同的目录服务（如：LDAP，NIS，ADS等），而它提供了一种标准的API来访问类型不同的目录。据说，使用完整的SDK可以开发那些JNDI还不支持的目录服务提供者。<br /><br />    JNDI是J2EE的一个API，提供了一套标准的接口，以定位用户、机器、网络、对象、以及服务。例如，你可以使用JNDI来定位内部网中的一台打印机，你也可以使用它来定位Java对象或连接到一个数据库。JNDI可以用于EJB、RMI-IIOP、JDBC中。它是网络查找定位的标准方法。    JNDI API被用来访问命名和目录服务。它提供一个相容的模式来访问和操作企业范围大的资源，例如一个应用服务器中的DNS、LDAP、本地文件系统或者对象。</div>
		<div> </div>
		<div>有了上述两种技术的支持就可以实施分布式布署了。</div>
		<div> </div>
		<div>比如你有两个服务器：</div>
		<div>A服务器192.168.0.1：JBOSS 4.0其上布署了EJB的业务实现模块</div>
		<div>B服务器192.168.0.2：Tomcat 5.0 运行Jsp/JavaBean或Struts等Web页面程序</div>
		<div>实验目的：分布式不同应用服务器访问EJB组件</div>
		<div> </div>
		<div> </div>
		<div>A服务器上对EJB的开发及布署，请参见其它相关文档：</div>
		<div> </div>
		<div>a. HelloWorldBean.java //业务实现了getHelloWorld提供remote的方法</div>
		<div> </div>
		<div>
				<blockquote>
						<div>package donne.study;</div>
						<div>public abstract class HelloWorldBean implements javax.ejb.SessionBean {</div>
						<div>    /**<br />     * @ejb.interface-method view-type="remote"<br />     */<br />    public String getHelloWorld(String sMessage) {</div>
						<div>        return "Hello World! "+sMessage;<br />    }</div>
						<div>}<br /></div>
				</blockquote>
		</div>
		<div> </div>
		<div>EJB Classes 由lomboz自动生成的EJB接口文件</div>
		<div>b. HelloWorld.java</div>
		<div>
				<blockquote>
						<div>package donne.study;</div>
						<div>/**<br /> * Remote interface for HelloWorld.<br /> * @generated <br /> * @lomboz generated<br /> */<br />public interface HelloWorld<br />   extends javax.ejb.EJBObject<br />{</div>
						<div>   public java.lang.String getHelloWorld( java.lang.String sMessage )<br />      throws java.rmi.RemoteException;</div>
						<div>}<br /></div>
				</blockquote>
		</div>
		<div> </div>
		<div>c. HelloWorldHome.java</div>
		<div> </div>
		<div>
				<blockquote>
						<div>package donne.study;</div>
						<div>/**<br /> * Home interface for HelloWorld.<br /> * @generated <br /> * @lomboz generated<br /> */<br />public interface HelloWorldHome<br />   extends javax.ejb.EJBHome<br />{<br />   public static final String COMP_NAME="java:comp/env/ejb/HelloWorld";<br />   public static final String JNDI_NAME="HelloWorld";</div>
						<div>   public donne.study.HelloWorld create()<br />      throws javax.ejb.CreateException,java.rmi.RemoteException;</div>
						<div>}</div>
				</blockquote>
		</div>
		<div>其它文件略</div>
		<div> </div>
		<div>B服务器上Tocamt上调用JBoss下EJB的remote接口</div>
		<div>1. Copy Jboss下的client目录下的jar文件到你的测试工程的lib目录，有些jar是不需要的根据实际情况</div>
		<div> </div>
		<div>2. 将上述两个接口b、c文件生成的class文件打包成jar文件，也copy到lib下，可以看到到不管你的EJB里业务内容如何变化这个接口的定义都不会变</div>
		<div> </div>
		<div>3. HelloWorldClient.java</div>
		<div> </div>
		<div>
				<blockquote>
						<div>package donne.study;</div>
						<div>import java.util.Hashtable;</div>
						<div>import javax.naming.InitialContext;<br />import javax.naming.NamingException;</div>
						<div> </div>
						<div>public class HelloWorldClient {</div>
						<div>    private donne.study.HelloWorldHome getHome() throws NamingException {<br />        return (donne.study.HelloWorldHome) getContext().lookup(<br />                donne.study.HelloWorldHome.JNDI_NAME);<br />    }</div>
						<div>    private InitialContext getContext() throws NamingException {<br />        Hashtable props = new Hashtable();</div>
						<div>        props.put(InitialContext.INITIAL_CONTEXT_FACTORY,<br />                "org.jnp.interfaces.NamingContextFactory");<br />        props.put(InitialContext.PROVIDER_URL, "jnp://192.168.0.1:1099");<br />        InitialContext initialContext = new InitialContext(props);<br />        return initialContext;<br />    }</div>
						<div> </div>
						<div>    public String getEJBString() {<br />        try {<br />            donne.study.HelloWorld myBean = getHome().create();<br />            return myBean.getHelloWorld("From Tomcat Jsp");<br />        } catch (Exception e) {<br />            return e.getMessage(); <br />            <br />        }<br />    }<br />}<br /></div>
				</blockquote>
		</div>
		<div> </div>
		<div>4. hello.jsp</div>
		<div> </div>
		<div>
				<blockquote>
						<div>&lt;%@ page contentType="text/html; charset=GBK"%&gt;<br />&lt;%@ page import = "donne.study.HelloWorldClient" %&gt;<br />&lt;HTML&gt;<br />&lt;BODY&gt;<br />&lt;%<br /> HelloWorldClient helloID=new HelloWorldClient();<br /> out.print(helloID.getEJBString());<br />%&gt;</div>
						<div>&lt;/BODY&gt;<br />&lt;/HTML&gt;</div>
				</blockquote>
		</div>
		<div> </div>
		<div>运行一下hello.jsp将出现Hello World! From Tomcat Jsp就对了</div>
<img src ="http://www.blogjava.net/43880800/aggbug/99040.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-02-09 16:48 <a href="http://www.blogjava.net/43880800/archive/2007/02/09/99040.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring vs EJB</title><link>http://www.blogjava.net/43880800/archive/2007/02/09/99039.html</link><dc:creator>Tom</dc:creator><author>Tom</author><pubDate>Fri, 09 Feb 2007 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/43880800/archive/2007/02/09/99039.html</guid><wfw:comment>http://www.blogjava.net/43880800/comments/99039.html</wfw:comment><comments>http://www.blogjava.net/43880800/archive/2007/02/09/99039.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/43880800/comments/commentRss/99039.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/43880800/services/trackbacks/99039.html</trackback:ping><description><![CDATA[
		<p> </p>
		<p>几天前，在Don Box的博客上，我设法回答一个问题"Spring比EJB简单吗？".现在,这个问题像是有些多余了，因为Spring和EJB的目标并不完全一致，但也许从EJB和Spring两者所共有之处来回答，是可以的。Ted Neward在他的博客上对我的回复进行了评论,我现在去回应一下他的观点。</p>
		<p>　　Ted评论:Spring是一个比EJB简单多了的框架，因为Spring更多是用基于POJO(PlainObject Old Object)的方案，但对于"一些情况"下，它并不简单,而是更复杂。</p>
		<p>　　Rod:好的,在"一些情况"下,地球是扁平的对吧。在我的经验中，如果实现业务逻辑所需要的java Object超过3个的时候，认为用POJO(通常有一个接口)方案更复杂的人很少：给我印象深刻的是，那些否定POJO方案的那些人，真正尝试两种方案并做出对比的人为零。可能他们有自己的观点，但我并不知道。(也许直接的事务和远程方法更另人愉悦？)我真的非常希望看到能真正证明基于POJO的方案更复杂更难用的评论。</p>
		<p>　　Rod:为什么Spring比EJB简单易用?我不能给你一个独立的主观臆断，我可以告诉你的是，我是借鉴EJB，并运用我多年的经验来设计Spring的，我也很乐于去比较.从一开始，Spring(或者其他的IOC加Services框架)框架就是和你的业务代码隔离的，没有藕合的.这个区别是很有重大意义的。任何Object可以被事务化而不需要陷入EJB的丛林中。这对于代码的重用也是有意义的。实际上，在你自己的业务对象中，很少有框架的侵入，换句话说，你会有更多的自由去运用面向对象的分析设计。</p>
		<p>　　Ted:哦，我已经说过了，企业级系统通常不是来练习OO(面向对象),因为那么做有一种让我们陷入麻烦的危险趋势----这也就是为什么人们在网络计算的趋势下，使用CORBA,DCOM和RMI来解决问题的原因。你应该考虑一下，把collection置于服务器端，iterator放在客户端的意义，然后你就明白.....</p>
		<p>　　Rod:Ted,我提到的"更多自由去使用OO",并不是说所有地方都用OO,当然，分布式对象是很需要的。但重要的是，不要把"企业应用"和"分布式应用"混为一谈. 应用程序的内部结构应该尽可能的面向对象.然后提供一个高层的接口对远程调用暴露，理想状态下，仅仅这个接口才可以放弃面向对象.(基本上像SDO--服务数据对象Service Data Objects这样的解决方案在这部分是很庞大的).所以在分布式对象建模中，在应用内部引入优秀的应用程序接口(虽然破坏OO)是没有争议的。Spring和其他的IOC(inverse of control控制反转)容器，不会在OO方面设置障碍,而EJB就没做到，它大范围内地依赖了EJB的接口和框架。</p>
		<p>　　在我对于Spring的XML配置要比EJB复杂的部署描述文件简单易配置的评论后----Ted写到:公正地说,Rod--JSR 175 在简化部署描述配置(包括你的Spring的XML配置)方面的所做的工作是有意义的(而不是所有),在java5之前，部署描述文件是一个必须的，很恼人的事情吗？不幸的是，事实表明，考虑到所有的可能性，这已经是最佳的解决方案了。(所有人都记得EJB1.0时，基于对象的描述符)。</p>
		<p>　　Rod:没错,JSR-175会在DD(Data Define数据定义)方面进一步改善(已经有所改善，虽然注释被一再过度使用,不过那是另一个话题了).不错，DDs(数据定义文件)是必要的，虽然很繁琐，这是java借用C#中属性集/注释的想法而来的.但问题是,现在的EJB部署描述让人惊骇地冗长，差不多全在XML里.而且一个标准的ejb-jar.xml部署描述文件并不够，通常需要两个。相反，Spring的配置文件短小精悍，而且不需要额外的引用。当然，EJB3.0不在这里讨论，因为我想评论的是现在使用EJB的方案(直到2006或者JSR-220完成的时候)。</p>
		<p>　    在Don的博客上，我对他拿Spring进行的测试表达了我的尊敬: </p>
		<p>   　 Rod:因为你的代码不是严重依赖于容器的，所以可以方便的进行单元测试，比如用JUnit。这样一来，和过去传统的J2EE容器内测试方案比起来，提高了巨大的效率。你也可以在Spring容器上做集成测试，而不需要一个重量级的J2EE应用服务器----不像其他应用服务器，Spring容器可以很快启动。</p>
		<p>　　Don:我仅仅是说尽量少的依赖于容器，EJB并不是一个完全失败的技术，用OpenEJB容器效率并不会很低的，至少从我的测试来证明。</p>
		<p>　　Rod:我并不确定像OpenEJB这种轻量级的EJB容器会是一个另人满意的解决方案.我没有遇到有人用过它，我自己也没用过。真正的EJB测试总是繁杂的，通常需要五分钟一个编码/测试循环。</p>
		<p>　　Rod:比较一下Spring的Pet Store例子和EJB方案的，就可以发现,在Spring的例子中，很少有冗余的代码，也就是说什么都不做的代码...</p>
		<p>　　比如Service接口,JNDI服务查询操作等等.在我接触的项目中,用一个Spring+Hibernate的混合框架，至少能拿去EJB方案的10%---20%的代码,对于项目的提交和后期维护是有重大意义的.</p>
		<p>　　Don:我来说说我的观点,简单并不永远是好的，不幸的是，它仅仅代表简单，没有JNDI，就等于说牺牲了管理人员在不重启服务器的情况下，对配置进行调整的需要。这可能对于一些客户的应用来说不是太重要，但对于一个24*7的应用来讲就是个大问题了。</p>
		<p>　　Rod:当然，我说的用Spring终结你代码中的"服务接口，JNDI查找",并不是说真的不用JNDI,比如说，你还是希望调用EJB,Spring可以给你创建一个代理，封装了JNDI查找啊。</p>
		<p>　　在Pet Store的例子中，我尽力寻求一个简单的架构--既然我们来讨论Pet Store,关键的就是，Spring和其他轻量级的框架技术，给了你一个简易框架的选择。如果是传统的J2EE,你想创建一个Pet Store,你最好是用Perl或者.Net,或者抛弃J2EE的高级特性，只选择Servlet和JSP,所以有一个你自己的简易架构是必要的。</p>
		<p>　　没有JNDI，就等于说牺牲了管理人员在不重启服务器的情况下，对配置进行调整的需要",嗯，有多少需要用JNDI重新配置应用的需要?更好的解决方案是JMX,但应用服务器并不了解你想做什么有意义的配置，同时Spring 1.2已经加入了对JMX的支持,这将方便开发者去操作应用对象和配置。比如说，改变一个JNDI的环境变量是我们很少要做的事情.开发者通常会很准确地配置这些信息，来避免修改的痛苦。(我同意，这可能是个不好的假设，但确实通常是这样的)，你如果想通过JNDI来改变某个值，你已经知道何时来找到它,等等。</p>
		<p>　　Don:请记住，EJB提供双机事务的支持，而Spring没有，这一点让我不安，Spring失去了它的亮点。</p>
		<p>　　Rod:Spring不会做或者很少做双机事务,不知道怎么就确定Spring失去它的亮点了,Spring的事务层抽象是在事物策略的基础上的一层，一个方案就是JTA,在这种方案下，双机事务来自于应用服务器底层的支持，而不是Spring.实际上,JTA事物策略是我们最早就重视并实现的功能。我明白，在一个无JTA支持的简单容器下，丢弃一个落后的local和global事务编程模型是很有意义的.</p>
<img src ="http://www.blogjava.net/43880800/aggbug/99039.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/43880800/" target="_blank">Tom</a> 2007-02-09 16:46 <a href="http://www.blogjava.net/43880800/archive/2007/02/09/99039.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>