﻿<?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-　　　　　　　　　　　　　彬 ^_^ -随笔分类-Jakarta</title><link>http://www.blogjava.net/libin2722/category/29422.html</link><description>快乐学习，快乐工作</description><language>zh-cn</language><lastBuildDate>Wed, 13 Feb 2008 17:52:16 GMT</lastBuildDate><pubDate>Wed, 13 Feb 2008 17:52:16 GMT</pubDate><ttl>60</ttl><item><title>整理一个ANT在J2EE项目中的应用</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179856.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:59:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179856.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179856.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179856.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179856.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179856.html</trackback:ping><description><![CDATA[<p><span style="font-size: 12pt; color: #000080;">首先，假设我们的项目的结构如下 ${project.root}<br />
&nbsp; |<br />
&nbsp; +-- build/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- WAR/EAR档的目录<br />
&nbsp; +-- classes/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- 编译的输出目录，与JBuilder兼容<br />
&nbsp; +-- src/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- Java源文件目录<br />
&nbsp; +-- web/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- WEB Content 目录<br />
&nbsp; |&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; +--pages/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- JSP 文件目录<br />
&nbsp; |&nbsp;&nbsp;&nbsp; +--WEB-INF/&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- web.xml 等配置文件<br />
&nbsp; +-- ejb&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- EJB Content 目录<br />
&nbsp; |&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; +---INF/&nbsp;&nbsp;&nbsp; &lt;-- EJB 配置文件<br />
&nbsp; +-- ear&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- EAR Content 目录<br />
&nbsp; |&nbsp;&nbsp;&nbsp; |<br />
&nbsp; |&nbsp;&nbsp;&nbsp; +---INF/&nbsp;&nbsp;&nbsp; &lt;-- EAR 配置文件<br />
&nbsp; |-- lib&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;-- 项目所要用到的library </span></p>
<p><span style="font-size: 12pt; color: #000080;">接下来第一步，就是要先定义好一些全局的参数，以便以后更改起来方便，风格<br />
大家自己选择好了，我用的是如下的方式：</span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(1) 给出项目的目录：<br />
&nbsp;
&lt;!--// project directories //--&gt;&lt;property name="dir.project"
="D:/Code/MyProject"/&gt;&lt;property name="dir.project.lib"
="${dir.project}/lib"/&gt;&lt;property name="dir.project.src"
="${dir.project}/src"/&gt;&lt;property name="dir.project.web_module"
="${dir.project}/web"/&gt;&lt;property name="dir.project.ejb_module"
="${dir.project}/ejb"/&gt;&lt;property name="dir.project.ear_module"
="${dir.project}/ear"/&gt;&lt;!--// compile, build and deploy
directories //--&gt;&lt;property name="dir.project.compile"
="${dir.project}/classes"/&gt;&lt;property
name="dir.project.compile.jspcache"
="${dir.project.compile}/jspcache"/&gt;&lt;property
name="dir.project.build" ="${dir.project}/build"/&gt;&lt;!--// J2EE
Container //--&gt;&lt;property name="dir.appserver.tomcat.home"
="D:/J2EE_HOME/AppServer/Tomcat"/&gt;&lt;property
name="dir.appserver.oc4j.j2ee.home"
="D:/J2EE_HOME/AppServer/OC4J/j2ee/home"/&gt;<br />
&nbsp;</span></span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(2) 定义Java Source的编译选项<br />
&lt;!--//
Java compiler options //--&gt; &lt;property name="opt.compile.source"
="1.4"/&gt;&lt;property name="opt.compile.target"
="1.4"/&gt;&lt;property name="opt.compile.encoding"
="UTF-8"/&gt;&lt;property name="opt.compile.deprecation"
="on"/&gt;&lt;property name="opt.compile.debug" ="on"/&gt;&lt;property
name="opt.compile.optimize" ="off"/&gt;<br />
&nbsp;</span></span></p>
<p><span style="font-size: 12pt; color: #000080;">(3) 如果需要 import EJB library 的话，给出下面的定义，后面会用到<br />
&nbsp;&nbsp;&nbsp; &lt;!--// EJB imported resource //--&gt;&lt;property name="import.ejb.report.server" ="${dir.project.lib}/Appwork.jar"/&gt;<br />
&nbsp;</span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(4) 给出部署WAR/EAR文件的名称：<br />
&nbsp;
&lt;!--// Deployment //--&gt;&lt;property name="deploy.file.ejb_module"
="MyApp_EJB.jar" /&gt;&lt;property name="deploy.file.web_module"
="MyApp_WEB.war" /&gt;&lt;property name="deploy.file.ear_module"
="MyApp.ear" /&gt;<br />
&nbsp;</span></span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(5) 给出CLASSPATH的定义，引入相关的Library和项目编译生成的Java Classes<br />
&nbsp;
&lt;path id="CLASSPATH"&gt;&lt;!--// Tomcat Libraries
//--&gt;&lt;fileset dir="${dir.appserver.tomcat.home}/bin"&gt;
&lt;include name="*.jar"/&gt;&lt;/fileset&gt; &lt;fileset
dir="${dir.appserver.tomcat.home}/server/lib"&gt; &lt;include
name="*.jar"/&gt; &lt;/fileset&gt; &lt;fileset
dir="${dir.appserver.tomcat.home}/common/lib"&gt; &lt;include
name="*.jar"/&gt; &lt;/fileset&gt; &lt;!--// Depended Libraries
//--&gt;&lt;pathelement
location="${dir.project.lib}/abc.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/AppServer.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/AppServiceClient.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/AppUtil.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/xport.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/jaxen-full.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/jstl.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/log4j-1.2.13.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/ojdbc14.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/saxpath.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/standard.jar"/&gt;&lt;pathelement
location="${dir.project.lib}/taglibs-log.jar"/&gt;&lt;!--// Project
classes //--&gt;&lt;pathelement
location="${dir.project.compile}"/&gt;&lt;/path&gt;<br />
&nbsp;</span></span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(6) 基本的clean和init的task<br />
&nbsp;
&lt;target name="clean"&gt;&lt;delete
dir="${dir.project.build}"/&gt;&lt;delete
dir="${dir.project.compile.jspcache}"/&gt;&lt;delete
dir="${dir.project.compile}"/&gt;&lt;delete
dir="${dir.project.web_module}/WEB-INF/classes"/&gt;&lt;delete
dir="${dir.project.web_module}/WEB-INF/lib"/&gt;&lt;/target&gt;&lt;target
name="init"&gt;&lt;mkdir dir="${dir.project.compile}"/&gt;&lt;mkdir
dir="${dir.project.compile.jspcache}"/&gt;&lt;mkdir
dir="${dir.project.web_module}/WEB-INF/classes"/&gt;&lt;mkdir
dir="${dir.project.web_module}/WEB-INF/lib"/&gt;&lt;mkdir
dir="${dir.project.build}"/&gt;&lt;/target&gt;<br />
&nbsp;</span></span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(7) 编译Java Source<br />
&lt;target
name="src_compile" depends="init"&gt;&lt;!--// compile the Java source
//--&gt;&lt;javac srcdir="${dir.project.src}"
destdir="${dir.project.compile}" encoding="${opt.compile.encoding}"
source="${opt.compile.source}" target="${opt.compile.source}"
deprecation="${opt.compile.deprecation}"debug="${opt.compile.debug}"
optimize="{opt.compile.optimize}" &gt;&lt;classpath
refid="CLASSPATH"/&gt;&lt;include
name="**/*.java"/&gt;&lt;/javac&gt;&lt;!--// copy the classpath
resources //--&gt;&lt;copy
todir="${dir.project.compile}"&gt;&lt;fileset
dir="${dir.project.src}"&gt;&lt;exclude
name="**/*.java"/&gt;&lt;/fileset&gt;&lt;/copy&gt; &lt;/target&gt;<br />
&nbsp;</span></span></p>
<p><span><span style="font-size: 12pt; color: #000080;">(8) 预编译JSP文件，可选择基于Tomcat或是Oracle Application Server<br />
&nbsp;
&lt;!--// for Tomcat //--&gt; &lt;target name="jsp_src_generate"
depends="src_compile"&gt;&lt;taskdef classname="org.apache.jasper.JspC"
name="jasper2"&gt;&lt;classpath refid="CLASSPATH"/&gt;
&lt;/taskdef&gt;&lt;jasper2 validateXml="false"
verbose="9"uriroot="${dir.project.web_module}"
outputDir="${dir.project.compile.jspcache}"
webXmlFragment="${dir.project.compile.jspcache}/generated-web.xml"
/&gt; &lt;/target&gt;&lt;target name="jsp_src_compile"&gt;&lt;javac
srcdir="${dir.project.compile.jspcache}"
destdir="${dir.project.compile.jspcache}"
encoding="${opt.compile.encoding}" source="${opt.compile.source}"
target="${opt.compile.source}"
deprecation="${opt.compile.deprecation}"debug="${opt.compile.debug}"
optimize="{opt.compile.optimize}" &gt;&lt;classpath
refid="CLASSPATH"/&gt;&lt;include
name="**"/&gt;&lt;/javac&gt;&lt;/target&gt;&lt;target
name="jsp_precompile" depends="src_compile, jsp_src_generate,
jsp_src_compile" /&gt;<br />
&nbsp;</span></span></p>
<span><span style="font-size: 12pt; color: #000080;">(9) 开始进行compile，make 和 build，并生成部署档案<br />
&nbsp;
&lt;target name="compile" depends="src_compile, jsp_precompile"
/&gt;&lt;!--// Build WAR file //--&gt;&lt;target name="make.web_module"
depends="compile"&gt;&lt;war
destfile="${dir.project.build}/${deploy.file.web_module}"
webxml="${dir.project.web_module}/WEB-INF/web.xml"&gt;&lt;fileset
dir="${dir.project.web_module}" &gt;&lt;include
name="**"/&gt;&lt;exclude name="WEB-INF/classes/**"/&gt;&lt;exclude
name="WEB-INF/lib/**"/&gt;&lt;/fileset&gt;&lt;classes
dir="${dir.project.compile}"&gt;&lt;include name="**"/&gt;&lt;exclude
name="project/package/trx/**"/&gt;&lt;exclude
name="jspcache/**"/&gt;&lt;/classes&gt;&lt;lib
dir="${dir.project.lib}"&gt;&lt;include
name="AppUtil.jar"/&gt;&lt;include
name="AppClient.jar"/&gt;&lt;/lib&gt;&lt;/war&gt;&lt;/target&gt;&lt;!--//
Build EJB Jar file //--&gt;&lt;target name="make.ejb_module"
depends="src_compile"&gt;&lt;jar
destfile="${dir.project.build}/${deploy.file.ejb_module}"&gt;&lt;zipgroupfileset
dir="${dir.project.lib}"&gt;&lt;include
name="AppServer.jar"/&gt;&lt;/zipgroupfileset&gt;&lt;fileset
dir="${dir.project.ejb_module}"&gt;&lt;include
name="**"/&gt;&lt;/fileset&gt;&lt;fileset
dir="${dir.project.compile}"&gt;&lt;include name="**"/&gt;&lt;exclude
name="project/package/controller/**"/&gt;&lt;exclude
name="jspcache/**"/&gt;&lt;/fileset&gt;&lt;/jar&gt;&lt;/target&gt;&lt;!--//
Build EAR file //--&gt;&lt;target name="make.ear_module"
depends="compile, make.web_module, make.ejb_module"&gt;&lt;ear
destfile="${dir.project.build}/${deploy.file.ear_module}"
appxml="${dir.project.ear_module}/-INF/application.xml"&gt;&lt;fileset
dir="${dir.project.build}"&gt;&lt;include
name="${deploy.file.web_module}"/&gt;&lt;include
name="${deploy.file.ejb_module}"/&gt;&lt;/fileset&gt;&lt;/ear&gt;&lt;/target&gt;&lt;target
name="make" depends="init, compile, make.web_module, make.ejb_module,
make.ear_module" /&gt;&lt;target name="build" depends="clean, init,
make" /&gt;</span></span>
<img src ="http://www.blogjava.net/libin2722/aggbug/179856.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:59 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179856.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>配合ant开发web项目（原创）</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179855.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:58:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179855.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179855.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179855.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179855.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179855.html</trackback:ping><description><![CDATA[<p>引用地址：<a href="http://www.easydone.cn/014/200604110005145285.htm">http://www.easydone.cn/014/200604110005145285.htm</a><br />
<br />
配合ａｎｔ开发ｗｅｂ项目<br />
应用相关说明：<br />
1、ａｎｔ版本：apache-ant-1.6.1<br />
2、eclipse版本：eclipse-SDK-3.0.1-win32<br />
3、j2sdk1.4.2_08<br />
4、jakarta-tomcat-5.0.19<br />
5、mysql<br />
目录结构如下：<br />
</p>
<img src="http://www.easydone.com.cn/html/UploadFile/2006041100061630.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" /><br />
ａｎｔ具体配置如下<br />
1、"Easydone"project"demo"bin目录下新建build.xml<br />
内容如下：<br />
<br />
&lt;?xml version="1.0"&nbsp; encoding="GB2312" ?&gt;<br />
&lt;project name="Demo-Home" basedir="." default="usage"&gt;
<p>&nbsp;&lt;property name="app.name" ="demo"/&gt;<br />
&nbsp;&lt;property name="app.dir" location="../WebRoot"/&gt;<br />
&nbsp;&lt;property name="webserver.home" location="../../../platform/jakarta-tomcat-5.0.19"/&gt;<br />
&nbsp;&lt;property name="webserver.deploy" location="${webserver.home}/webapps/"/&gt;<br />
&nbsp;&lt;property name="src.dir" location="../src"/&gt;<br />
&nbsp;&lt;property name="build.dir" location="${app.dir}/WEB-INF/classes"/&gt;<br />
&nbsp;&lt;property name="lib.dir" location="${app.dir}/WEB-INF/lib"/&gt;<br />
&nbsp;&lt;property name="dist.dir" location="../dist"/&gt;<br />
&nbsp;&lt;property name="properties.dir" location="${src.dir}/com/easydone/struts/ApplicationResources.properties"/&gt;<br />
&nbsp;&lt;property name="properties_zh.dir" location="${build.dir}/com/easydone/struts/ApplicationResources_zh.properties"/&gt;<br />
&nbsp;&lt;property name="doc.dir" ="../api"/&gt;<br />
&nbsp;&lt;property name="packages" ="com.easydone.*"/&gt;<br />
&nbsp;<br />
&nbsp;&lt;echo&gt;+--------------------------------------------------+&lt;/echo&gt;<br />
&nbsp;&lt;echo&gt;|&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; |&lt;/echo&gt;<br />
&nbsp;&lt;echo&gt;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; R U N N I N G&nbsp;&nbsp; A N T&nbsp;&nbsp;&nbsp; REPOSITORY&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&lt;/echo&gt;<br />
&nbsp;&lt;echo&gt;|&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; |&lt;/echo&gt;<br />
&nbsp;&lt;echo&gt;+--------------------------------------------------+&lt;/echo&gt;<br />
&nbsp;&lt;!---Help Information--&gt;<br />
&nbsp;&lt;target name="usage" &gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message=""/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="-------------------------------------------------------------"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="操作说明："/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="首先将您编写的java文件拷贝至${src.dir}目录下,按先后顺序执行以下命令既可。"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="第一步：compile 命令编译*.java"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="第二步：deploy 命令生成${app.name}.jar文件"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="第三步：doc 命令生成详细javadoc文档"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="每一步操作都能看到 BUILD SUCCESSFUL提示后，表示您操作成功！"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="-------------------------------------------------------------"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message=""/&gt;<br />
&nbsp;&lt;/target&gt;&nbsp;&nbsp;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 设置应用环境变量&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; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;&nbsp;<br />
&nbsp;&lt;path id="compile.classpath"&gt;<br />
&nbsp;&nbsp;&lt;pathelement path ="${build.dir}"/&gt;<br />
&nbsp;&nbsp;&lt;fileset dir="${lib.dir}"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;include name="**/*.jar"/&gt;<br />
&nbsp;&nbsp;&lt;/fileset&gt;<br />
&nbsp;&lt;/path&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 格式化中文资源包，解决国际化中文问题&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;&nbsp;<br />
&nbsp;&nbsp;&nbsp; &lt;target name="checkToZh"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;uptodate property="toZh.notRequired"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; srcfile="${properties.dir}"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; targetfile="${properties_zh.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;target name="toZh" depends="checkToZh" unless="toZh.notRequired"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;delete file="${properties_zh.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- native2ascii struts.properties --&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;exec executable="native2ascii"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;arg line=" ${properties.dir}&nbsp; ${properties_zh.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/exec&gt;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;echo message="toZh performed!"/&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 初始化创建相关应用目录&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; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp;&nbsp;&nbsp; &lt;target name="prepare" deion="create build,dist files"&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt;mkdir dir="${build.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp; &nbsp;&lt;mkdir dir="${dist.dir}"/&gt;&nbsp;&nbsp; &nbsp;<br />
&nbsp;&nbsp;&nbsp; &lt;/target&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 初始化应用程序，删除相关目录&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; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;&nbsp;<br />
&nbsp;&lt;target name="clean" deion="Delete build files"&gt;<br />
&nbsp;&nbsp;&lt;delete dir="${build.dir}"/&gt;<br />
&nbsp;&nbsp;&lt;delete dir="${dist.dir}"/&gt;<br />
&nbsp;&lt;/target&gt;<br />
&nbsp;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- compile 命令，执行javac编译命令&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;&nbsp;<br />
&nbsp;&lt;target name="compile" depends="prepare"&gt;<br />
&nbsp;&nbsp;&lt;javac srcdir="${src.dir}" destdir="${build.dir}" debug="on"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;classpath refid="compile.classpath"/&gt;<br />
&nbsp;&nbsp;&lt;/javac&gt;<br />
&nbsp;&lt;/target&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- update命令，编译及处理国际化中文资源文件 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp;&lt;target name="update" depends="compile,toZh"&gt;<br />
&nbsp;&nbsp;&lt;!--copy classes--&gt;<br />
&nbsp;&nbsp;&lt;copy todir="${webserver.deploy}/${app.name}/WEB-INF/classes" includeEmptyDirs="no"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset dir="${build.dir}"/&gt;<br />
&nbsp;&nbsp;&lt;/copy&gt;<br />
&nbsp;&nbsp;&lt;!--copy pages--&gt;<br />
&nbsp;&nbsp;&lt;copy todir="${webserver.deploy}/${app.name}" includeEmptyDirs="no"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset dir="${app.dir}"/&gt;<br />
&nbsp;&nbsp;&lt;/copy&gt;<br />
&nbsp;&nbsp;&lt;!-- copy libs--&gt;<br />
&nbsp;&nbsp;&lt;copy todir="${webserver.deploy}/${app.name}/WEB-INF/lib" includeEmptyDirs="no"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset dir="${lib.dir}"/&gt;<br />
&nbsp;&nbsp;&lt;/copy&gt;<br />
&nbsp;&lt;/target&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 部署应用程序，依赖于 compile命令clean,prepare,compile,dist&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;</p>
&nbsp;&lt;target name="deploy" depends="clean,prepare,compile,toZh,dist"&gt;<br />
&nbsp;&nbsp;&lt;delete dir="${webserver.deploy}/${app.name}.war"/&gt;<br />
&nbsp;&nbsp;&lt;delete dir="${webserver.deploy}/${app.name}"/&gt;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&lt;copy todir="${webserver.deploy}" includeEmptyDirs="no"&gt;<br />
&nbsp;&nbsp;&nbsp;&lt;fileset dir="${dist.dir}"/&gt;<br />
&nbsp;&nbsp;&lt;/copy&gt;<br />
&nbsp;&lt;/target&gt;&nbsp;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 部署应用程序，将其打为mshome.war包，依赖于 compile命令&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;&nbsp;<br />
&nbsp;&lt;target name="dist" depends="compile"&gt;<br />
&nbsp;&nbsp; &lt;echo&gt;building war...&lt;/echo&gt;<br />
&nbsp;&nbsp; &lt;war warfile="${dist.dir}/${app.name}.war"<br />
&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; webxml="${app.dir}/WEB-INF/web.xml"&gt;<br />
&nbsp;&nbsp; &nbsp; &lt;fileset dir="${app.dir}"/&gt;<br />
&nbsp;&nbsp; &nbsp; &lt;classes dir="${build.dir}"/&gt;<br />
&nbsp;&nbsp; &nbsp; &lt;classes dir="${lib.dir}"&gt;<br />
&nbsp;&nbsp; &nbsp; &nbsp;&lt;include name="*.propertries"/&gt;<br />
&nbsp;&nbsp; &lt;/classes&gt;<br />
&nbsp;&nbsp; &lt;lib dir="${lib.dir}"&gt;<br />
&nbsp;&nbsp; &nbsp;&lt;include name="*.jar"/&gt;<br />
&nbsp;&nbsp; &lt;/lib&gt;<br />
&nbsp;&nbsp;&lt;/war&gt;<br />
&nbsp;&lt;/target&gt;&nbsp;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 生成说明文档(api)&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; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp;&lt;target name="javadoc" depends="usage,compile"&gt;<br />
&nbsp;&nbsp; &nbsp;&lt;delete dir="${doc.dir}"/&gt;<br />
&nbsp;&nbsp; &nbsp;&lt;mkdir dir="${doc.dir}"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;javadoc packagenames="${packages}"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sourcepath="${src.dir}"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; destdir="${doc.dir}"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; author="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; version="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; use="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; splitindex="true"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; windowtitle="${app.name} API"<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; doctitle="${app.name}"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;classpath refid="compile.classpath"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp; &lt;/javadoc&gt;<br />
&nbsp; &lt;/target&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt;<br />
&nbsp; &lt;!-- 执行一个数据库操作，其中demo为您的数据库名，可测试相关jdbc连接<br />
&nbsp; &nbsp;&nbsp;&nbsp; 查询语句为bin目录下的db.sql&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; --&gt;<br />
&nbsp; &lt;!-- =================================================================== --&gt; &nbsp;<br />
&nbsp;&lt;target name = "mysqlInit"&gt;<br />
&nbsp;&lt;echo&gt;ANT 操作数据库开始.....&lt;/echo&gt;<br />
&nbsp;&lt;sql<br />
&nbsp;&nbsp;driver = "org.gjt.mm.mysql.Driver"<br />
&nbsp;&nbsp;url = "jdbc:mysql://localhost:3306/demo"<br />
&nbsp;&nbsp;userid = "root"<br />
&nbsp;&nbsp;password = "*******"<br />
&nbsp;&nbsp;src = "db.sql"<br />
&nbsp;&nbsp;print="yes"<br />
&nbsp;&nbsp;="continue"<br />
&nbsp;/&gt;<br />
&nbsp;&lt;/target&gt;<br />
&nbsp;&lt;!--END--&gt;<br />
&lt;/project&gt;<br />
<br />
2、在"Easydone"project"demo"bin目录下新建setEnv.bat<br />
dos处理脚本，主要为设置环境变量（这样做您无需手工配置环境变量，将整个工程移动到任何目录都可以使用），内容如下：<br />
<br />
set ANT_HOME=../../../platform/apache-ant-1.6.1<br />
set JAVA_HOME=../../../platform/j2sdk1.4.2_08<br />
set CLASSPATH=%JAVA_HOME%/lib/toos.jar;%JAVA_HOME%/lib/dt.jar<br />
set CATALINA_HOME=../../../platform/jakarta-tomcat-5.0.19<br />
set PATH=%ANT_HOME%/bin;%CATALINA_HOME%/BIN;%JAVA_HOME%/bin;%CATALINA_HOME%/BIN<br />
3、服务控制脚本：<br />
tomcat启动服务：<br />
在"Easydone"project"demo"bin目录下新建　<strong>run.cmd：</strong><br />
<br />
call setEnv.bat<br />
startup<br />
<br />
tomcat停止服务：<br />
在"Easydone"project"demo"bin目录下新建　<strong>down.cmd<br />
</strong><br />
call setEnv.bat<br />
shutdown<br />
<br />
更新脚本：<br />
在"Easydone"project"demo"bin目录下新建　<strong>update.cmd<br />
</strong>call setEnv.bat<br />
ant -buildfile build.xml&nbsp; update<br />
<br />
部署脚本：<br />
在"Easydone"project"demo"bin目录下新建　<strong>deploy.cmd<br />
</strong>call setEnv.bat<br />
ant -buildfile build.xml&nbsp; deploy<br />
<br />
java doc 脚本：<br />
在"Easydone"project"demo"bin目录下新建　<strong>doc.cmd</strong><br />
call setEnv.bat<br />
ant -buildfile build.xml&nbsp; javadoc<br />
<br />
剩下的都在build.xml中，根据你的需要自己定义脚本程序就可以了<br />
很简单，这样可控制你的应用。
<img src ="http://www.blogjava.net/libin2722/aggbug/179855.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:58 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179855.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对google个性主页的拖拽效果的js的完整注释－1</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:51:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179851.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179851.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179851.html</trackback:ping><description><![CDATA[<span style="color: #008000;">//</span> <span style="color: #008000;">工具类，使用Util的命名空间，方便管理</span> <span style="color: #008000;"><br />
</span><span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;Util&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #0000ff;">new</span> <span style="color: #000000;">&nbsp;Object();<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">获取http&nbsp;header里面的UserAgent，浏览器信息</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.getUserAgent&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;navigator.userAgent;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">是否是Gecko核心的Browser，比如Mozila、Firefox</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.isGecko&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getUserAgent.indexOf(</span> <span style="color: #000000;">"</span> <span style="color: #000000;">Gecko</span> <span style="color: #000000;">"</span> <span style="color: #000000;">)&nbsp;</span> <span style="color: #000000;">!=</span> &nbsp; <span style="color: #000000;">-</span> <span style="color: #000000;">1</span> <span style="color: #000000;">;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">是否是Opera</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.isOpera&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getUserAgent.indexOf(</span> <span style="color: #000000;">"</span> <span style="color: #000000;">Opera</span> <span style="color: #000000;">"</span> <span style="color: #000000;">)&nbsp;</span> <span style="color: #000000;">!=</span> &nbsp; <span style="color: #000000;">-</span> <span style="color: #000000;">1</span> <span style="color: #000000;">;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">获取一个element的offset信息，其实就是相对于Body的padding以内的绝对坐标</span> <span style="color: #008000;"><br />
//</span> <span style="color: #008000;">后面一个参数如果是true则获取offsetLeft，false则是offsetTop</span> <span style="color: #008000;"><br />
//</span> <span style="color: #008000;">关于offset、style、client等坐标的定义参考dindin的这个帖子：http://www.jroller.com/page/dindin/?anchor=pro_java_12</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.getOffset&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;(el,&nbsp;isLeft)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;ret&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">0</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">while</span> <span style="color: #000000;">&nbsp;(el&nbsp;</span> <span style="color: #000000;">!=</span> &nbsp; <span style="color: #0000ff;">null</span> <span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ret&nbsp;</span> <span style="color: #000000;">+=</span> <span style="color: #000000;">&nbsp;el[</span> <span style="color: #000000;">"</span> <span style="color: #000000;">offset</span> <span style="color: #000000;">"</span> &nbsp; <span style="color: #000000;">+</span> <span style="color: #000000;">&nbsp;(isLeft&nbsp;</span> <span style="color: #000000;">?</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">Left</span> <span style="color: #000000;">"</span> <span style="color: #000000;">&nbsp;:&nbsp;</span> <span style="color: #000000;">"</span> <span style="color: #000000;">Top</span> <span style="color: #000000;">"</span> <span style="color: #000000;">)];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;el&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;el.offsetParent;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> <span style="color: #000000;">&nbsp;ret;<br />
};<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">将一个（参数中的funcName是这个fuction的名字）绑定到一个element上，并且以这个element的上下文运行，其实是一种继承，这个可以google些文章看看</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.bind&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;(el,&nbsp;fucName)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> <span style="color: #000000;">&nbsp;el[fucName].apply(el,&nbsp;arguments);<br />
&nbsp;&nbsp;&nbsp;&nbsp;};<br />
};<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">重新计算所有的可以拖拽的element的坐标，对同一个column下面的可拖拽图层重新计算它们的高度而得出新的坐标，防止遮叠</span> <span style="color: #008000;"><br />
//</span> <span style="color: #008000;">计算出来的坐标记录在pagePosLeft和pagePosTop两个属性里面</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.re_calcOff&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;(el)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">for</span> <span style="color: #000000;">&nbsp;(</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;i&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <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;Util.dragArray.length;&nbsp;i</span> <span style="color: #000000;">++</span> <span style="color: #000000;">)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;ele&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.dragArray[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ele.elm.pagePosLeft&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getOffset(ele.elm,&nbsp;</span> <span style="color: #0000ff;">true</span> <span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ele.elm.pagePosTop&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;Util.getOffset(ele.elm,&nbsp;</span> <span style="color: #0000ff;">false</span> <span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">var</span> <span style="color: #000000;">&nbsp;nextSib&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;el.elm.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">while</span> <span style="color: #000000;">&nbsp;(nextSib)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nextSib.pagePosTop&nbsp;</span> <span style="color: #000000;">-=</span> <span style="color: #000000;">&nbsp;el.elm.offsetHeight;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nextSib&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;nextSib.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
};<br />
<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">隐藏Google&nbsp;Ig中间那个table，也就是拖拽的容器，配合show一般就是刷新用，解决一些浏览器的怪癖</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.hide&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Util.rootElement.style.display&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">none</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
};<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">显示Google&nbsp;Ig中间那个table，解释同上</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">Util.show&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;Util.rootElement.style.display&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">""</span> <span style="color: #000000;">;<br />
};<br />
<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">移动时显示的占位虚线框</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">ghostElement&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #0000ff;">null</span> <span style="color: #000000;">;<br />
</span><span style="color: #008000;">//</span> <span style="color: #008000;">获取这个虚线框，通过dom动态生成</span> <span style="color: #008000;"><br />
</span><span style="color: #000000;">getGhostElement&nbsp;</span> <span style="color: #000000;">=</span> &nbsp;  <span style="color: #000000;">&nbsp;()&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">if</span> <span style="color: #000000;">&nbsp;(</span> <span style="color: #000000;">!</span> <span style="color: #000000;">ghostElement)&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement&nbsp;</span> <span style="color: #000000;">=</span> <span style="color: #000000;">&nbsp;createElement(</span> <span style="color: #000000;">"</span> <span style="color: #000000;">DIV</span> <span style="color: #000000;">"</span> <span style="color: #000000;">);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.className&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">modbox</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.backgroundColor&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">""</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.style.border&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">2px&nbsp;dashed&nbsp;#aaa</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ghostElement.innerHTML&nbsp;</span> <span style="color: #000000;">=</span> &nbsp; <span style="color: #000000;">"</span> <span style="color: #000000;">&amp;nbsp;</span> <span style="color: #000000;">"</span> <span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span> <span style="color: #0000ff;">return</span> <span style="color: #000000;">&nbsp;ghostElement;<br />
};<br />
</span>
<p>// 初始化可以拖拽的Element的函数，与拖拽无关的我去掉了 <br />
&nbsp; draggable(el) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的开始拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragStart&nbsp; =&nbsp; start_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的正在拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._drag&nbsp; =&nbsp; when_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的拖拽结束的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragEnd&nbsp; =&nbsp; end_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这个函数主要用来进行拖拽结束后的dom处理 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._afterDrag&nbsp; =&nbsp; after_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 是否正在被拖动，一开始当然没有被拖动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将这个Element的this指针注册在elm这个变量里面，方便在自己的上下文以外调用自己的函数等，很常用的方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm&nbsp; =&nbsp; el;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 触发拖拽的Element，在这里就是这个div上显示标题的那个div <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .header&nbsp; =&nbsp; getElementById(el.id&nbsp; +&nbsp;&nbsp; " _h " );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 对于有i的element拖拽不同，这里检测一下并记录 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .hasI&nbsp; =&nbsp;&nbsp; this .elm.getElementsByTagName( " I " ).length&nbsp; &gt;&nbsp;&nbsp; 0 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果找到了header就绑定drag相关的event <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( this .header) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽时的叉子鼠标指针 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .header.style.cursor&nbsp; =&nbsp;&nbsp; " move " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将函数绑定到header和element的this上，参照那个函数的说明 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Drag.init( this .header,&nbsp; this .elm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 下面三个语句将写好的三个函数绑定给这个elemnt的三个函数钩子上，也就实现了element从draggable继承可拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragStart&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragStart " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDrag&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _drag " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragEnd&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragEnd " );<br />
&nbsp;&nbsp;&nbsp; }<br />
};</p>
// 下面就是draggable里面用到的那4个 <br />
// 公用的开始拖拽的函数 <br />
&nbsp; start_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 重置坐标，实现拖拽以后自己的位置马上会被填充的效果 <br />
&nbsp;&nbsp;&nbsp; Util.re_calcOff( this );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 记录原先的邻居节点，用来对比是否被移动到新的位置 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .origNextSibling&nbsp; =&nbsp;&nbsp; this .elm.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取移动的时候那个灰色的虚线框 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _ghostElement&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的高度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offH&nbsp; =&nbsp;&nbsp; this .elm.offsetHeight;<br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isGecko) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 修正gecko引擎的怪癖吧 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offH&nbsp; -=&nbsp; parseInt(_ghostElement.style.borderTopWidth)&nbsp; *&nbsp;&nbsp; 2 ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的宽度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offW&nbsp; =&nbsp;&nbsp; this .elm.offsetWidth;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取left和top的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offLeft&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; true );<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offTop&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; false );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 防止闪烁，现隐藏 <br />
&nbsp;&nbsp;&nbsp; Util.hide();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将自己的宽度记录在style属性里面 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.width&nbsp; =&nbsp; offW&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将那个灰框设定得与正在拖动的对象一样高，比较形象 <br />
&nbsp;&nbsp;&nbsp; _ghostElement.style.height&nbsp; =&nbsp; offH&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 把灰框放到这个对象原先的位置上 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.parentNode.insertBefore(_ghostElement,&nbsp; this .elm.nextSibling);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于要拖动必须将被拖动的对象从原先的盒子模型里面抽出来，所以设定position为absolute，这个可以参考一下css布局方面的知识 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.position&nbsp; =&nbsp;&nbsp; " absolute " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 设置zIndex，让它处在最前面一层，当然其实zIndex=100是让它很靠前，如果页面里有zIndex&gt;100的，那&#8230;&#8230; <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.zIndex&nbsp; =&nbsp;&nbsp; 100 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于position=absolute了，所以left和top实现绝对坐标定位，这就是先前计算坐标的作用，不让这个模型乱跑，要从开始拖动的地方开始移动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.left&nbsp; =&nbsp; offLeft&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.top&nbsp; =&nbsp; offTop&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 坐标设定完毕，可以显示了，这样就不会闪烁了 <br />
&nbsp;&nbsp;&nbsp; Util.show();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这里本来有个ig_d.G，没搞明白干什么用的，不过没有也可以用，谁知道麻烦告诉我一声，不好意思 <br />
&nbsp;&nbsp;&nbsp;&nbsp; // 还没有开始拖拽，这里做个记号 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
};<br />
<br />
<div><span style="color: #008000;">// 初始化可以拖拽的Element的函数，与拖拽无关的我去掉了 <br />
&nbsp; draggable(el) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的开始拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragStart&nbsp; =&nbsp; start_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的正在拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._drag&nbsp; =&nbsp; when_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 公用的拖拽结束的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._dragEnd&nbsp; =&nbsp; end_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这个函数主要用来进行拖拽结束后的dom处理 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this ._afterDrag&nbsp; =&nbsp; after_Drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 是否正在被拖动，一开始当然没有被拖动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将这个Element的this指针注册在elm这个变量里面，方便在自己的上下文以外调用自己的函数等，很常用的方法 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm&nbsp; =&nbsp; el;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 触发拖拽的Element，在这里就是这个div上显示标题的那个div <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .header&nbsp; =&nbsp; getElementById(el.id&nbsp; +&nbsp;&nbsp; " _h " );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 对于有i的element拖拽不同，这里检测一下并记录 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .hasI&nbsp; =&nbsp;&nbsp; this .elm.getElementsByTagName( " I " ).length&nbsp; &gt;&nbsp;&nbsp; 0 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果找到了header就绑定drag相关的event <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( this .header) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽时的叉子鼠标指针 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .header.style.cursor&nbsp; =&nbsp;&nbsp; " move " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将函数绑定到header和element的this上，参照那个函数的说明 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Drag.init( this .header,&nbsp; this .elm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 下面三个语句将写好的三个函数绑定给这个elemnt的三个函数钩子上，也就实现了element从draggable继承可拖拽的函数 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragStart&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragStart " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDrag&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _drag " );<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.onDragEnd&nbsp; =&nbsp; Util.bind( this ,&nbsp; " _dragEnd " );<br />
&nbsp;&nbsp;&nbsp; }<br />
};</span></div>
<span style="color: #008000;">// 下面就是draggable里面用到的那4个 <br />
// 公用的开始拖拽的函数 <br />
&nbsp; start_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 重置坐标，实现拖拽以后自己的位置马上会被填充的效果 <br />
&nbsp;&nbsp;&nbsp; Util.re_calcOff( this );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 记录原先的邻居节点，用来对比是否被移动到新的位置 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .origNextSibling&nbsp; =&nbsp;&nbsp; this .elm.nextSibling;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取移动的时候那个灰色的虚线框 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _ghostElement&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的高度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offH&nbsp; =&nbsp;&nbsp; this .elm.offsetHeight;<br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isGecko) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 修正gecko引擎的怪癖吧 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; offH&nbsp; -=&nbsp; parseInt(_ghostElement.style.borderTopWidth)&nbsp; *&nbsp;&nbsp; 2 ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取正在移动的这个对象的宽度 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offW&nbsp; =&nbsp;&nbsp; this .elm.offsetWidth;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取left和top的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offLeft&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; true );<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; offTop&nbsp; =&nbsp; Util.getOffset( this .elm,&nbsp; false );<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 防止闪烁，现隐藏 <br />
&nbsp;&nbsp;&nbsp; Util.hide();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将自己的宽度记录在style属性里面 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.width&nbsp; =&nbsp; offW&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 将那个灰框设定得与正在拖动的对象一样高，比较形象 <br />
&nbsp;&nbsp;&nbsp; _ghostElement.style.height&nbsp; =&nbsp; offH&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 把灰框放到这个对象原先的位置上 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.parentNode.insertBefore(_ghostElement,&nbsp; this .elm.nextSibling);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于要拖动必须将被拖动的对象从原先的盒子模型里面抽出来，所以设定position为absolute，这个可以参考一下css布局方面的知识 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.position&nbsp; =&nbsp;&nbsp; " absolute " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 设置zIndex，让它处在最前面一层，当然其实zIndex=100是让它很靠前，如果页面里有zIndex&gt;100的，那&#8230;&#8230; <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.zIndex&nbsp; =&nbsp;&nbsp; 100 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 由于position=absolute了，所以left和top实现绝对坐标定位，这就是先前计算坐标的作用，不让这个模型乱跑，要从开始拖动的地方开始移动 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.left&nbsp; =&nbsp; offLeft&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.top&nbsp; =&nbsp; offTop&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 坐标设定完毕，可以显示了，这样就不会闪烁了 <br />
&nbsp;&nbsp;&nbsp; Util.show();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这里本来有个ig_d.G，没搞明白干什么用的，不过没有也可以用，谁知道麻烦告诉我一声，不好意思 <br />
&nbsp;&nbsp;&nbsp;&nbsp; // 还没有开始拖拽，这里做个记号 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
};<br />
</span><span style="color: #000000;">// 在拖拽时的相应函数，由于绑定到鼠标的move这个event上，所以会传入鼠标的坐标clientX, clientY <br />
&nbsp; when_Drag(clientX, clientY) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 刚开始拖拽的时候将图层变透明，并标记为正在被拖拽 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( ! this .isDragging) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.filter&nbsp; =&nbsp;&nbsp; " alpha(opacity=70) " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.opacity&nbsp; =&nbsp;&nbsp; 0.7 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this .isDragging&nbsp; =&nbsp;&nbsp; true ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 被拖拽到的新的column（当然也可以是原来那个） <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; found&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 最大的距离，可能是防止溢出或者什么bug <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; max_distance&nbsp; =&nbsp;&nbsp; 100000000 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 遍历所有的可拖拽的element，寻找离当前鼠标坐标最近的那个可拖拽元素，以便后面插入 <br />
&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp; ( var&nbsp; i&nbsp; =&nbsp;&nbsp; 0 ; i&nbsp; &lt;&nbsp; Util.dragArray.length; i ++ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele&nbsp; =&nbsp; Util.dragArray[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 利用勾股定理计算鼠标到遍历到的这个元素的距离 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
var&nbsp; distance&nbsp; =&nbsp; Math.sqrt(Math.pow(clientX&nbsp; -&nbsp; ele.elm.pagePosLeft,&nbsp;
2 )&nbsp; +&nbsp; Math.pow(clientY&nbsp; -&nbsp; ele.elm.pagePosTop,&nbsp; 2 ));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 自己已经浮动了，所以不计算自己的 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (ele&nbsp; ==&nbsp;&nbsp; this ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果计算失败继续循环 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (isNaN(distance)) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; continue ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果更小，记录下这个距离，并将它作为found <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (distance&nbsp; &lt;&nbsp; max_distance) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; max_distance&nbsp; =&nbsp; distance;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; found&nbsp; =&nbsp; ele;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 准备让灰框落脚 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _ghostElement&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果找到了另外的落脚点 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (found&nbsp; !=&nbsp;&nbsp; null&nbsp;&nbsp; &amp;&amp;&nbsp; _ghostElement.nextSibling&nbsp; !=&nbsp; found.elm) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 找到落脚点就先把灰框插进去，这就是我们看到的那个灰框停靠的特效，有点像吸附的感觉，哈哈 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; found.elm.parentNode.insertBefore(_ghostElement, found.elm);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isOpera) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Opera的现实问题，要隐藏/显示后才能刷新出变化 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; " none " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
};<br />
// 拖拽完毕 <br />
&nbsp; end_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽完毕后执行后面的钩子，执行after_Drag()，如果布局发生了变动了就记录到远程服务器，保存你拖拽后新的布局顺序 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( this ._afterDrag()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // remote call to save the change <br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; true ;<br />
};<br />
// 拖拽后的执行钩子 <br />
&nbsp; after_Drag() {<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; return&nbsp; =&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 防止闪烁 <br />
&nbsp;&nbsp;&nbsp; Util.hide();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 把拖拽时的position=absolute和相关的那些style都消除 <br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.position&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.width&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.zIndex&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.filter&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; this .elm.style.opacity&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 获取灰框 <br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele&nbsp; =&nbsp; getGhostElement();<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 如果现在的邻居不是原来的邻居了 <br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (ele.nextSibling&nbsp; !=&nbsp;&nbsp; this .origNextSibling) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 把被拖拽的这个节点插到灰框的前面 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ele.parentNode.insertBefore( this .elm, ele.nextSibling);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 标明被拖拽了新的地方 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; =&nbsp;&nbsp; true ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 移除灰框，这是这个灰框的生命周期应该就结束了 <br />
&nbsp;&nbsp;&nbsp; ele.parentNode.removeChild(ele);<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 修改完毕，显示 <br />
&nbsp;&nbsp;&nbsp; Util.show();<br />
&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (Util.isOpera) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Opera的现实问题，要隐藏/显示后才能刷新出变化 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; " none " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; body.style.display&nbsp; =&nbsp;&nbsp; "" ;<br />
&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; return;<br />
};<br />
</span><span style="color: #000000;"><br />
<br />
</span>
<p><span style="color: #008000;">// 可拖拽Element的原形，用来将event绑定到各个钩子，这部分市比较通用的，netvibes也是基本完全相同的实现 <br />
// 这部分推荐看dindin的这个，也会帮助理解，<a href="http://www.jroller.com/page/dindin/?anchor=pro_java_12">http://www.jroller.com/page/dindin/?anchor=pro_java_12</a> <br />
var&nbsp; Drag&nbsp; =&nbsp; {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 对这个element的引用，一次只能拖拽一个Element <br />
&nbsp;&nbsp;&nbsp; obj: null , <br />
&nbsp;&nbsp;&nbsp;&nbsp; // element是被拖拽的对象的引用，elementHeader就是鼠标可以拖拽的区域 <br />
&nbsp;&nbsp;&nbsp; init: &nbsp; (elementHeader, element) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将start绑定到down事件，按下鼠标触发start <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elementHeader.down&nbsp; =&nbsp; Drag.start;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将element存到header的obj里面，方便header拖拽的时候引用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; elementHeader.obj&nbsp; =&nbsp; element;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 初始化绝对的坐标，因为不是position=absolute所以不会起什么作用，但是防止后面onDrag的时候parse出错了 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (isNaN(parseInt(element.style.left))) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.left&nbsp; =&nbsp;&nbsp; " 0px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (isNaN(parseInt(element.style.top))) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.top&nbsp; =&nbsp;&nbsp; " 0px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 挂上空，初始化这几个成员，在Drag.init被调用后才帮定到实际的函数，可以参照draggable里面的内容 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDragStart&nbsp; =&nbsp;&nbsp; new&nbsp; ();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDragEnd&nbsp; =&nbsp;&nbsp; new&nbsp; ();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDrag&nbsp; =&nbsp;&nbsp; new&nbsp; ();<br />
&nbsp;&nbsp;&nbsp; },<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 开始拖拽的绑定，绑定到鼠标的移动的event上 <br />
&nbsp;&nbsp;&nbsp; start: &nbsp; (event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; element&nbsp; =&nbsp; Drag.obj&nbsp; =&nbsp;&nbsp; this .obj;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event&nbsp; =&nbsp; Drag.fixE(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 看看是不是左键点击 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (event.which&nbsp; !=&nbsp;&nbsp; 1 ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 除了左键都不起作用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; true ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 参照这个函数的解释，挂上开始拖拽的钩子 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDragStart();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录鼠标坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseX&nbsp; =&nbsp; event.clientX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseY&nbsp; =&nbsp; event.clientY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 将Global的event绑定到被拖动的element上面来 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; up&nbsp; =&nbsp; Drag.end;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; move&nbsp; =&nbsp; Drag.drag;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp; }, <br />
&nbsp;&nbsp;&nbsp;&nbsp; // Element正在被拖动的函数 <br />
&nbsp;&nbsp;&nbsp; drag: &nbsp; (event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event&nbsp; =&nbsp; Drag.fixE(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 看看是不是左键点击 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (event.which&nbsp; ==&nbsp;&nbsp; 0 ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 除了左键都不起作用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; Drag.end();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 正在被拖动的Element <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; element&nbsp; =&nbsp; Drag.obj;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 鼠标坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _clientX&nbsp; =&nbsp; event.clientY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _clientY&nbsp; =&nbsp; event.clientX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果鼠标没动就什么都不作 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (element.lastMouseX&nbsp; ==&nbsp; _clientY&nbsp; &amp;&amp;&nbsp; element.lastMouseY&nbsp; ==&nbsp; _clientX) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 刚才Element的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _lastX&nbsp; =&nbsp; parseInt(element.style.top);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _lastY&nbsp; =&nbsp; parseInt(element.style.left);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 新的坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; newX, newY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 计算新的坐标：原先的坐标+鼠标移动的值差 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newX&nbsp; =&nbsp; _lastY&nbsp; +&nbsp; _clientY&nbsp; -&nbsp; element.lastMouseX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newY&nbsp; =&nbsp; _lastX&nbsp; +&nbsp; _clientX&nbsp; -&nbsp; element.lastMouseY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 修改element的显示坐标 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.left&nbsp; =&nbsp; newX&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.style.top&nbsp; =&nbsp; newY&nbsp; +&nbsp;&nbsp; " px " ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 记录element现在的坐标供下一次移动使用 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseX&nbsp; =&nbsp; _clientY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.lastMouseY&nbsp; =&nbsp; _clientX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 参照这个函数的解释，挂接上Drag时的钩子 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; element.onDrag(newX, newY);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;&nbsp; false ;<br />
&nbsp;&nbsp;&nbsp; },<br />
&nbsp;&nbsp;&nbsp;&nbsp; // Element正在被释放的函数，停止拖拽 <br />
&nbsp;&nbsp;&nbsp; end: &nbsp; (event) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; event&nbsp; =&nbsp; Drag.fixE(event);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 解除对Global的event的绑定 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; move&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; up&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 先记录下onDragEnd的钩子，好移除obj <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; _onDragEndFuc&nbsp; =&nbsp; Drag.obj.onDragEnd();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 拖拽完毕，obj清空 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Drag.obj&nbsp; =&nbsp;&nbsp; null ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; _onDragEndFuc;<br />
&nbsp;&nbsp;&nbsp; }, <br />
&nbsp;&nbsp;&nbsp;&nbsp; // 解决不同浏览器的event模型不同的问题 <br />
&nbsp;&nbsp;&nbsp; fixE: &nbsp; (ig_) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_&nbsp; =&nbsp; event;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_.layerX&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_.layerX&nbsp; =&nbsp; ig_.offsetX;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_.layerY&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_.layerY&nbsp; =&nbsp; ig_.offsetY;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; ( typeof&nbsp; ig_.which&nbsp; ==&nbsp;&nbsp; " undefined " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ig_.which&nbsp; =&nbsp; ig_.button;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp; ig_;<br />
&nbsp;&nbsp;&nbsp; }<br />
};</span></p>
<p><span style="color: #008000;">// 下面是初始化的函数了，看看上面这些东西怎么被调用 <br />
var&nbsp; _IG_initDrag&nbsp; =&nbsp;&nbsp; &nbsp; (el) {<br />
&nbsp;&nbsp;&nbsp;&nbsp; // column那个容器，在google里面就是那个table布局的tbody，netvibes用的&lt;div&gt; <br />
&nbsp;&nbsp;&nbsp; Util.rootElement&nbsp; =&nbsp; el;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 这个tbody的行 <br />
&nbsp;&nbsp;&nbsp; Util._rows&nbsp; =&nbsp; Util.rootElement.tBodies[ 0 ].rows[ 0 ];<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 列，google是3列，其实也可以更多 <br />
&nbsp;&nbsp;&nbsp; Util.column&nbsp; =&nbsp; Util._rows.cells;<br />
&nbsp;&nbsp;&nbsp;&nbsp; // 用来存取可拖拽的对象 <br />
&nbsp;&nbsp;&nbsp; Util.dragArray&nbsp; =&nbsp;&nbsp; new&nbsp; Array();<br />
&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; counter&nbsp; =&nbsp;&nbsp; 0 ;<br />
&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp; ( var&nbsp; i&nbsp; =&nbsp;&nbsp; 0 ; i&nbsp; &lt;&nbsp; Util.column.length; i ++ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 搜索所有的column <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele&nbsp; =&nbsp; Util.column[i];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for&nbsp; ( var&nbsp; j&nbsp; =&nbsp;&nbsp; 0 ; j&nbsp; &lt;&nbsp; ele.childNodes.length; j ++ ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 搜索每一column里面的所有element <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var&nbsp; ele1&nbsp; =&nbsp; ele.childNodes[j];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 如果是div就把它初始化为一个draggable对象 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if&nbsp; (ele1.tagName&nbsp; ==&nbsp;&nbsp; " DIV " ) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Util.dragArray[counter]&nbsp; =&nbsp;&nbsp; new&nbsp; draggable(ele1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; counter ++ ;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />
&nbsp;&nbsp;&nbsp; }<br />
};</span></p>
<p><span style="color: #008000;">// google的页面里可以拖动的部分的id是"t_1" <br />
// 挂载到，载入完毕执行。不过实际上google没有用。 <br />
// 而是写在页面最下面，异曲同工吧，也许直接写在页面是种怪癖，或者也有可能是兼容性考虑。 </span></p>
<p><span style="color: #008000;">// 请将下面两条被注释掉的代码加，到你自己下载的一个google ig页面里面，把里面的所有其余删除，挂上这个js也可以拖拽了，哈哈 <br />
// _table=getElementById("t_1"); <br />
//  = _IG_initDrag(_table); </span></p>
<span style="color: #008000;">// 其实看懂这些代码对学习java很有益，希望对大家能有帮助</span><br />
<img src ="http://www.blogjava.net/libin2722/aggbug/179851.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:51 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179851.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google“爬虫”主动“送食”（转载）</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179850.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179850.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179850.html</trackback:ping><description><![CDATA[<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">如果希望自己的网站能够更快的被<span style="font-family: Times New Roman;">google</span>收录，抓取更多的内容（甚至抓取所有网页），可以使用<span style="font-family: Times New Roman;">google</span>提供的<span style="font-family: Times New Roman;">google&nbsp;Sitemap</span>服务（<span style="font-family: Times New Roman;">&nbsp;<a href="https://www.google.com/webmasters/tools/docs/zh_CN/sitemap-generator.html">https://www.google.com/webmasters/tools/docs/zh_CN/sitemap-generator.html</a></span>）</p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">使搜索引搜索蜘蛛的收录由被动变为主动，<span style="font-family: Times New Roman;">google&nbsp;Sitemap</span>服务目前尚不提供在线创建<span style="font-family: Times New Roman;">Sitemap</span>的功能，但是我们可以借助第三方网站提供的此类服务，打开网站（<a href="http://www.xml-sitemaps.com/"><span style="font-family: Times New Roman;">http://www.xml-sitemaps.com</span></a>）（如图<span style="font-family: Times New Roman;">1</span>）&nbsp;</p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">在&#8220;<span style="font-family: Times New Roman;">Starting&nbsp;URL</span>&#8221;栏中输入你自己的网站地址，在&#8220;<span style="font-family: Times New Roman;">Change&nbsp;frequency</span>&#8221;下拉列表选择网站的更新频率（经常&nbsp;每天&nbsp;每年等不同的时段），在&#8220;<span style="font-family: Times New Roman;">Last&nbsp;modification</span>&#8221;选择最后修改时间（建议选择<span style="font-size: 8.5pt;">Use&nbsp;server's&nbsp;response</span>服务器反映时间&nbsp;），在&#8220;Priority&#8221;栏中速入跟新的优先权，最后点击&#8220;Start&#8221;按钮创建网站地图&nbsp;（如图0）<img src="http://www.6b9g.com/sitemap0.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" /></p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">完成操作后，我们将在显示的结果中看到各式各样的网站生成地图Sitemap文件，将&#8220;Sitemap.xml&#8221;下载到本地然后再传到服务器主目录下，下面用Gmail帐户登陆到google&nbsp;Sitemap,添加自己的网站sitemap文件（如图2）<img src="http://www.6b9g.com/sitemap.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" />，再选在添加该站点的sitemap，注意在选择分类的时候选择添加常规网络(如图3)<img src="http://www.6b9g.com/sitemap3.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)"  alt="" />sitemap然后输入刚才上传得那个sitemap.xml地址，各式<a href="http://www.6b9g.com/sitemap.xml">http://www.6b9g.com/sitemap.xml</a>&nbsp;&nbsp;再点击&#8220;添加普通sitemap&#8221;&nbsp;按钮</p>
<p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">首发&nbsp;高峰&nbsp;站长互动信息网&nbsp;&nbsp;&nbsp;<a href="http://www.6b9g.com/">http://www.6b9g.com</a></p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179850.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:44 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179850.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>论坛灌水机 -- HTTPClient</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:37:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179849.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179849.html</trackback:ping><description><![CDATA[ 这篇文章是讲如何做一个论坛灌水机，针对某个大型房地产论坛测试通过，那是一个基于jive3的论坛，假如论坛加入了图片认证登陆，本程序将失去作用。<br />
<br />
本程序使用了HTTPClient包，下载地址：<br />
<a href="http://www.innovation.ch/java/HTTPClient/" target="_blank"><span style="color: #800080;">http://www.innovation.ch/java/HTTPClient/</span></a><br />
<br />
灌水机原理很简单，就是分析论坛的表单，用自己的程序模拟提交就可以了，<br />
本文的目的在于介绍HTTPClient这个开源工具，比jdk的.net包强何止百倍，<br />
HTTPClient的特点是多个操作可以复用同一个连接，设置连接超时(基于socket)，使用代理验证。具体可以到innovation网站看看对比数据。<br />
<br />
如下是灌水程序的简单程序，仅供参考<br />
import java.net.*;<br />
import java.io.*;<br />
import java.util.*;<br />
import HTTPClient.*;<br />
<br />
class WebRequester{<br />
private static InputStream istr = null;<br />
private static OutputStream ostr = null;<br />
private static NVPair form_data[];<br />
private static HTTPConnection httpCon;<br />
private static HTTPResponse rsp;<br />
private static String host;<br />
private static WebRequester instance;<br />
private WebRequester(){<br />
}<br />
public static WebRequester getInstance(){<br />
&nbsp;&nbsp;if(instance==null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;instance = new WebRequester();<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return instance;<br />
}<br />
public static String request(HTTPConnection connection,String pathName,String method,NVPair form_data[]) {<br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;httpCon = connection;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(method.toLowerCase().equals("get")){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(form_data!=null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Get(pathName, form_data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Get(pathName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;else{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(form_data!=null)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Post(pathName, form_data);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rsp = httpCon.Post(pathName);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;istr = rsp.getInputStream();<br />
&nbsp;&nbsp;&nbsp;&nbsp;BufferedReader reader = new BufferedReader(new InputStreamReader(istr));<br />
&nbsp;&nbsp;&nbsp;&nbsp;String line;<br />
&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer result = new StringBuffer();<br />
&nbsp;&nbsp;&nbsp;&nbsp;while ((line = reader.readLine()) != null) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;result.append(line + System.getProperty("line.separator"));<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;return result.toString();<br />
&nbsp;&nbsp;} catch(Exception e){<br />
&nbsp;&nbsp;}<br />
return "";<br />
}<br />
}<br />
<br />
<br />
public class Flood<br />
{<br />
private HTTPConnection connection;<br />
public Flood(){<br />
<br />
&nbsp;&nbsp;getConnection("sitename.com",80);<br />
}<br />
public void releaseConnection(){<br />
&nbsp;&nbsp;if(connection!=null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;connection.stop();<br />
&nbsp;&nbsp;&nbsp;&nbsp;connection = null;<br />
&nbsp;&nbsp;}<br />
}<br />
public HTTPClient.HTTPConnection getConnection(String hostName,int port){<br />
&nbsp;&nbsp;if(connection==null){<br />
&nbsp;&nbsp;&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection = new HTTPClient.HTTPConnection(hostName,port);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HTTPClient.Module.setPolicyHandler(null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.addDefaultModule(Class.forName("HTTPClient.Module"), 1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;connection.addModule(Class.forName("HTTPClient.RedirectionModule"),2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}catch(Exception e){<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;e.printStackTrace();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return connection;<br />
}<br />
<br />
public void post(String subject,String body){<br />
&nbsp;&nbsp;NVPair[] form_data = new NVPair[5];<br />
&nbsp;&nbsp;form_data[0] = new NVPair("forumID","87");<br />
&nbsp;&nbsp;form_data[1] = new NVPair("subject",subject);<br />
&nbsp;&nbsp;form_data[2] = new NVPair("classifier","-1");<br />
&nbsp;&nbsp;form_data[3] = new NVPair("body",body);<br />
&nbsp;&nbsp;form_data[4] = new NVPair("doPost"," 发 表 ");<br />
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);<br />
<br />
}<br />
public void reply(String thread,String subject,String body){<br />
&nbsp;&nbsp;//提交表单需要多少项，查看回复页面表单可以获得<br />
&nbsp;&nbsp;NVPair[] form_data = new NVPair[7];<br />
&nbsp;&nbsp;form_data[0] = new NVPair("forumID","87");<br />
&nbsp;&nbsp;form_data[1] = new NVPair("subject",subject);<br />
&nbsp;&nbsp;form_data[2] = new NVPair("classifier","-1");<br />
&nbsp;&nbsp;form_data[3] = new NVPair("body",body);<br />
&nbsp;&nbsp;form_data[4] = new NVPair("reply","true");<br />
&nbsp;&nbsp;form_data[5] = new NVPair("threadID",thread);<br />
&nbsp;&nbsp;form_data[6] = new NVPair("doPost"," 发 表 ");<br />
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);<br />
<br />
}<br />
public void finish(){<br />
&nbsp;&nbsp;releaseConnection();<br />
}<br />
public void login(){<br />
<br />
&nbsp;&nbsp;WebRequester wr = WebRequester.getInstance();<br />
&nbsp;&nbsp;NVPair[] form_data = new NVPair[4];<br />
&nbsp;&nbsp;//对应登陆需要的表单字段填写<br />
&nbsp;&nbsp;form_data[0] = new NVPair("formUsername","user");<br />
&nbsp;&nbsp;form_data[1] = new NVPair("formPassword","pass");<br />
&nbsp;&nbsp;form_data[2] = new NVPair("formLogins cript","sitename.com/loginuser.jsp");<br />
&nbsp;&nbsp;form_data[3] = new NVPair("forumLogin","Y");<br />
&nbsp;&nbsp;//提交到指定登陆页面<br />
&nbsp;&nbsp;wr.request(connection,"cgi-bin/gzhome/registration/LoginUser1.jsp","post",form_data);<br />
&nbsp;&nbsp;//假如重定向，必须用该链接再次请求新的页面<br />
&nbsp;&nbsp;wr.request(connection,"loginuser.jsp","get",null);<br />
&nbsp;&nbsp;wr.request(connection,"index.jspa","get",null);<br />
}<br />
<br />
<br />
public static void main(String[] args)<br />
{&nbsp;&nbsp; <br />
&nbsp;&nbsp;try{<br />
&nbsp;&nbsp;Flood f=new Flood();<br />
&nbsp;&nbsp;f.login();<br />
&nbsp;&nbsp;//post一个新主题，id由系统自己产生<br />
&nbsp;&nbsp;//f.post("friends","剧本");<br />
&nbsp;&nbsp;//得到某个主题id，进行指定数量的跟帖<br />
&nbsp;&nbsp;for(int i=0;i&lt;50;i++){<br />
&nbsp;&nbsp;&nbsp;&nbsp;f.reply("67145","Re: 警告：在线朋友发言又少了，望奔走相告","洪水来了");<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;/*如下是读取某个文件每一行文字作为回帖进行灌水<br />
&nbsp;&nbsp;BufferedReader
br = new BufferedReader(new FileReader("E:""movie""101-105""Friends -
1x04 - TOW George Stephanopoulos.CHN.srt"));<br />
&nbsp;&nbsp;StringBuffer sb = new StringBuffer();<br />
&nbsp;&nbsp;String t = null;<br />
&nbsp;&nbsp;int counter=0;<br />
&nbsp;&nbsp;while((t=br.readLine())!=null){<br />
&nbsp;&nbsp;if(t.length()==0){<br />
&nbsp;&nbsp;&nbsp;&nbsp;//System.out.println(sb.toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//System.out.println("====");<br />
&nbsp;&nbsp;counter++;<br />
&nbsp;&nbsp;f.reply("66617","" + counter,sb.toString());<br />
&nbsp;&nbsp;sb.delete(0,sb.length());<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;sb.append(t + ""n");<br />
&nbsp;&nbsp;<br />
&nbsp;&nbsp;}*/<br />
&nbsp;&nbsp;f.finish();<br />
}catch(Exception e){<br />
&nbsp;&nbsp;e.printStackTrace();<br />
}<br />
}<br />
}<br />
<br />
<br />
OKOK~大家自己研究<br />
我做好了
<img src ="http://www.blogjava.net/libin2722/aggbug/179849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:37 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>httpclient中MultipartPostMethod类上传文件</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:35:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179848.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179848.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179848.html</trackback:ping><description><![CDATA[<p>在文件上传过程中碰到很多问题，首先是搞错了类，刚开始时我用的是PostodMethod,以为一个
setrequestbody（）方法就可以搞定，结果改过来改过去也没改出来什么名堂，最后改用的是MultipartPostMethod类，呵呵，
问题解决了，关键点是MultipartPostMethod类里的addParameter()和addPart()两个方法都要用到，而且要注意顺
序。不过马上又出现了新的问题，httpclient不支持中文名的文件上传，晕了。又在这上面浪费了一段时间。解决的途径是。找到
httpclient3.0"rc"java"org"apache"commons"httpclient"util目录下的
EncodingUtil.java,打开，找到文件里面这个地方：<br />
public static byte[] getAsciiBytes(final String data) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
if (data == null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
throw new IllegalArgumentException("Parameter may not be null");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
try {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return data.getBytes("US-ASCII");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br />
catch (UnsupportedEncodingException e) {throw new HttpClientError("HttpClient requires ASCII support");&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;<br />
}<br />
看
到了没有，return
data.getBytes("US-ASCII");它的编码方式是US-ASCII，问题就出在这里了，把这个取掉，换成"GBK"或者
"GB2312"保存以后编译，重新运行程序，goooooooooooood。中文名文件现在可以上传了，呵呵</p>
<p>Introducing FileUpload<br />
The FileUpload component has the
capability of simplifying the handling of files uploaded to a server.
Note that the FileUpload component is meant for use on the server side;
in other words, it handles where the files are being uploaded to—not
the client side where the files are uploaded from. Uploading files from
an HTML form is pretty simple; however, handling these files when they
get to the server is not that simple. If you want to apply any rules
and store these files based on those rules, things get more difficult.</p>
<p>The FileUpload component remedies this situation, and in very few
lines of code you can easily manage the files uploaded and store them
in appropriate locations. You will now see an example where you upload
some files first using a standard HTML form and then using HttpClient
code.</p>
<p>Using HTML File Upload<br />
The commonly used methodology to upload
files is to have an HTML form where you define the files you want to
upload. A common example of this HTML interface is the Web page you
encounter when you want to attach files to an email while using any of
the popular Web mail services.</p>
<p>In this example, you will create a simple HTML page where you
provide for three files to be uploaded. Listing 1-1 shows the HTML for
this page. Note that the enctype attribute for the form has the
multipart/form-data, and the input tag used is of type file. Based on
the of the action attribute, on form submission, the data is sent to
ProcessFileUpload.jsp.</p>
<p>Listing 1-1. UploadFiles.html<br />
&lt;HTML&gt;<br />
&nbsp;&nbsp;&lt;HEAD&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt; HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;TITLE&gt;File Upload Page&lt;/TITLE&gt;<br />
&nbsp;&nbsp;&lt;/HEAD&gt;<br />
&nbsp;&nbsp;&lt;BODY&gt;Upload Files<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;FORM name="filesForm" action="ProcessFileUpload.jsp"<br />
&nbsp;&nbsp;&nbsp;&nbsp;method="post" enctype="multipart/form-data"&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File 1:&lt;input type="file" name="file1"/&gt;&lt;br/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File 2:&lt;input type="file" name="file2"/&gt;&lt;br/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File 3:&lt;input type="file" name="file3"/&gt;&lt;br/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;input type="submit" name="Submit" ="Upload Files"/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/FORM&gt;<br />
&nbsp;&nbsp;&lt;/BODY&gt;<br />
&lt;/HTML&gt;</p>
<p>You can use a servlet to handle the file upload. I have used JSP to
minimize the code you need to write. The task that the JSP has to
accomplish is to pick up the files that are sent as part of the request
and store these files on the server. In the JSP, instead of displaying
the result of the upload in the Web browser, I have chosen to print
messages on the server console so that you can use this same JSP when
it is not invoked through an HTML form but by using HttpClient-based
code.</p>
<p>Listing 1-2 shows the JSP code. Note the code that checks whether
the item is a form field. This check is required because the Submit
button contents are also sent as part of the request, and you want to
distinguish between this data and the files that are part of the
request. You have set the maximum file size to 1,000,000 bytes using
the setSizeMax method.</p>
<p>Listing 1-2. ProcessFileUpload.jsp<br />
&lt;%@ page contentType="text/html;charset=windows-1252"%&gt;<br />
&lt;%@ page import="org.apache.commons.fileupload.DiskFileUpload"%&gt;<br />
&lt;%@ page import="org.apache.commons.fileupload.FileItem"%&gt;<br />
&lt;%@ page import="jsp servlet ejb .util.List"%&gt;<br />
&lt;%@ page import="jsp servlet ejb .util.Iterator"%&gt;<br />
&lt;%@ page import="jsp servlet ejb .io.File"%&gt;<br />
html&gt;<br />
&lt;head&gt;<br />
&lt; http-equiv="Content-Type" content="text/html; charset=windows-1252"&gt;<br />
&lt;title&gt;Process File Upload&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;%<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Content Type ="+request.getContentType());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DiskFileUpload fu = new DiskFileUpload();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// If file size exceeds, a FileUploadException will be thrown<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fu.setSizeMax(1000000);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;List fileItems = fu.parseRequest(request);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator itr = fileItems.iterator();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while(itr.hasNext()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FileItem fi = (FileItem)itr.next();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//Check if not form field so as to only handle the file inputs<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//else condition handles the submit button input<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(!fi.isFormField()) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(""nNAME: "+fi.getName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("SIZE: "+fi.getSize());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//System.out.println(fi.getOutputStream().toString());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File fNew= new File(application.getRealPath("/"), fi.getName());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(fNew.getAbsolutePath());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fi.write(fNew);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("Field ="+fi.getFieldName());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
%&gt;<br />
&lt;body&gt;<br />
Upload Successful!!<br />
&lt;/body&gt;<br />
&lt;/html&gt;</p>
<p>CAUTION With FileUpload 1.0 I found that when the form was submitted
using Opera version 7.11, the getName method of the class FileItem
returns just the name of the file. However, if the form is submitted
using Internet Explorer 5.5, the filename along with its entire path is
returned by the same method. This can cause some problems.</p>
<p>To run this example, you can use any three files, as the contents of
the files are not important. Upon submitting the form using Opera and
uploading three random XML files, the output I got on the Tomcat server
console was as follows:</p>
<p>Content Type =multipart/form-data; boundary=----------rz7ZNYDVpN1To8L73sZ6OE</p>
<p>NAME: academy.xml<br />
SIZE: 951<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academy.xml</p>
<p>NAME: academyRules.xml<br />
SIZE: 1211<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academyRules.xml</p>
<p>NAME: students.xml<br />
SIZE: 279<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"students.xml<br />
Field =Submit<br />
However, when submitting this same form using Internet Explorer 5.5, the output on the server console was as follows:<br />
Content Type =multipart/form-data; boundary=---------------------------7d3bb1de0<br />
2e4</p>
<p>NAME: D:"temp"academy.xml<br />
SIZE: 951<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"D:"temp"academy.xml</p>
<p>The browser displayed the following message: &#8220;The requested resource
(D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"D:"temp"academy.xml
(The filename, directory name, or volume label syntax is incorrect)) is
not available.&#8221;</p>
<p>This contrasting behavior on different browsers can cause problems. One workaround that I found in an article at <a href="http://www.onjava.com/pub/a/onjava/2003/06/25/commons.html" target="_blank"><span style="color: #000000;">http://www.onjava.com/pub/a/onjava/2003/06/25/commons.html</span></a>
is to first create a file reference with whatever is supplied by the
getName method and then create a new file reference using the name
returned by the earlier file reference. Therefore, you can insert the
following code to have your code work with both browsers (I wonder who
the guilty party is&#8230;blaming Microsoft is always the easy way out) </p>
<p>File tempFileRef&nbsp;&nbsp;= new File(fi.getName());<br />
File fNew = new File(application.getRealPath("/"),tempFileRef.getName());</p>
<p>In this section, you uploaded files using a standard HTML form
mechanism. However, often a need arises to be able to upload files from
within your jsp servlet ejb code, without any browser or form coming
into the picture. In the next section, you will look at
HttpClient-based file upload.</p>
<p>Using HttpClient-Based FileUpload<br />
Earlier in the article you saw
some of the capabilities of the HttpClient component. One capability I
did not cover was its ability to send multipart requests. In this
section, you will use this capability to upload a few files to the same
JSP that you used for uploads using HTML.</p>
<p>The class org.apache.commons.httpclient.methods.MultipartPostMethod
provides the multipart method capability to send multipart-encoded
forms, and the package org.apache.commons.httpclient.methods.multipart
has the support classes required. Sending a multipart form using
HttpClient is quite simple. In the code in Listing 1-3, you send three
files to ProcessFileUpload.jsp.</p>
<p>Listing 1-3. HttpMultiPartFileUpload.java<br />
package com.commonsbook.chap9;<br />
import jsp servlet ejb .io.File;<br />
import jsp servlet ejb .io.IOException;</p>
<p>import org.apache.commons.httpclient.HttpClient;<br />
import org.apache.commons.httpclient.methods.MultipartPostMethod;</p>
<p>public class HttpMultiPartFileUpload {<br />
&nbsp;&nbsp;&nbsp;&nbsp;private static String url =<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;"http://localhost/yaoliang/ProcessFileUpload.jsp";</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws IOException {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient client = new HttpClient();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MultipartPostMethod mPost = new MultipartPostMethod(url);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.setConnectionTimeout(8000);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Send any XML file as the body of the POST request<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File f1 = new File("D:/students.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File f2 = new File("D:/demy.xml");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;File f3 = new File("D:/demyRules.xml");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File1 Length = " + f1.length());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File2 Length = " + f2.length());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("File3 Length = " + f3.length());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.addParameter(f1.getName(),f1.getName(),&nbsp;&nbsp;f1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.addParameter(f2.getName(), f2.getName(), f2);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.addParameter(f3.getName(), f3.getName(),f3);</p>
<p>FilePart part1 = new FilePart("file1",file);<br />
FilePart part2 = new FilePart("file2",file);<br />
FilePart part3 = new FilePart("file3",file);<br />
mPost.addPart(part1);<br />
mPost.addPart(part2);<br />
mPost.addPart(part3);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int statusCode1 = client.executeMethod(mPost);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println("statusLine&gt;&gt;&gt;" + mPost.getStatusLine());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mPost.releaseConnection();<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p>In this code, you just add the files as parameters and execute the
method. The ProcessFileUpload.jsp file gets invoked, and the output is
as follows:</p>
<p>Content Type =multipart/form-data; boundary=----------------31415926535897932384<br />
6</p>
<p>NAME: students.xml<br />
SIZE: 279<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"students.xml</p>
<p>NAME: academy.xml<br />
SIZE: 951<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academy.xml</p>
<p>NAME: academyRules.xml<br />
SIZE: 1211<br />
D:"javaGizmos"jakarta-tomcat-4.0.1"webapps"HttpServerSideApp"academyRules.xml</p>
<p>Thus, file uploads on the server side become quite a simple task if you are using the Commons FileUpload component.</p>
<img src ="http://www.blogjava.net/libin2722/aggbug/179848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:35 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用HttpClient来对付各种顽固的WEB服务器</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:34:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179847.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179847.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179847.html</trackback:ping><description><![CDATA[<p>一般的情况下我们都是使用IE或者Navigator浏览器来访问一个WEB服务器，用来浏览页面查看信息或者提交一些数据等等。所访问的这些页面
有的仅仅是一些普通的页面，有的需要用户登录后方可使用，或者需要认证以及是一些通过加密方式传输，例如HTTPS。目前我们使用的浏览器处理这些情况都
不会构成问题。不过你可能在某些时候需要通过程序来访问这样的一些页面，比如从别人的网页中&#8220;偷&#8221;一些数据；利用某些站点提供的页面来完成某种功能，例如
说我们想知道某个手机号码的归属地而我们自己又没有这样的数据，因此只好借助其他公司已有的网站来完成这个功能，这个时候我们需要向网页提交手机号码并从
返回的页面中解析出我们想要的数据来。如果对方仅仅是一个很简单的页面，那我们的程序会很简单，本文也就没有必要大张旗鼓的在这里浪费口舌。但是考虑到一
些服务授权的问题，很多公司提供的页面往往并不是可以通过一个简单的URL就可以访问的，而必须经过注册然后登录后方可使用提供服务的页面，这个时候就涉
及到问题的处理。我们知道目前流行的动态网页技术例如ASP、JSP无不是通过来处理会话信息的。为了使我们的程序能使用别人所提供的服务页面，就要求程
序首先登录后再访问服务页面，这过程就需要自行处理，想想当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情
啊！况且这仅仅是我们所说的顽固的WEB服务器中的一个很常见的&#8220;顽固&#8221;！再有如通过HTTP来上传文件呢？不需要头疼，这些问题有了&#8220;它&#8221;就很容易解决
了！ <br />
</p>
<p><span style="font-size: 10pt; font-family: Courier New;">我们不可能列举所
有可能的顽固，我们会针对几种最常见的问题进行处理。当然了，正如前面说到的，如果我们自己使用java.net.HttpURLConnection来
搞定这些问题是很恐怖的事情，因此在开始之前我们先要介绍一下一个开放源码的项目，这个项目就是Apache开源组织中的httpclient，它隶属于
Jakarta的commons项目，目前的版本是2.0RC2。commons下本来已经有一个net的子项目，但是又把httpclient单独提出
来，可见http服务器的访问绝非易事。</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">Commons-httpclient
项目就是专门设计来简化HTTP客户端与服务器进行各种通讯编程。通过它可以让原来很头疼的事情现在轻松的解决，例如你不再管是HTTP或者HTTPS的
通讯方式，告诉它你想使用HTTPS方式，剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时经常碰到的几个问题进
行分别介绍如何使用httpclient来解决它们，为了让读者更快的熟悉这个项目我们最开始先给出一个简单的例子来读取一个网页的内容，然后循序渐进解
决掉前进中的所有问题。</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">1． 读取网页(HTTP/HTTPS)内容</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">下面是我们给出的一个简单的例子用来访问某个页面</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">/*</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">* Created on 2003-12-14 by Liudong</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">*/</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">package http.demo;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">import java.io.IOException;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">import org.apache.commons.httpclient.*;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">import org.apache.commons.httpclient.methods.*;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">/**</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">* 最简单的HTTP客户端,用来演示通过GET或者POST方式访问某个页面</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">* @author Liudong</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">*/</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">public class SimpleClient {</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws IOException</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;{</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient client = new HttpClient();&nbsp;&nbsp;&nbsp;&nbsp;</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//设置代理服务器地址和端口&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//使用GET方法，如果服务器需要通过HTTPS连接，那只需要将下面URL中的http换成https</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpMethod method = new GetMethod("<a href="http://java.sun.com/" target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//使用POST方法</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//HttpMethod method = new PostMethod("<a href="http://java.sun.com/" target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.executeMethod(method);</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印服务器返回的状态</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(method.getStatusLine());</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印返回的信息</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(method.getResponseBodyAsString());</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//释放连接</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.releaseConnection();</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</span></p>
<p><span style="font-size: 10pt; font-family: Courier New;">在这个例子中首先创建一个
HTTP客户端(HttpClient)的实例，然后选择提交的方法是GET或者POST，最后在HttpClient实例上执行提交的方法，最后从所选
择的提交方法中读取服务器反馈回来的结果。这就是使用HttpClient的基本流程。其实用一行代码也就可以搞定整个请求的过程，非常的简单！</span></p>
<span style="font-size: 10pt; font-family: Courier New;">
<p><br />
2． 以GET或者POST方式向网页提交参数</p>
<p>其实前面一个最简单的示例中我们已经介绍了如何使用GET或者POST方式来请求一个页面，本小节与之不同的是多了提交时设定页面所需的参数，我们
知道如果是GET的请求方式，那么所有参数都直接放到页面的URL后面用问号与页面地址隔开，每个参数用&amp;隔开，例如：<a href="http://java.sun.com/?name=liudong&amp;mobile=123456" target="_blank"><span style="color: #000000;">http://java.sun.com?name=liudong&amp;mobile=123456</span></a>，但是当使用POST方法时就会稍微有一点点麻烦。本小节的例子演示向如何查询手机号码所在的城市，代码如下：</p>
<p>/*</p>
<p>* Created on 2003-12-7 by Liudong</p>
<p>*/</p>
<p>package http.demo;</p>
<p>import java.io.IOException;</p>
<p>import org.apache.commons.httpclient.*;</p>
<p>import org.apache.commons.httpclient.methods.*;</p>
<p>/**</p>
<p>* 提交参数演示</p>
<p>* 该程序连接到一个用于查询手机号码所属地的页面</p>
<p>* 以便查询号码段1330227所在的省份以及城市</p>
<p>* @author Liudong</p>
<p>*/</p>
<p>public class SimpleHttpClient {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;public static void main(String[] args) throws IOException</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;{</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpClient client = new HttpClient();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.getHostConfiguration().setHost("<a href="http://www.imobile.com.cn/" target="_blank"><span style="color: #000000;">www.imobile.com.cn</span></a>", 80, "http");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;HttpMethod method = getPostMethod();//使用POST方式提交数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.executeMethod(method);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印服务器返回的状态</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(method.getStatusLine());</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//打印结果页面</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String response =</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new String(method.getResponseBodyAsString().getBytes("8859_1"));</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //打印返回的信息</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;System.out.println(response);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;method.releaseConnection();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/**</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * 使用GET方式提交数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @return</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;private static HttpMethod getGetMethod(){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return new GetMethod("/simcard.php?simcard=1330227");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;/**</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * 使用POST方式提交数据</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; * @return</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; */</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;private static HttpMethod getPostMethod(){</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PostMethod post = new PostMethod("/simcard.php");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NamePair simcard = new NamePair("simcard","1330227");</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;post.setRequestBody(new NamePair[] { simcard});</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return post;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>}</p>
<p>在上面的例子中页面<a href="http://www.imobile.com.cn/simcard.php" target="_blank"><span style="color: #000000;">http://www.imobile.com.cn/simcard.php</span></a>需要一个参数是simcard，这个参数值为手机号码段，即手机号码的前七位，服务器会返回提交的手机号码对应的省份、城市以及其他详细信息。GET的提交方法只需要在URL后加入参数信息，而POST则需要通过NamePair类来设置参数名称和它所对应的值</p>
<p>3． 处理页面重定向</p>
<p>在JSP/Servlet编程中response.sendRedirect方法就是使用HTTP协议中的重定向机制。它与JSP中的&lt;
jsp:forward
&#8230;&gt;的区别在于后者是在服务器中实现页面的跳转，也就是说应用容器加载了所要跳转的页面的内容并返回给客户端；而前者是返回一个状态码，这些状态码
的可能值见下表，然后客户端读取需要跳转到的页面的URL并重新加载新的页面。就是这样一个过程，所以我们编程的时候就要通过
HttpMethod.getStatusCode()方法判断返回值是否为下表中的某个值来判断是否需要跳转。如果已经确认需要进行页面跳转了，那么可
以通过读取HTTP头中的location属性来获取新的地址。</p>
</span>
<img src ="http://www.blogjava.net/libin2722/aggbug/179847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:34 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons HttpClient 学习笔记(2)</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179846.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:32:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179846.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179846.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179846.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179846.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179846.html</trackback:ping><description><![CDATA[<h4>10、SSL</h4>
<br />
借助Java Secure Socket Extension
(JSSE)，HttpClient全面支持Secure Sockets Layer (SSL)或IETF Transport Layer
Security (TLS)协议上的HTTP。JSSE已经jre1.4及以后的版本中，以前的版本则需要手工安装设置，具体过程参见<a href="http://java.sun.com/products/jsse/doc/guide/API_users_guide.html#Installation" target="_blank"><span style="color: #000000;">Sun网站</span></a>或本学习笔记。<br />
HttpClient中使用SSL非常简单，参考下面两个例子: <br />
<div>HttpClient httpclient = new HttpClient();<br />
GetMethod httpget = new GetMethod("https://www.verisign.com/"); <br />
httpclient.executeMethod(httpget);<br />
System.out.println(httpget.getStatusLine().toString());</div>
，如果通过需要授权的代理，则如下： <br />
<div>HttpClient httpclient = new HttpClient();<br />
httpclient.getHostConfiguration().setProxy("myproxyhost", 8080);<br />
httpclient.getState().setProxyCredentials("my-proxy-realm", " myproxyhost",<br />
new UsernamePasswordCredentials("my-proxy-username", "my-proxy-password"));<br />
GetMethod httpget = new GetMethod("https://www.verisign.com/"); <br />
httpclient.executeMethod(httpget);<br />
System.out.println(httpget.getStatusLine().toString());</div>
<br />
在HttpClient中定制SSL的步骤如下：<br />
<br />
<ol>
    <li>提供了一个实现了
    org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory接口的
    socket factory。这个 socket
    factory负责打一个到服务器的端口，使用标准的或第三方的SSL函数库，并进行象连接握手等初始化操作。通常情况下，这个初始化操作在端口被创建时
    自动进行的。<br />
    <br />
    </li>
    <li>实例化一个org.apache.commons.httpclient.protocol.Protocol对象。创建这个实例时，需要一个合法的协议类型(如https)，一个定制的socket factory，和一个默认的端中号(如https的443端口). <br />
    <div>Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);</div>
    然后，这个实例可被设置为协议的处理器。 <br />
    <div>HttpClient httpclient = new HttpClient();<br />
    httpclient.getHostConfiguration().setHost("www.whatever.com", 443, myhttps);<br />
    GetMethod httpget = new GetMethod("/");<br />
    httpclient.executeMethod(httpget);</div>
    </li>
    <li>通过调用Protocol.registerProtocol方法，将此定制的实例，注册为某一特定协议的默认的处理器。由此，可以很方便地定制自己的协议类型(如myhttps)。 <br />
    <div>Protocol.registerProtocol("myhttps", <br />
    new Protocol("https", new MySSLSocketFactory(), 9443));<br />
    ...<br />
    HttpClient httpclient = new HttpClient();<br />
    GetMethod httpget = new GetMethod("my<a href="https://www.whatever.com/" target="_blank"><span style="color: #000000;">https://www.whatever.com/</span></a>");<br />
    httpclient.executeMethod(httpget);</div>
    如果想用自己定制的处理器取代https默认的处理器，只需要将其注册为"https"即可。 <br />
    <div>Protocol.registerProtocol("https", <br />
    new Protocol("https", new MySSLSocketFactory(), 443));<br />
    HttpClient httpclient = new HttpClient();<br />
    GetMethod httpget = new GetMethod("https://www.whatever.com/");<br />
    httpclient.executeMethod(httpget);</div>
    </li>
</ol>
<br />
已知的限制和问题<br />
<br />
<ol>
    <li>持续的SSL连接在Sun的低于1.4JVM上不能工作，这是由于JVM的bug造成。<br />
    <br />
    </li>
    <li>通过代理访问服务器时，非抢先认证（ Non-preemptive authentication）会失败，这是由于HttpClient的设计缺陷造成的，以后的版本中会修改。</li>
</ol>
<br />
遇到问题的处理<br />
很多问题，特别是在jvm低于1.4时，是由jsse的安装造成的。<br />
下面的代码，可作为最终的检测手段。<br />
<br />
<div>import java.io.BufferedReader;<br />
import java.io.InputStreamReader;<br />
import java.io.OutputStreamWriter;<br />
import java.io.Writer;<br />
import java.net.Socket; import javax.net.ssl.SSLSocketFactory; public class Test {<br />
<br />
public static final String TARGET_HTTPS_SERVER = "www.verisign.com"; <br />
public static final int TARGET_HTTPS_PORT = 443; <br />
<br />
public static void main(String[] args) throws Exception {<br />
<br />
Socket socket = SSLSocketFactory.getDefault().<br />
createSocket(TARGET_HTTPS_SERVER, TARGET_HTTPS_PORT);<br />
try {<br />
Writer out = new OutputStreamWriter(<br />
socket.getOutputStream(), "ISO-8859-1");<br />
out.write("GET / HTTP/1.1"r"n"); <br />
out.write("Host: " + TARGET_HTTPS_SERVER + ":" + <br />
TARGET_HTTPS_PORT + ""r"n"); <br />
out.write("Agent: SSL-TEST"r"n"); <br />
out.write(""r"n"); <br />
out.flush(); <br />
BufferedReader in = new BufferedReader(<br />
new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));<br />
String line = null;<br />
while ((line = in.readLine()) != null) {<br />
System.out.println(line);<br />
}<br />
} finally {<br />
socket.close(); <br />
}<br />
}<br />
}</div>
<br />
<br />
<h4>11、httpclient的多线程处理</h4>
<br />
使用多线程的主要目的，是为了实现并行的下载。在httpclient运行的过程
中，每个http协议的方法，使用一个HttpConnection实例。由于连接是一种有限的资源，每个连接在某一时刻只能供一个线程和方法使用，所以
需要确保在需要时正确地分配连接。HttpClient采用了一种类似jdbc连接池的方法来管理连接，这个管理工作由
MultiThreadedHttpConnectionManager完成。 <br />
<div>MultiThreadedHttpConnectionManager connectionManager = <br />
new MultiThreadedHttpConnectionManager();<br />
HttpClient client = new HttpClient(connectionManager);</div>
此
是，client可以在多个线程中被用来执行多个方法。每次调用HttpClient.executeMethod()
方法，都会去链接管理器申请一个连接实例，申请成功这个链接实例被签出(checkout)，随之在链接使用完后必须归还管理器。管理器支持两个设置：
<br />
<table border="1">
    <tbody>
        <tr>
            <td>maxConnectionsPerHost</td>
            <td>每个主机的最大并行链接数，默认为2</td>
        </tr>
        <tr>
            <td>maxTotalConnections</td>
            <td>客户端总并行链接最大数，默认为20</td>
        </tr>
    </tbody>
</table>
<br />
管理器重新利用链接时，采取早归还者先重用的方式（least recently used approach）。<br />
由于是使用HttpClient的程序而不是HttpClient本身来读取应答包的主体，所以HttpClient无法决定什么时间连接不再使用了，这也就要求在读完应答包的主体后必须手工显式地调用releaseConnection()来释放申请的链接。 <br />
<div>MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();<br />
HttpClient client = new HttpClient(connectionManager);<br />
...<br />
// 在某个线程中。<br />
GetMethod get = new GetMethod("http://jakarta.apache.org/");<br />
try {<br />
client.executeMethod(get);<br />
// print response to stdout<br />
System.out.println(get.getResponseBodyAsStream());<br />
} finally {<br />
// be sure the connection is released back to the connection <br />
// manager<br />
get.releaseConnection();<br />
}</div>
对每一个HttpClient.executeMethod须有一个method.releaseConnection()与之匹配. <br />
<h4>12、HTTP方法</h4>
<br />
HttpClient支持的HTTP方法有8种，下面分述之。<br />
<br />
1、Options<br />
<br />
HTTP方法Options用来向服务器发送请求，希望获得针对由请求URL(request
url)标志的资源在请求/应答的通信过程可以使用的功能选项。通过这个方法，客户端可以在采取具体行动之前，就可对某一资源决定采取什么动作和/或以及
一些必要条件，或者了解服务器提供的功能。这个方法最典型的应用，就是用来获取服务器支持哪些HTTP方法。<br />
HttpClient中有一个类叫OptionsMethod，来支持这个HTTP方法，利用这个类的getAllowedMethods方法，就可以很简单地实现上述的典型应用。<br />
<br />
<div>OptionsMethod options = new OptionsMethod("http://jakarta.apache.org");<br />
// 执行方法并做相应的异常处理<br />
...<br />
Enumeration allowedMethods = options.getAllowedMethods();<br />
options.releaseConnection();</div>
<br />
2、Get<br />
<br />
HTTP方法GET用来取回请求URI（request-URI）标志的任何信息（以实体(entity)的形式），"get"这个单词本意就是&#8221;获取
&#8220;的意思。如果请求URI指向的一个数据处理过程，那这个过程生成的数据，在应答中以实体的形式被返回，而不是将这个过程的代码的返回。<br />
如果
HTTP包中含有If-ModifiedSince, If-Unmodified-Since, If-Match, If-None-Match,
或
If-Range等头字段，则GET也就变成了&#8221;条件GET&#8220;，即只有满足上述字段描述的条件的实体才被取回，这样可以减少一些非必需的网络传输，或者减
少为获取某一资源的多次请求（如第一次检查，第二次下载）。（一般的浏览器，都有一个临时目录，用来缓存一些网页信息，当再次浏览某个页面的时候，只下载
那些修改过的内容，以加快浏览速度，就是这个道理。至于检查，则常用比GET更好的方法HEAD来实现。）如果HTTP包中含有Range头字段，那么请
求URI指定的实体中，只有决定范围条件的那部分才被取回来。（用过多线程下载工具的朋友，可能比较容易理解这一点）<br />
这个方法的典型应用，用
来从web服务器下载文档。HttpClient定义了一个类叫GetMethod来支持这个方法，用GetMethod类中
getResponseBody, getResponseBodyAsStream 或
getResponseBodyAsString函数就可以取到应答包包体中的文档（如HTML页面）信息。这这三个函数中，
getResponseBodyAsStream通常是最好的方法，主要是因为它可以避免在处理下载的文档之前缓存所有的下载的数据。<br />
<br />
<div>GetMethod get = new GetMethod("http://jakarta.apache.org");<br />
// 执行方法，并处理失败的请求.<br />
...<br />
InputStream in = get.getResponseBodyAsStream();<br />
// 利用输入流来处理信息。<br />
get.releaseConnection();</div>
<br />
对GetMethod的最常见的不正确的使用，是没有将全部的应答主体的数据读出来。还有，必须注意要手工明确地将链接释放。<br />
<br />
3、Head<br />
<br />
HTTP的Head方法，与Get方法完全一致，唯一的差别是服务器不能在应答包中包含主体(message-body)，而且一定不能包含主体。使用
这个方法，可以使得客户无需将资源下载回就可就以得到一些关于它的基本信息。这个方法常用来检查超链的可访问性以及资源最近有没有被修改。<br />
HTTP的head方法最典型的应用，是获取资源的基本信息。HttpClient定义了HeadMethod类支持这个方法，HeadMethod类与其它*Method类一样，用 getResponseHeaders()取回头部信息，而没有自己的特殊方法。<br />
<br />
<div>HeadMethod head = new HeadMethod("http://jakarta.apache.org");<br />
// 执行方法，并处理失败的请求.<br />
...<br />
// 取回应答包的头字段信息.<br />
Header[] headers = head.getResponseHeaders(); // 只取回最后修改日期字段的信息.<br />
String lastModified = head.getResponseHeader("last-modified").get();</div>
<br />
<br />
4、Post<br />
<br />
Post在英文有&#8220;派驻&#8221;的意思，HTTP方法POST就是要求服务器接受请求包中的实体，并将其作为请求URI的下属资源。从本质上说，这意味着服务
器要保存这个实体信息，而且通常由服务器端的程序进行处理。Post方法的设计意图，是要以一种统一的方式实现下列功能： <br />
<ol>
    <li>对已有的资源做评注<br />
    <br />
    </li>
    <li>将信息发布到BBS、新闻组、邮件列表，或类似的文章组中<br />
    <br />
    </li>
    <li>将一块数据，提交给数据处理进程<br />
    <br />
    </li>
    <li>通过追加操作，来扩展一个数据库</li>
</ol>
这些都操作期待着在服务器端产生一定的&#8220;副作用&#8221;，如修改了数据库等。<br />
HttpClient定义PostMethod类以支持该HTTP方法，在httpclient中，使用post方法有两个基本的步骤：为请求包准备数
据，然后读取服务器来的应答包的信息。通过调用
setRequestBody()函数，来为请求包提供数据，它可以接收三类参数：输入流、名值对数组或字符串。至于读取应答包需要调用
getResponseBody* 那一系列的方法，与GET方法处理应答包的方法相同。<br />
常见问题是，没有将全部应答读取（无论它对程序是否有用），或没有释放链接资源。<br />
<br />
<h4>参考资料：</h4>
<a href="http://www.systinet.com/doc/wasp_uddi/uddi/igpreliminary.html" target="_blank"><span style="color: #000000;">http://www.systinet.com/doc/wasp_uddi/uddi/igpreliminary.html</span></a>
<img src ="http://www.blogjava.net/libin2722/aggbug/179846.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:32 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179846.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons HttpClient 学习笔记(1)</title><link>http://www.blogjava.net/libin2722/archive/2008/02/13/179845.html</link><dc:creator>礼物</dc:creator><author>礼物</author><pubDate>Wed, 13 Feb 2008 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/libin2722/archive/2008/02/13/179845.html</guid><wfw:comment>http://www.blogjava.net/libin2722/comments/179845.html</wfw:comment><comments>http://www.blogjava.net/libin2722/archive/2008/02/13/179845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/libin2722/comments/commentRss/179845.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/libin2722/services/trackbacks/179845.html</trackback:ping><description><![CDATA[虽然用telnet这样的程序都可把页面取回来，但是在与web服务器的交互中，如果涉及或https或ssl等内容，一般功能相对完备的http客户端
还是非常必要的。IE或NetScape等浏览器确实不错，可是如果为实现持续互动而在程序调用浏览器，我个人认为其中的工作量还是不小的，这还没考虑版
权问题。最好的办法，就是能有一个开源的包，能实现http客户端的功能，供我们开发的程序调用。<a href="http://jakarta.apache.org/commons/httpclient/" target="_blank"><span style="color: #000000;">httpclient</span></a>就是这么一个包，我相信可能有比它的实现更好的，但目前我只关注这个。：）<br />
下面是nogoop做的功能比较表：<br />
<br />
<table border="1" cellpadding="4" cellspacing="1">
    <tbody>
        <tr>
            <td>Features</td>
            <td>nogoop</td>
            <td>Sun JRE &lt; 1.4.2</td>
            <td>Sun JRE 1.4.2</td>
            <td>Innovation</td>
            <td>Apache/Jakarta</td>
        </tr>
        <tr>
            <td>s</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>plug compatible</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>[partial]</td>
        </tr>
        <tr>
            <td>true request output stream</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>true response input stream</td>
            <td>X</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>connection keep alive</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>connection pool throttling</td>
            <td>X</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
        </tr>
        <tr>
            <td>connection/request timeout</td>
            <td>X</td>
            <td><br />
            </td>
            <td>X [uns]</td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>idle connection timeout</td>
            <td>X</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
        </tr>
        <tr>
            <td>pipelining of requests</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>alternate DNS resolution (dnsjava)</td>
            <td>X</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td><br />
            </td>
        </tr>
        <tr>
            <td>SSL</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>basic authentication</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>digest authentication</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>NTLM authentication</td>
            <td>X</td>
            <td><br />
            </td>
            <td>[Windows only]</td>
            <td><br />
            </td>
            <td>X</td>
        </tr>
        <tr>
            <td>proxy authentication</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>minimum JRE version</td>
            <td>1.2</td>
            <td>1</td>
            <td>01年4月2日</td>
            <td>1.2</td>
            <td>1.2</td>
        </tr>
        <tr>
            <td>price</td>
            <td>$499</td>
            <td>free</td>
            <td>free</td>
            <td>free</td>
            <td>free</td>
        </tr>
        <tr>
            <td>source available</td>
            <td>X</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>diagnostic tracing</td>
            <td>X</td>
            <td><br />
            </td>
            <td><br />
            </td>
            <td>X</td>
            <td>X</td>
        </tr>
        <tr>
            <td>actively supported</td>
            <td>X</td>
            <td>X</td>
            <td>X</td>
            <td><br />
            </td>
            <td>X</td>
        </tr>
        <tr>
            <td>fix turnaround</td>
            <td>fast</td>
            <td>slow</td>
            <td>slow</td>
            <td>none</td>
            <td>medium</td>
        </tr>
        <tr>
            <td>license</td>
            <td>purchase</td>
            <td>Sun JRE</td>
            <td>Sun JRE</td>
            <td>LGPL</td>
            <td>Apache</td>
        </tr>
    </tbody>
</table>
<h4>1、HttpClient的功能</h4>
<ol>
    <li>基于标准，纯正java，实现了http1.0和1.1。<br />
    <br />
    </li>
    <li>在一个可扩展的OO框架内，实现了HTTP的全部方法(GET, POST, <br />
    PUT, DELETE, HEAD, OPTIONS, and TRACE)<br />
    <br />
    </li>
    <li>支持HTTPS(ssl上的HTTP)的加密操作<br />
    <br />
    </li>
    <li>透明地穿过HTTP代理建立连接<br />
    <br />
    </li>
    <li>通过CONNECT方法，利用通过建立穿过HTTP代理的HTTPS连接<br />
    <br />
    </li>
    <li>利用本地Java socket，透明地穿过SOCKS(版本5和4）代理建立连接<br />
    <br />
    </li>
    <li>支持利用Basic、Digest和NTLM加密的认证<br />
    <br />
    </li>
    <li>支持用于上传大文件的Multi-Part表单POST方法<br />
    <br />
    </li>
    <li>插件式安全socket实现，易于使用第三方的解决方案<br />
    <br />
    </li>
    <li>连接管理，支持多线程应用，支持设定单个主机总连接和最高连接数量,自动检测和关闭失效连接<br />
    <br />
    </li>
    <li>直接将请求信息流送到服务器的端口<br />
    <br />
    </li>
    <li>直接读取从服务器的端口送出的应答信息<br />
    <br />
    </li>
    <li>支持HTTP/1.0中用KeepAlive和HTTP/1.1中用persistance设置的持久连接<br />
    <br />
    </li>
    <li>直接访问由服务器送出的应答代码和头部信息<br />
    <br />
    </li>
    <li>可设置连接超时时间 <br />
    </li>
    <li>
    <br />
    </li>
    <li>HttpMethods 实现Command Pattern，以允许并行请求或高效连接复用<br />
    <br />
    </li>
    <li>遵循the Apache Software License协议，源码免费可得 <br />
    </li>
</ol>
<h4>2、预备工作</h4>
<br />
对jre1.3.*，如果要HttpClient支持https，则需要下载并安装<a href="http://java.sun.com/products/jsse/" target="_blank"><span style="color: #000000;">jsse</span></a>和<a href="http://java.sun.com/products/jce/" target="_blank"><span style="color: #000000;">jce</span></a>.安装的步骤如下：<br />
1)下载jsse和jce.<br />
2)检查CLASSPATH中没有与jsse和jce相关的jar包<br />
3)将 US_export_policy.jar、local_policy.jar、jsse.jar、jnet.jar、jce1_2_x.jar、sunjce_provider.jar、jcert.jar复制到目录：<br />
UNIX:$JDK_HOME/jre/lib/ext<br />
Windows:%JDK_HOME%"jre"lib"ext<br />
4)修改下述目录下的java.security文件。<br />
UNIX:$JDK_HOME/jre/lib/security/<br />
Windows:%JDK_HOME%"jre"lib"security"<br />
5) <br />
<div>将<br />
#<br />
# List of providers and their preference orders:<br />
#<br />
security.provider.1=sun.security.provider.Sun<br />
security.provider.2=com.sun.rsajca.Provider<br />
改为：<br />
#<br />
# List of providers and their preference orders:<br />
#<br />
security.provider.1=com.sun.crypto.provider.SunJCE<br />
security.provider.2=sun.security.provider.Sun<br />
security.provider.3=com.sun.rsajca.Provider<br />
security.provider.4=com.sun.net.ssl.internal.ssl.Provider</div>
<br />
HttpClient还要求安装commons-logging，下面跟httpclient一块安装。<br />
<br />
<h4>3、取得源码</h4>
<div>cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login<br />
password: anoncvs<br />
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/logging<br />
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/httpclient</div>
<br />
编译： <br />
<div>cd jakarta-commons/logging<br />
ant dist<br />
cp dis/*.jar ../httpclient/lib/<br />
cd ../httpclient<br />
ant dist</div>
<h4>4、使用HttpClient编程的基本步聚</h4>
<ol>
    <li>创建 HttpClient 的一个实例.<br />
    <br />
    </li>
    <li>创建某个方法（DeleteMethod，EntityEnclosingMethod，ExpectContinueMethod，
    GetMethod，HeadMethod，MultipartPostMethod，OptionsMethod，PostMethod，
    PutMethod，TraceMethod）的一个实例，一般可用要目标URL为参数。<br />
    <br />
    </li>
    <li>让 HttpClient 执行这个方法.<br />
    <br />
    </li>
    <li>读取应答信息.<br />
    <br />
    </li>
    <li>释放连接.<br />
    <br />
    </li>
    <li>处理应答.<br />
    </li>
</ol>
<br />
在执行方法的过程中，有两种异常，一种是HttpRecoverableException，表示偶然性错误发生，一般再试可能成功，另一种是IOException，严重错误。<br />
这儿有这个教程中的一个例程，可以<a href="http://hedong.3322.org/archives/docs/HttpClientTutorial.java" target="_blank"><span style="color: #000000;">下载</span></a>。 <br />
<h4>5、认证</h4>
<br />
HttpClient三种不同的认证方案: Basic, Digest and NTLM. 这些方案可用于服务器或代理对客户端的认证，简称服务器认证或代理认证。<br />
1)服务器认证(Server Authentication)<br />
HttpClient处理服务器认证几乎是透明的，仅需要开发人员提供登录信息(login
credentials)。登录信息保存在HttpState类的实例中，可以通过 setCredentials(String realm,
Credentials cred)和getCredentials(String
realm)来获取或设置。注意，设定对非特定站点访问所需要的登录信息，将realm参数置为null.
HttpClient内建的自动认证，可以通过HttpMethod类的setDoAuthentication(boolean
doAuthentication)方法关闭，而且这次关闭只影响HttpMethod当前的实例。<br />
抢先认证(Preemptive Authentication)可以通过下述方法打开. <br />
<div>client.getState().setAuthenticationPreemptive(true);</div>
在这种模式时，HttpClient会主动将basic认证应答信息传给服务器，即使在某种情况下服务器可能返回认证失败的应答，这样做主要是为了减少连接的建立。为使每个新建的 HttpState实例都实行抢先认证，可以如下设置系统属性。 <br />
<div>setSystemProperty(Authenticator.PREEMPTIVE_PROPERTY, "true");</div>
<br />
Httpclient实现的抢先认证遵循rfc2617.<br />
2)代理认证(proxy authentication)<br />
除了登录信息需单独存放以外，代理认证与服务器认证几乎一致。用 setProxyCredentials(String realm, Credentials cred)和 getProxyCredentials(String realm)设、取登录信息。<br />
3)认证方案(authentication schemes)<br />
Basic<br />
是HTTP中规定最早的也是最兼容(?)的方案，遗憾的是也是最不安全的一个方案，因为它以明码传送用户名和密码。它要求一个UsernamePasswordCredentials实例，可以指定服务器端的访问空间或采用默认的登录信息。<br />
Digest<br />
是在HTTP1.1中增加的一个方案，虽然不如Basic得到的软件支持多，但还是有广泛的使用。Digest方案比Basic方案安全得多，因它根本
就不通过网络传送实际的密码，传送的是利用这个密码对从服务器传来的一个随机数(nonce)的加密串。它要求一个
UsernamePasswordCredentials实例，可以指定服务器端的访问空间或采用默认的登录信息。<br />
NTLM<br />
这是
HttpClient支持的最复杂的认证协议。它M$设计的一个私有协议，没有公开的规范说明。一开始由于设计的缺陷，NTLM的安全性比Digest
差，后来经过一个ServicePack补丁后，安全性则比较Digest高。NTLM需要一个NTCredentials实例.
注意，由于NTLM不使用访问空间(realms)的概念，HttpClient利用服务器的域名作访问空间的名字。还需要注意，提供给
NTCredentials的用户名，不要用域名的前缀 - 如: "adrian" 是正确的，而 "DOMAIN"adrian" 则是错的.<br />
NTLM认证的工作机制与basic和digest有很大的差别。这些差别一般由HttpClient处理，但理解这些差别有助避免在使用NTLM认证时出现错误。<br />
<br />
<ol>
    <li>从HttpClientAPI的角度来看，NTLM与其它认证方式一样的工作，差别是需要提供'NTCredentials'实例而不是'UsernamePasswordCredentials'(其实，前者只是扩展了后者)<br />
    <br />
    </li>
    <li>对NTLM认证，访问空间是连接到的机器的域名，这对多域名主机会有一些麻烦.只有HttpClient连接中指定的域名才是认证用的域名。建议将realm设为null以使用默认的设置。<br />
    <br />
    </li>
    <li>NTLM只是认证了一个连接而不是一请求，所以每当一个新的连接建立就要进行一次认证，且在认证的过程中保持连接是非常重要的。 因此，NTLM不能同时用于代理认证和服务器认证，也不能用于http1.0连接或服务器不支持持久连接的情况。</li>
</ol>
<h4>6、重定向</h4>
<br />
由于技术限制，以及为保证2.0发布版API的稳定，HttpClient还不能自动处重定向，但对重定向到同一主机、同一端口且采用同一协议的情况HttpClient可以支持。不能自动的处理的情况，包括需要人工交互的情况，或超出httpclient的能力。<br />
当服务器重定向指令指到不同的主机时，HttpClient只是简单地将重定向状态码作为应答状态。所有的300到399（包含两端）的返回码，都表示是重定向应答。常见的有：<br />
<br />
<ol>
    <li>301 永久移动. HttpStatus.SC_MOVED_PERMANENTLY<br />
    <br />
    </li>
    <li>302 临时移动. HttpStatus.SC_MOVED_TEMPORARILY<br />
    <br />
    </li>
    <li>303 See Other. HttpStatus.SC_SEE_OTHER<br />
    <br />
    </li>
    <li>307 临时重定向. HttpStatus.SC_TEMPORARY_REDIRECT</li>
</ol>
<br />
当收到简单的重定向时，程序应从HttpMethod对象中抽取新的URL并将其下载。另外,限制一下重定向次数是个好的主意，这可以避免递归循环。新的URL可以从头字段Location中抽取，如下： <br />
<div>String redirectLocation;<br />
Header locationHeader = method.getResponseHeader("location");<br />
if (locationHeader != null) {<br />
redirectLocation = locationHeader.get();<br />
} else {<br />
// The response is invalid and did not provide the new location for<br />
// the resource. Report an error or possibly handle the response<br />
// like a 404 Not Found error.<br />
}</div>
<br />
特殊重定向：<br />
<br />
<ol>
    <li>300 多重选择. HttpStatus.SC_MULTIPLE_CHOICES<br />
    <br />
    </li>
    <li>304 没有改动. HttpStatus.SC_NO T_MODIFIED<br />
    <br />
    </li>
    <li>305 使用代理. HttpStatus.SC_USE_PROXY <br />
    </li>
</ol>
<br />
<h4>7、字符编码(character encoding)</h4>
<br />
一个HTTP协议的请求或应答的头部(在http协议中，数据包分
为两部分，一部分是头部，由一些名值对构成，一部分是主体(body)，是真正传办理的数据（如HTML页面等）），必须以US-ASCII编码，这是因
为头部不传数据而只描述被要传输的数据的一些信息，一个例外是，它是数据但是通过头部进行传输的，所以它也要用US-ASCII编码。<br />
HTTP数据包的主体部分，可以用任何一种方式进行编码，默认是ISO-8859-1，具体可以用头部字段Content-Type指定。可以利用
addRequestHeader方法，设定编码方式；用
getResponseCharSet取得编码方式。对HTML或XML等类型的文档，它们的本身的Content-Type也可以指定编码方式，主要区
分两者的作用范围以得到正确实的解码。<br />
URL的编码标准，由RFC1738指定为，只能是由可打印8位/字节的us-ascii字符组成，80-ff不是us-ascii字符，而00-1F是控制字符，这两个区域中用的字符都须加以编码(encoded)。<br />
<br />
<h4>8、s</h4>
<br />
HttpClient能自动管理,包括允许服务器设置并在需要的时候自动将返回服务器，它也支持手工设置后发送到服务器端。不幸的是，对如何处理，有几个
规范互相冲突：Netscape 草案, RFC2109, RFC2965，而且还有很大数量的软件商的实现不遵循任何规范.
为了处理这种状况，HttpClient提供了策略驱动的管理方式。HttpClient支持的规范有： <br />
<ol>
    <li><a>Netscape 草案</a>，是最早的规范，基于rfc2109。尽管这个规范与rc2109有较大的差别，这样做可以与一些服务器兼容。 <br />
    <br />
    </li>
    <li><a href="http://www.w3.org/Protocols/rfc2109/rfc2109.txt" target="_blank"><span style="color: #000000;">rfc2109</span></a>，
    是w3c发布的第一个官方规范。理论上讲，所有的服务器在处理(版本1)时，都要遵循此规范，正因如此，HttpClient将其设为默认的规范。遗憾的
    是，这个规范太严格了，以致很多服务器不正确的实施了该规范或仍在作用Netscape规范。在这种情况下，应使用兼容规范。<br />
    <br />
    </li>
    <li>兼容性规范，设计用来兼容尽可能多的服务器，即使它们并没有遵循标准规范。当解析出现问题时，应考虑采用兼容性规范。</li>
</ol>
<br />
RFC2965规范暂时没有被HttpClient支持（在以后的版本为会加上），它定义了版本2，并说明了版本1的不足，RFC2965有意有久取代rfc2109.<br />
在HttpClient中，有两种方法来指定规范的使用， <br />
<ol>
    <li>
    <div>HttpClient client = new HttpClient();<br />
    client.getState().setPolicy(Policy.COMPATIBILITY);</div>
    这种方法设置的规范只对当前的HttpState有效，参数可取值Policy.COMPATIBILITY，Policy.NETSCAPE_DRAFT或Policy.RFC2109。<br />
    <br />
    </li>
    <li>
    <div>System.setProperty("apache.commons.httpclient.spec", "COMPATIBILITY");</div>
    此法指的规范，对以后每个新建立的HttpState对象都有效，参数可取值"COMPATIBILITY","NETSCAPE_DRAFT"或"RFC2109"。<br />
    常有不能解析的问题，但更换到兼容规范大都能解决。<br />
    </li>
</ol>
<br />
<h4>9、使用HttpClient遇到问题怎么办?</h4>
<ol>
    <li>用一个浏览器访问服务器，以确认服务器应答正常<br />
    <br />
    </li>
    <li>如果在使代理，关掉代理试试<br />
    <br />
    </li>
    <li>另找一个服务器来试试（如果运行着不同的服务器软件更好）<br />
    <br />
    </li>
    <li>检查代码是否按教程中讲的思路编写<br />
    <br />
    </li>
    <li>设置log级别为debug，找出问题出现的原因<br />
    <br />
    </li>
    <li>打开wiretrace，来追踪客户端与服务器的通信，以确实问题出现在什么地方<br />
    <br />
    </li>
    <li>用telnet或netcat手工将信息发送到服务器，适合于猜测已经找到了原因而进行试验时<br />
    <br />
    </li>
    <li>将netcat以监听方式运行，用作服务器以检查httpclient如何处理应答的。<br />
    <br />
    </li>
    <li>利用最新的httpclient试试，bug可能在最新的版本中修复了<br />
    <br />
    </li>
    <li>向邮件列表求帮助<br />
    <br />
    </li>
    <li>向bugzilla报告bug.</li>
</ol>
<img src ="http://www.blogjava.net/libin2722/aggbug/179845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/libin2722/" target="_blank">礼物</a> 2008-02-13 22:23 <a href="http://www.blogjava.net/libin2722/archive/2008/02/13/179845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>