??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲高清在线观看,亚洲av无码片vr一区二区三区,亚洲午夜精品一级在线播放放 http://m.tkk7.com/libin2722/category/29422.html快乐学习Q快乐工?/description>zh-cnWed, 13 Feb 2008 17:52:16 GMTWed, 13 Feb 2008 17:52:16 GMT60整理一个ANT在J2EE目中的应用http://m.tkk7.com/libin2722/archive/2008/02/13/179856.htmlC物C物Wed, 13 Feb 2008 14:59:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179856.htmlhttp://m.tkk7.com/libin2722/comments/179856.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179856.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179856.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179856.html首先Q假设我们的目的结构如?${project.root}
  |
  +-- build/           <-- WAR/EAR档的目录
  +-- classes/         <-- ~译的输出目录,与JBuilder兼容
  +-- src/             <-- Java源文件目?br />   +-- web/             <-- WEB Content 目录
  |    |
  |    +--pages/       <-- JSP 文g目录
  |    +--WEB-INF/     <-- web.xml {配|文?br />   +-- ejb              <-- EJB Content 目录
  |    |
  |    +---INF/    <-- EJB 配置文g
  +-- ear              <-- EAR Content 目录
  |    |
  |    +---INF/    <-- EAR 配置文g
  |-- lib              <-- 目所要用到的library

接下来第一步,是要先定义好一些全局的参敎ͼ以便以后更改h方便Q风?br /> 大家自己选择好了Q我用的是如下的方式Q?/span>

(1) l出目的目录:
  <!--// project directories //--><property name="dir.project" ="D:/Code/MyProject"/><property name="dir.project.lib" ="${dir.project}/lib"/><property name="dir.project.src" ="${dir.project}/src"/><property name="dir.project.web_module" ="${dir.project}/web"/><property name="dir.project.ejb_module" ="${dir.project}/ejb"/><property name="dir.project.ear_module" ="${dir.project}/ear"/><!--// compile, build and deploy directories //--><property name="dir.project.compile" ="${dir.project}/classes"/><property name="dir.project.compile.jspcache" ="${dir.project.compile}/jspcache"/><property name="dir.project.build" ="${dir.project}/build"/><!--// J2EE Container //--><property name="dir.appserver.tomcat.home" ="D:/J2EE_HOME/AppServer/Tomcat"/><property name="dir.appserver.oc4j.j2ee.home" ="D:/J2EE_HOME/AppServer/OC4J/j2ee/home"/>
 

(2) 定义Java Source的编译选项
<!--// Java compiler options //--> <property name="opt.compile.source" ="1.4"/><property name="opt.compile.target" ="1.4"/><property name="opt.compile.encoding" ="UTF-8"/><property name="opt.compile.deprecation" ="on"/><property name="opt.compile.debug" ="on"/><property name="opt.compile.optimize" ="off"/>
 

(3) 如果需?import EJB library 的话Q给Z面的定义Q后面会用到
    <!--// EJB imported resource //--><property name="import.ejb.report.server" ="${dir.project.lib}/Appwork.jar"/>
 

(4) l出部vWAR/EAR文g的名Uͼ
  <!--// Deployment //--><property name="deploy.file.ejb_module" ="MyApp_EJB.jar" /><property name="deploy.file.web_module" ="MyApp_WEB.war" /><property name="deploy.file.ear_module" ="MyApp.ear" />
 

(5) l出CLASSPATH的定义,引入相关的Library和项目编译生成的Java Classes
  <path id="CLASSPATH"><!--// Tomcat Libraries //--><fileset dir="${dir.appserver.tomcat.home}/bin"> <include name="*.jar"/></fileset> <fileset dir="${dir.appserver.tomcat.home}/server/lib"> <include name="*.jar"/> </fileset> <fileset dir="${dir.appserver.tomcat.home}/common/lib"> <include name="*.jar"/> </fileset> <!--// Depended Libraries //--><pathelement location="${dir.project.lib}/abc.jar"/><pathelement location="${dir.project.lib}/AppServer.jar"/><pathelement location="${dir.project.lib}/AppServiceClient.jar"/><pathelement location="${dir.project.lib}/AppUtil.jar"/><pathelement location="${dir.project.lib}/xport.jar"/><pathelement location="${dir.project.lib}/jaxen-full.jar"/><pathelement location="${dir.project.lib}/jstl.jar"/><pathelement location="${dir.project.lib}/log4j-1.2.13.jar"/><pathelement location="${dir.project.lib}/ojdbc14.jar"/><pathelement location="${dir.project.lib}/saxpath.jar"/><pathelement location="${dir.project.lib}/standard.jar"/><pathelement location="${dir.project.lib}/taglibs-log.jar"/><!--// Project classes //--><pathelement location="${dir.project.compile}"/></path>
 

(6) 基本的clean和init的task
  <target name="clean"><delete dir="${dir.project.build}"/><delete dir="${dir.project.compile.jspcache}"/><delete dir="${dir.project.compile}"/><delete dir="${dir.project.web_module}/WEB-INF/classes"/><delete dir="${dir.project.web_module}/WEB-INF/lib"/></target><target name="init"><mkdir dir="${dir.project.compile}"/><mkdir dir="${dir.project.compile.jspcache}"/><mkdir dir="${dir.project.web_module}/WEB-INF/classes"/><mkdir dir="${dir.project.web_module}/WEB-INF/lib"/><mkdir dir="${dir.project.build}"/></target>
 

(7) ~译Java Source
<target name="src_compile" depends="init"><!--// compile the Java source //--><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}" ><classpath refid="CLASSPATH"/><include name="**/*.java"/></javac><!--// copy the classpath resources //--><copy todir="${dir.project.compile}"><fileset dir="${dir.project.src}"><exclude name="**/*.java"/></fileset></copy> </target>
 

(8) 预编译JSP文gQ可选择ZTomcat或是Oracle Application Server
  <!--// for Tomcat //--> <target name="jsp_src_generate" depends="src_compile"><taskdef classname="org.apache.jasper.JspC" name="jasper2"><classpath refid="CLASSPATH"/> </taskdef><jasper2 validateXml="false" verbose="9"uriroot="${dir.project.web_module}" outputDir="${dir.project.compile.jspcache}" webXmlFragment="${dir.project.compile.jspcache}/generated-web.xml" /> </target><target name="jsp_src_compile"><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}" ><classpath refid="CLASSPATH"/><include name="**"/></javac></target><target name="jsp_precompile" depends="src_compile, jsp_src_generate, jsp_src_compile" />
 

(9) 开始进行compileQmake ?buildQƈ生成部v档案
  <target name="compile" depends="src_compile, jsp_precompile" /><!--// Build WAR file //--><target name="make.web_module" depends="compile"><war destfile="${dir.project.build}/${deploy.file.web_module}" webxml="${dir.project.web_module}/WEB-INF/web.xml"><fileset dir="${dir.project.web_module}" ><include name="**"/><exclude name="WEB-INF/classes/**"/><exclude name="WEB-INF/lib/**"/></fileset><classes dir="${dir.project.compile}"><include name="**"/><exclude name="project/package/trx/**"/><exclude name="jspcache/**"/></classes><lib dir="${dir.project.lib}"><include name="AppUtil.jar"/><include name="AppClient.jar"/></lib></war></target><!--// Build EJB Jar file //--><target name="make.ejb_module" depends="src_compile"><jar destfile="${dir.project.build}/${deploy.file.ejb_module}"><zipgroupfileset dir="${dir.project.lib}"><include name="AppServer.jar"/></zipgroupfileset><fileset dir="${dir.project.ejb_module}"><include name="**"/></fileset><fileset dir="${dir.project.compile}"><include name="**"/><exclude name="project/package/controller/**"/><exclude name="jspcache/**"/></fileset></jar></target><!--// Build EAR file //--><target name="make.ear_module" depends="compile, make.web_module, make.ejb_module"><ear destfile="${dir.project.build}/${deploy.file.ear_module}" appxml="${dir.project.ear_module}/-INF/application.xml"><fileset dir="${dir.project.build}"><include name="${deploy.file.web_module}"/><include name="${deploy.file.ejb_module}"/></fileset></ear></target><target name="make" depends="init, compile, make.web_module, make.ejb_module, make.ear_module" /><target name="build" depends="clean, init, make" />


C物 2008-02-13 22:59 发表评论
]]>
配合ant开发web目Q原创)http://m.tkk7.com/libin2722/archive/2008/02/13/179855.htmlC物C物Wed, 13 Feb 2008 14:58:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179855.htmlhttp://m.tkk7.com/libin2722/comments/179855.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179855.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179855.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179855.html引用地址Q?a >http://www.easydone.cn/014/200604110005145285.htm

配合ant开发web目
应用相关说明Q?br /> 1、ant版本Qapache-ant-1.6.1
2、eclipse版本Qeclipse-SDK-3.0.1-win32
3、j2sdk1.4.2_08
4、jakarta-tomcat-5.0.19
5、mysql
目录l构如下Q?br />


ant具体配|如?br /> 1?Easydone"project"demo"bin目录下新建build.xml
内容如下Q?br />
<?xml version="1.0"  encoding="GB2312" ?>
<project name="Demo-Home" basedir="." default="usage">

 <property name="app.name" ="demo"/>
 <property name="app.dir" location="../WebRoot"/>
 <property name="webserver.home" location="../../../platform/jakarta-tomcat-5.0.19"/>
 <property name="webserver.deploy" location="${webserver.home}/webapps/"/>
 <property name="src.dir" location="../src"/>
 <property name="build.dir" location="${app.dir}/WEB-INF/classes"/>
 <property name="lib.dir" location="${app.dir}/WEB-INF/lib"/>
 <property name="dist.dir" location="../dist"/>
 <property name="properties.dir" location="${src.dir}/com/easydone/struts/ApplicationResources.properties"/>
 <property name="properties_zh.dir" location="${build.dir}/com/easydone/struts/ApplicationResources_zh.properties"/>
 <property name="doc.dir" ="../api"/>
 <property name="packages" ="com.easydone.*"/>
 
 <echo>+--------------------------------------------------+</echo>
 <echo>|                                                  |</echo>
 <echo>|       R U N N I N G   A N T    REPOSITORY        |</echo>
 <echo>|                                                  |</echo>
 <echo>+--------------------------------------------------+</echo>
 <!---Help Information-->
 <target name="usage" >
     <echo message=""/>
     <echo message="-------------------------------------------------------------"/>
     <echo message="操作说明Q?/>
     <echo message="首先您~写的java文g拯?{src.dir}目录?按先后顺序执行以下命令既可?/>
     <echo message="W一步:compile 命o~译*.java"/>
     <echo message="W二步:deploy 命o生成${app.name}.jar文g"/>
     <echo message="W三步:doc 命o生成详细javadoc文档"/>
     <echo message="每一步操作都能看?BUILD SUCCESSFUL提示后,表示您操作成功!"/>
     <echo message="-------------------------------------------------------------"/>
     <echo message=""/>
 </target>  
  <!-- =================================================================== -->
  <!-- 讄应用环境变量                           -->
  <!-- =================================================================== --> 
 <path id="compile.classpath">
  <pathelement path ="${build.dir}"/>
  <fileset dir="${lib.dir}">
   <include name="**/*.jar"/>
  </fileset>
 </path>
  <!-- =================================================================== -->
  <!-- 格式化中文资源包Q解军_际化中文问题                     -->
  <!-- =================================================================== --> 
    <target name="checkToZh">
         <uptodate property="toZh.notRequired"
            srcfile="${properties.dir}"
            targetfile="${properties_zh.dir}"/>
    </target>
    <target name="toZh" depends="checkToZh" unless="toZh.notRequired">
        <delete file="${properties_zh.dir}"/>
        <!-- native2ascii struts.properties -->
        <exec executable="native2ascii">
          <arg line=" ${properties.dir}  ${properties_zh.dir}"/>
        </exec> 
        <echo message="toZh performed!"/>
    </target>
  <!-- =================================================================== -->
  <!-- 初始化创建相兛_用目?nbsp;                            -->
  <!-- =================================================================== -->
    <target name="prepare" deion="create build,dist files">
     <mkdir dir="${build.dir}"/>
     <mkdir dir="${dist.dir}"/>    
    </target>
  <!-- =================================================================== -->
  <!-- 初始化应用程序,删除相关目录                           -->
  <!-- =================================================================== --> 
 <target name="clean" deion="Delete build files">
  <delete dir="${build.dir}"/>
  <delete dir="${dist.dir}"/>
 </target>
 
  <!-- =================================================================== -->
  <!-- compile 命oQ执行javac~译命o                          -->
  <!-- =================================================================== --> 
 <target name="compile" depends="prepare">
  <javac srcdir="${src.dir}" destdir="${build.dir}" debug="on">
   <classpath refid="compile.classpath"/>
  </javac>
 </target>
  <!-- =================================================================== -->
  <!-- update命oQ编译及处理国际化中文资源文?                       -->
  <!-- =================================================================== -->
 <target name="update" depends="compile,toZh">
  <!--copy classes-->
  <copy todir="${webserver.deploy}/${app.name}/WEB-INF/classes" includeEmptyDirs="no">
   <fileset dir="${build.dir}"/>
  </copy>
  <!--copy pages-->
  <copy todir="${webserver.deploy}/${app.name}" includeEmptyDirs="no">
   <fileset dir="${app.dir}"/>
  </copy>
  <!-- copy libs-->
  <copy todir="${webserver.deploy}/${app.name}/WEB-INF/lib" includeEmptyDirs="no">
   <fileset dir="${lib.dir}"/>
  </copy>
 </target>
  <!-- =================================================================== -->
  <!-- 部v应用E序Q依赖于 compile命oclean,prepare,compile,dist          -->
  <!-- =================================================================== -->

 <target name="deploy" depends="clean,prepare,compile,toZh,dist">
  <delete dir="${webserver.deploy}/${app.name}.war"/>
  <delete dir="${webserver.deploy}/${app.name}"/>  
  <copy todir="${webserver.deploy}" includeEmptyDirs="no">
   <fileset dir="${dist.dir}"/>
  </copy>
 </target> 
  <!-- =================================================================== -->
  <!-- 部v应用E序Q将其打为mshome.war包,依赖?compile命o              -->
  <!-- =================================================================== --> 
 <target name="dist" depends="compile">
   <echo>building war...</echo>
   <war warfile="${dist.dir}/${app.name}.war"
       webxml="${app.dir}/WEB-INF/web.xml">
     <fileset dir="${app.dir}"/>
     <classes dir="${build.dir}"/>
     <classes dir="${lib.dir}">
      <include name="*.propertries"/>
   </classes>
   <lib dir="${lib.dir}">
    <include name="*.jar"/>
   </lib>
  </war>
 </target> 
  <!-- =================================================================== -->
  <!-- 生成说明文档(api)                                                   -->
  <!-- =================================================================== -->
 <target name="javadoc" depends="usage,compile">
    <delete dir="${doc.dir}"/>
    <mkdir dir="${doc.dir}"/>
     <javadoc packagenames="${packages}"
              sourcepath="${src.dir}"
              destdir="${doc.dir}"
              author="true"
              version="true"
              use="true"
              splitindex="true"
              windowtitle="${app.name} API"
              doctitle="${app.name}">
       <classpath refid="compile.classpath"/>
     </javadoc>
  </target>
  <!-- =================================================================== -->
  <!-- 执行一个数据库操作Q其中demo为您的数据库名,可测试相关jdbcq接
      查询语句为bin目录下的db.sql                                -->
  <!-- =================================================================== -->  
 <target name = "mysqlInit">
 <echo>ANT 操作数据库开?....</echo>
 <sql
  driver = "org.gjt.mm.mysql.Driver"
  url = "jdbc:mysql://localhost:3306/demo"
  userid = "root"
  password = "*******"
  src = "db.sql"
  print="yes"
  ="continue"
 />
 </target>
 <!--END-->
</project>

2、在"Easydone"project"demo"bin目录下新建setEnv.bat
dos处理脚本Q主要ؓ讄环境变量Q这样做您无需手工配置环境变量Q将整个工程UdCQ何目录都可以使用Q,内容如下Q?br />
set ANT_HOME=../../../platform/apache-ant-1.6.1
set JAVA_HOME=../../../platform/j2sdk1.4.2_08
set CLASSPATH=%JAVA_HOME%/lib/toos.jar;%JAVA_HOME%/lib/dt.jar
set CATALINA_HOME=../../../platform/jakarta-tomcat-5.0.19
set PATH=%ANT_HOME%/bin;%CATALINA_HOME%/BIN;%JAVA_HOME%/bin;%CATALINA_HOME%/BIN
3、服务控制脚本:
tomcat启动服务Q?br /> ?Easydone"project"demo"bin目录下新建 run.cmdQ?/strong>

call setEnv.bat
startup

tomcat停止服务Q?br /> ?Easydone"project"demo"bin目录下新建 down.cmd

call setEnv.bat
shutdown

更新脚本Q?br /> ?Easydone"project"demo"bin目录下新建 update.cmd
call setEnv.bat
ant -buildfile build.xml  update

部v脚本Q?br /> ?Easydone"project"demo"bin目录下新建 deploy.cmd
call setEnv.bat
ant -buildfile build.xml  deploy

java doc 脚本Q?br /> ?Easydone"project"demo"bin目录下新建 doc.cmd
call setEnv.bat
ant -buildfile build.xml  javadoc

剩下的都在build.xml中,Ҏ你的需要自己定义脚本程序就可以?br /> 很简单,q样可控制你的应用?

C物 2008-02-13 22:58 发表评论
]]>
对google个性主늚拖拽效果的js的完整注释-1http://m.tkk7.com/libin2722/archive/2008/02/13/179851.htmlC物C物Wed, 13 Feb 2008 14:51:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179851.htmlhttp://m.tkk7.com/libin2722/comments/179851.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179851.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179851.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179851.html// 工具c,使用Util的命名空_方便理
var  Util  =   new  Object();
// 获取http header里面的UserAgentQ浏览器信息
Util.getUserAgent  =  navigator.userAgent;
// 是否是Gecko核心的BrowserQ比如Mozila、Firefox
Util.isGecko  =  Util.getUserAgent.indexOf( " Gecko " !=   - 1 ;
// 是否是Opera
Util.isOpera  =  Util.getUserAgent.indexOf( " Opera " !=   - 1 ;
// 获取一个element的offset信息Q其实就是相对于Body的padding以内的绝对坐?/span>
//
后面一个参数如果是true则获取offsetLeftQfalse则是offsetTop
//
关于offset、style、client{坐标的定义参考dindin的这个帖子:http://www.jroller.com/page/dindin/?anchor=pro_java_12
Util.getOffset  =    (el, isLeft) {
    
var  ret  =   0 ;
    
while  (el  !=   null ) {
        ret 
+=  el[ " offset "   +  (isLeft  ?   " Left "  :  " Top " )];
        el 
=  el.offsetParent;
    }
    
return  ret;
};
// 一个(参数中的funcName是这个fuction的名字)l定C个element上,q且以这个element的上下文q行Q其实是一U承,q个可以google些文章看?/span>
Util.bind  =    (el, fucName) {
    
return    () {
        
return  el[fucName].apply(el, arguments);
    };
};
// 重新计算所有的可以拖拽的element的坐标,对同一个column下面的可拖拽囑ֱ重新计算它们的高度而得出新的坐标,防止遮叠
//
计算出来的坐标记录在pagePosLeft和pagePosTop两个属性里?/span>
Util.re_calcOff  =    (el) {
    
for  ( var  i  =   0 ; i  <  Util.dragArray.length; i ++ ) {
        
var  ele  =  Util.dragArray[i];
        ele.elm.pagePosLeft 
=  Util.getOffset(ele.elm,  true );
        ele.elm.pagePosTop 
=  Util.getOffset(ele.elm,  false );
    }
    
var  nextSib  =  el.elm.nextSibling;
    
while  (nextSib) {
        nextSib.pagePosTop 
-=  el.elm.offsetHeight;
        nextSib 
=  nextSib.nextSibling;
    }
};

// 隐藏Google Ig中间那个tableQ也是拖拽的容器,配合show一般就是刷新用Q解决一些浏览器的怪癖
Util.hide  =    () {
    Util.rootElement.style.display 
=   " none " ;
};
// 昄Google Ig中间那个tableQ解释同?/span>
Util.show  =    () {
    Util.rootElement.style.display 
=   "" ;
};

// Ud时显C的占位虚线?/span>
ghostElement  =   null ;
// 获取q个虚线框,通过dom动态生?/span>
getGhostElement  =    () {
    
if  ( ! ghostElement) {
        ghostElement 
=  createElement( " DIV " );
        ghostElement.className 
=   " modbox " ;
        ghostElement.backgroundColor 
=   "" ;
        ghostElement.style.border 
=   " 2px dashed #aaa " ;
        ghostElement.innerHTML 
=   " &nbsp; " ;
    }
    
return  ghostElement;
};

// 初始化可以拖拽的Element的函敎ͼ与拖拽无关的我去掉了
  draggable(el) {
     // 公用的开始拖拽的函数
     this ._dragStart  =  start_Drag;
     // 公用的正在拖拽的函数
     this ._drag  =  when_Drag;
     // 公用的拖拽结束的函数
     this ._dragEnd  =  end_Drag;
     // q个函数主要用来q行拖拽l束后的dom处理
     this ._afterDrag  =  after_Drag;
     // 是否正在被拖动,一开始当然没有被拖动
     this .isDragging  =   false ;
     // 这个Element的this指针注册在elmq个变量里面Q方便在自己的上下文以外调用自己的函数等Q很常用的方?
     this .elm  =  el;
     // 触发拖拽的ElementQ在q里是q个div上显C标题的那个div
     this .header  =  getElementById(el.id  +   " _h " );
     // 对于有i的element拖拽不同Q这里检一下ƈ记录
     this .hasI  =   this .elm.getElementsByTagName( " I " ).length  >   0 ;
     // 如果扑ֈ了headerq定drag相关的event
     if  ( this .header) {
         // 拖拽时的叉子鼠标指针
         this .header.style.cursor  =   " move " ;
         // 函数绑定到header和element的this上,参照那个函数的说?
        Drag.init( this .header,  this .elm);
         // 下面三个语句写好的三个函数l定l这个elemnt的三个函数钩子上Q也实Celement从draggablel承可拖拽的函数
         this .elm.onDragStart  =  Util.bind( this ,  " _dragStart " );
         this .elm.onDrag  =  Util.bind( this ,  " _drag " );
         this .elm.onDragEnd  =  Util.bind( this ,  " _dragEnd " );
    }
};

// 下面是draggable里面用到的那4?
// 公用的开始拖拽的函数
  start_Drag() {
     // 重置坐标Q实现拖拽以后自q位置马上会被填充的效?
    Util.re_calcOff( this );
     // 记录原先的邻居节点,用来Ҏ是否被移动到新的位置
     this .origNextSibling  =   this .elm.nextSibling;
     // 获取Ud的时候那个灰色的虚线?
     var  _ghostElement  =  getGhostElement();
     // 获取正在Ud的这个对象的高度
     var  offH  =   this .elm.offsetHeight;
     if  (Util.isGecko) {
         // 修正gecko引擎的怪癖?
        offH  -=  parseInt(_ghostElement.style.borderTopWidth)  *   2 ;
    }
     // 获取正在Ud的这个对象的宽度
     var  offW  =   this .elm.offsetWidth;
     // 获取left和top的坐?
     var  offLeft  =  Util.getOffset( this .elm,  true );
     var  offTop  =  Util.getOffset( this .elm,  false );
     // 防止闪烁Q现隐藏
    Util.hide();
     // 自q宽度记录在style属性里?
     this .elm.style.width  =  offW  +   " px " ;
     // 那个灰框设定得与正在拖动的对象一样高Q比较Ş?
    _ghostElement.style.height  =  offH  +   " px " ;
     // 把灰框放到这个对象原先的位置?
     this .elm.parentNode.insertBefore(_ghostElement,  this .elm.nextSibling);
     // ׃要拖动必d被拖动的对象从原先的盒子模型里面抽出来,所以设定position为absoluteQ这个可以参考一下css布局斚w的知?
     this .elm.style.position  =   " absolute " ;
     // 讄zIndexQ让它处在最前面一层,当然其实zIndex=100是让它很靠前Q如果页面里有zIndex>100的,?#8230;…
     this .elm.style.zIndex  =   100 ;
     // ׃position=absolute了,所以left和top实现l对坐标定位Q这是先前计算坐标的作用,不让q个模型pQ要从开始拖动的地方开始移?
     this .elm.style.left  =  offLeft  +   " px " ;
     this .elm.style.top  =  offTop  +   " px " ;
     // 坐标讑֮完毕Q可以显CZQ这样就不会闪烁?
    Util.show();
     // q里本来有个ig_d.GQ没搞明白干什么用的,不过没有也可以用Q谁知道ȝ告诉我一壎ͼ不好意?
     // q没有开始拖拽,q里做个记号
     this .isDragging  =   false ;
     return   false ;
};

// 初始化可以拖拽的Element的函敎ͼ与拖拽无关的我去掉了
  draggable(el) {
     // 公用的开始拖拽的函数
     this ._dragStart  =  start_Drag;
     // 公用的正在拖拽的函数
     this ._drag  =  when_Drag;
     // 公用的拖拽结束的函数
     this ._dragEnd  =  end_Drag;
     // q个函数主要用来q行拖拽l束后的dom处理
     this ._afterDrag  =  after_Drag;
     // 是否正在被拖动,一开始当然没有被拖动
     this .isDragging  =   false ;
     // 这个Element的this指针注册在elmq个变量里面Q方便在自己的上下文以外调用自己的函数等Q很常用的方?
     this .elm  =  el;
     // 触发拖拽的ElementQ在q里是q个div上显C标题的那个div
     this .header  =  getElementById(el.id  +   " _h " );
     // 对于有i的element拖拽不同Q这里检一下ƈ记录
     this .hasI  =   this .elm.getElementsByTagName( " I " ).length  >   0 ;
     // 如果扑ֈ了headerq定drag相关的event
     if  ( this .header) {
         // 拖拽时的叉子鼠标指针
         this .header.style.cursor  =   " move " ;
         // 函数绑定到header和element的this上,参照那个函数的说?
        Drag.init( this .header,  this .elm);
         // 下面三个语句写好的三个函数l定l这个elemnt的三个函数钩子上Q也实Celement从draggablel承可拖拽的函数
         this .elm.onDragStart  =  Util.bind( this ,  " _dragStart " );
         this .elm.onDrag  =  Util.bind( this ,  " _drag " );
         this .elm.onDragEnd  =  Util.bind( this ,  " _dragEnd " );
    }
};
// 下面是draggable里面用到的那4?
// 公用的开始拖拽的函数
  start_Drag() {
     // 重置坐标Q实现拖拽以后自q位置马上会被填充的效?
    Util.re_calcOff( this );
     // 记录原先的邻居节点,用来Ҏ是否被移动到新的位置
     this .origNextSibling  =   this .elm.nextSibling;
     // 获取Ud的时候那个灰色的虚线?
     var  _ghostElement  =  getGhostElement();
     // 获取正在Ud的这个对象的高度
     var  offH  =   this .elm.offsetHeight;
     if  (Util.isGecko) {
         // 修正gecko引擎的怪癖?
        offH  -=  parseInt(_ghostElement.style.borderTopWidth)  *   2 ;
    }
     // 获取正在Ud的这个对象的宽度
     var  offW  =   this .elm.offsetWidth;
     // 获取left和top的坐?
     var  offLeft  =  Util.getOffset( this .elm,  true );
     var  offTop  =  Util.getOffset( this .elm,  false );
     // 防止闪烁Q现隐藏
    Util.hide();
     // 自q宽度记录在style属性里?
     this .elm.style.width  =  offW  +   " px " ;
     // 那个灰框设定得与正在拖动的对象一样高Q比较Ş?
    _ghostElement.style.height  =  offH  +   " px " ;
     // 把灰框放到这个对象原先的位置?
     this .elm.parentNode.insertBefore(_ghostElement,  this .elm.nextSibling);
     // ׃要拖动必d被拖动的对象从原先的盒子模型里面抽出来,所以设定position为absoluteQ这个可以参考一下css布局斚w的知?
     this .elm.style.position  =   " absolute " ;
     // 讄zIndexQ让它处在最前面一层,当然其实zIndex=100是让它很靠前Q如果页面里有zIndex>100的,?#8230;…
     this .elm.style.zIndex  =   100 ;
     // ׃position=absolute了,所以left和top实现l对坐标定位Q这是先前计算坐标的作用,不让q个模型pQ要从开始拖动的地方开始移?
     this .elm.style.left  =  offLeft  +   " px " ;
     this .elm.style.top  =  offTop  +   " px " ;
     // 坐标讑֮完毕Q可以显CZQ这样就不会闪烁?
    Util.show();
     // q里本来有个ig_d.GQ没搞明白干什么用的,不过没有也可以用Q谁知道ȝ告诉我一壎ͼ不好意?
     // q没有开始拖拽,q里做个记号
     this .isDragging  =   false ;
     return   false ;
};
// 在拖拽时的相应函敎ͼ׃l定到鼠标的moveq个event上,所以会传入鼠标的坐标clientX, clientY
  when_Drag(clientX, clientY) {
     // 刚开始拖拽的时候将囑ֱ变透明Qƈ标记为正在被拖拽
     if  ( ! this .isDragging) {
         this .elm.style.filter  =   " alpha(opacity=70) " ;
         this .elm.style.opacity  =   0.7 ;
         this .isDragging  =   true ;
    }
     // 被拖拽到的新的columnQ当然也可以是原来那个)
     var  found  =   null ;
     // 最大的距离Q可能是防止溢出或者什么bug
     var  max_distance  =   100000000 ;
     // 遍历所有的可拖拽的elementQ寻扄当前鼠标坐标最q的那个可拖拽元素,以便后面插入
     for  ( var  i  =   0 ; i  <  Util.dragArray.length; i ++ ) {
         var  ele  =  Util.dragArray[i];
         // 利用勾股定理计算鼠标到遍历到的这个元素的距离
         var  distance  =  Math.sqrt(Math.pow(clientX  -  ele.elm.pagePosLeft,  2 )  +  Math.pow(clientY  -  ele.elm.pagePosTop,  2 ));
         // 自己已经动了,所以不计算自己?
         if  (ele  ==   this ) {
             continue ;
        }
         // 如果计算p|l箋循环
         if  (isNaN(distance)) {
             continue ;
        }
         // 如果更小Q记录下q个距离Qƈ它作ؓfound
         if  (distance  <  max_distance) {
            max_distance  =  distance;
            found  =  ele;
        }
    }
     // 准备让灰框落?
     var  _ghostElement  =  getGhostElement();
     // 如果扑ֈ了另外的落脚?
     if  (found  !=   null   &&  _ghostElement.nextSibling  !=  found.elm) {
         // 扑ֈ落脚点就先把灰框插进去,q就是我们看到的那个灰框停靠的特效,有点像吸附的感觉Q哈?
        found.elm.parentNode.insertBefore(_ghostElement, found.elm);
         if  (Util.isOpera) {
             // Opera的现实问题,要隐?昄后才能刷新出变化
            body.style.display  =   " none " ;
            body.style.display  =   "" ;
        }
    }
};
// 拖拽完毕
  end_Drag() {
     // 拖拽完毕后执行后面的钩子Q执行after_Drag()Q如果布局发生了变动了p录到q程服务器,保存你拖拽后新的布局序
     if  ( this ._afterDrag()) {
         // remote call to save the change
    }
     return   true ;
};
// 拖拽后的执行钩子
  after_Drag() {
     var  return  =   false ;
     // 防止闪烁
    Util.hide();
     // 把拖拽时的position=absolute和相关的那些style都消?
     this .elm.style.position  =   "" ;
     this .elm.style.width  =   "" ;
     this .elm.style.zIndex  =   "" ;
     this .elm.style.filter  =   "" ;
     this .elm.style.opacity  =   "" ;
     // 获取灰框
     var  ele  =  getGhostElement();
     // 如果现在的邻居不是原来的d?
     if  (ele.nextSibling  !=   this .origNextSibling) {
         // 把被拖拽的这个节Ҏ到灰框的前面
        ele.parentNode.insertBefore( this .elm, ele.nextSibling);
         // 标明被拖拽了新的地方
        return  =   true ;
    }
     // U除灰框Q这是这个灰框的生命周期应该q束了
    ele.parentNode.removeChild(ele);
     // 修改完毕Q显C?
    Util.show();
     if  (Util.isOpera) {
         // Opera的现实问题,要隐?昄后才能刷新出变化
        body.style.display  =   " none " ;
        body.style.display  =   "" ;
    }
     return  return;
};


// 可拖拽Element的原形,用来eventl定到各个钩子,q部分市比较通用的,netvibes也是基本完全相同的实?
// q部分推荐看dindin的这个,也会帮助理解Q?a >http://www.jroller.com/page/dindin/?anchor=pro_java_12
var  Drag  =  {
     // 对这个element的引用,一ơ只能拖拽一个Element
    obj: null ,
     // element是被拖拽的对象的引用QelementHeader是鼠标可以拖拽的区?
    init:   (elementHeader, element) {
         // startl定到down事gQ按下鼠标触发start
        elementHeader.down  =  Drag.start;
         // element存到header的obj里面Q方便header拖拽的时候引?
        elementHeader.obj  =  element;
         // 初始化绝对的坐标Q因Z是position=absolute所以不会v什么作用,但是防止后面onDrag的时候parse出错?
         if  (isNaN(parseInt(element.style.left))) {
            element.style.left  =   " 0px " ;
        }
         if  (isNaN(parseInt(element.style.top))) {
            element.style.top  =   " 0px " ;
        }
         // 挂上I,初始化这几个成员Q在Drag.init被调用后才帮定到实际的函敎ͼ可以参照draggable里面的内?
        element.onDragStart  =   new  ();
        element.onDragEnd  =   new  ();
        element.onDrag  =   new  ();
    },
     // 开始拖拽的l定Q绑定到鼠标的移动的event?
    start:   (event) {
         var  element  =  Drag.obj  =   this .obj;
         // 解决不同览器的event模型不同的问?
        event  =  Drag.fixE(event);
         // 看看是不是左键点?
         if  (event.which  !=   1 ) {
             // 除了左键都不起作?
             return   true ;
        }
         // 参照q个函数的解释,挂上开始拖拽的钩子
        element.onDragStart();
         // 记录鼠标坐标
        element.lastMouseX  =  event.clientX;
        element.lastMouseY  =  event.clientY;
         // Global的eventl定到被拖动的element上面?
        up  =  Drag.end;
        move  =  Drag.drag;
         return   false ;
    },
     // Element正在被拖动的函数
    drag:   (event) {
         // 解决不同览器的event模型不同的问?
        event  =  Drag.fixE(event);
         // 看看是不是左键点?
         if  (event.which  ==   0 ) {
             // 除了左键都不起作?
             return  Drag.end();
        }
         // 正在被拖动的Element
         var  element  =  Drag.obj;
         // 鼠标坐标
         var  _clientX  =  event.clientY;
         var  _clientY  =  event.clientX;
         // 如果鼠标没动׃么都不作
         if  (element.lastMouseX  ==  _clientY  &&  element.lastMouseY  ==  _clientX) {
             return   false ;
        }
         // 刚才Element的坐?
         var  _lastX  =  parseInt(element.style.top);
         var  _lastY  =  parseInt(element.style.left);
         // 新的坐标
         var  newX, newY;
         // 计算新的坐标Q原先的坐标+鼠标Ud的值差
        newX  =  _lastY  +  _clientY  -  element.lastMouseX;
        newY  =  _lastX  +  _clientX  -  element.lastMouseY;
         // 修改element的显C坐?
        element.style.left  =  newX  +   " px " ;
        element.style.top  =  newY  +   " px " ;
         // 记录element现在的坐标供下一ơ移动?
        element.lastMouseX  =  _clientY;
        element.lastMouseY  =  _clientX;
         // 参照q个函数的解释,挂接上Drag时的钩子
        element.onDrag(newX, newY);
         return   false ;
    },
     // Element正在被释攄函数Q停止拖?
    end:   (event) {
         // 解决不同览器的event模型不同的问?
        event  =  Drag.fixE(event);
         // 解除对Global的event的绑?
        move  =   null ;
        up  =   null ;
         // 先记录下onDragEnd的钩子,好移除obj
         var  _onDragEndFuc  =  Drag.obj.onDragEnd();
         // 拖拽完毕Qobj清空
        Drag.obj  =   null ;
         return  _onDragEndFuc;
    },
     // 解决不同览器的event模型不同的问?
    fixE:   (ig_) {
         if  ( typeof  ig_  ==   " undefined " ) {
            ig_  =  event;
        }
         if  ( typeof  ig_.layerX  ==   " undefined " ) {
            ig_.layerX  =  ig_.offsetX;
        }
         if  ( typeof  ig_.layerY  ==   " undefined " ) {
            ig_.layerY  =  ig_.offsetY;
        }
         if  ( typeof  ig_.which  ==   " undefined " ) {
            ig_.which  =  ig_.button;
        }
         return  ig_;
    }
};

// 下面是初始化的函CQ看看上面这些东西怎么被调?
var  _IG_initDrag  =     (el) {
     // column那个容器Q在google里面是那个table布局的tbodyQnetvibes用的<div>
    Util.rootElement  =  el;
     // q个tbody的行
    Util._rows  =  Util.rootElement.tBodies[ 0 ].rows[ 0 ];
     // 列,google?列,其实也可以更?
    Util.column  =  Util._rows.cells;
     // 用来存取可拖拽的对象
    Util.dragArray  =   new  Array();
     var  counter  =   0 ;
     for  ( var  i  =   0 ; i  <  Util.column.length; i ++ ) {
         // 搜烦所有的column
         var  ele  =  Util.column[i];
         for  ( var  j  =   0 ; j  <  ele.childNodes.length; j ++ ) {
             // 搜烦每一column里面的所有element
             var  ele1  =  ele.childNodes[j];
             // 如果是div把它初始化Z个draggable对象
             if  (ele1.tagName  ==   " DIV " ) {
                Util.dragArray[counter]  =   new  draggable(ele1);
                counter ++ ;
            }
        }
    }
};

// google的页面里可以拖动的部分的id?t_1"
// 挂蝲刎ͼ载入完毕执行。不q实际上google没有用?
// 而是写在面最下面Q异曲同工吧Q也许直接写在页面是U怪癖Q或者也有可能是兼容性考虑?

// 请将下面两条被注释掉的代码加Q到你自׃载的一个google ig面里面Q把里面的所有其余删除,挂上q个js也可以拖拽了Q哈?
// _table=getElementById("t_1");
// = _IG_initDrag(_table);

// 其实看懂q些代码对学习java很有益,希望对大家能有帮?/span>


C物 2008-02-13 22:51 发表评论
]]>
Google“爬虫”主动“送食”(转蝲Q?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:44:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179850.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179850.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/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>收录Q抓取更多的内容Q甚x取所有网)Q可以?span style="font-family: Times New Roman;">google</span>提供?span style="font-family: Times New Roman;">google Sitemap</span>服务Q?span style="font-family: Times New Roman;"> <a >https://www.google.com/webmasters/tools/docs/zh_CN/sitemap-generator.html</a></span>Q?/p> <p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">使搜索引搜烦蜘蛛的收录由被动变ؓdQ?span style="font-family: Times New Roman;">google Sitemap</span>服务目前不提供在线创徏<span style="font-family: Times New Roman;">Sitemap</span>的功能,但是我们可以借助W三方网站提供的此类服务Q打开|站Q?a ><span style="font-family: Times New Roman;">http://www.xml-sitemaps.com</span></a>Q(如图<span style="font-family: Times New Roman;">1</span>Q?nbsp;</p> <p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">?#8220;<span style="font-family: Times New Roman;">Starting URL</span>”栏中输入你自q|站地址Q在“<span style="font-family: Times New Roman;">Change frequency</span>”下拉列表选择|站的更新频率(l常 每天 每年{不同的时段Q,?#8220;<span style="font-family: Times New Roman;">Last modification</span>”选择最后修Ҏ_选择<span style="font-size: 8.5pt;">Use server's response</span>服务器反映时?nbsp;Q,?#8220;Priority”栏中速入跟新的优先权Q最后点?#8220;Start”按钮创徏|站地图 Q如?Q?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文gQ将“Sitemap.xml”下蝲到本地然后再传到服务器主目录下,下面用Gmail帐户登陆到google Sitemap,d自己的网站sitemap文gQ如?Q?img src="http://www.6b9g.com/sitemap.gif" onclick="javascript:window.open(this.src);" style="cursor: pointer;" onload="rsimg(this,500)" alt="" />Q再选在d该站点的sitemapQ注意在选择分类的时候选择d常规|络(如图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地址Q各?a >http://www.6b9g.com/sitemap.xml</a>  再点?#8220;d普通sitemap” 按钮</p> <p style="margin: 0cm 0cm 0pt 10.5pt; text-align: center;" align="center">首发 高峰 站长互动信息|?nbsp;  <a >http://www.6b9g.com</a></p> <img src ="http://m.tkk7.com/libin2722/aggbug/179850.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:44 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179850.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>论坛灌水?-- HTTPClienthttp://m.tkk7.com/libin2722/archive/2008/02/13/179849.htmlC物C物Wed, 13 Feb 2008 14:37:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179849.htmlhttp://m.tkk7.com/libin2722/comments/179849.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179849.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179849.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179849.html
本程序用了HTTPClient包,下蝲地址Q?br /> http://www.innovation.ch/java/HTTPClient/

灌水机原理很单,是分析论坛的表单,用自qE序模拟提交可以了Q?br /> 本文的目的在于介lHTTPClientq个开源工P比jdk?net包强何止癑ր,
HTTPClient的特Ҏ多个操作可以复用同一个连接,讄q接时(Zsocket)Q用代理验证。具体可以到innovation|站看看Ҏ数据?br />
如下是灌水程序的单程序,仅供参?br /> import java.net.*;
import java.io.*;
import java.util.*;
import HTTPClient.*;

class WebRequester{
private static InputStream istr = null;
private static OutputStream ostr = null;
private static NVPair form_data[];
private static HTTPConnection httpCon;
private static HTTPResponse rsp;
private static String host;
private static WebRequester instance;
private WebRequester(){
}
public static WebRequester getInstance(){
  if(instance==null){
    instance = new WebRequester();
  }
  return instance;
}
public static String request(HTTPConnection connection,String pathName,String method,NVPair form_data[]) {
  try{
    httpCon = connection;
    if(method.toLowerCase().equals("get")){
      if(form_data!=null)
      rsp = httpCon.Get(pathName, form_data);
      else
      rsp = httpCon.Get(pathName);
    }
    else{
      if(form_data!=null)
      rsp = httpCon.Post(pathName, form_data);
      else
      rsp = httpCon.Post(pathName);
    }
    istr = rsp.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(istr));
    String line;
    StringBuffer result = new StringBuffer();
    while ((line = reader.readLine()) != null) {
    result.append(line + System.getProperty("line.separator"));
    }
    return result.toString();
  } catch(Exception e){
  }
return "";
}
}


public class Flood
{
private HTTPConnection connection;
public Flood(){

  getConnection("sitename.com",80);
}
public void releaseConnection(){
  if(connection!=null){
    connection.stop();
    connection = null;
  }
}
public HTTPClient.HTTPConnection getConnection(String hostName,int port){
  if(connection==null){
    try{
      connection = new HTTPClient.HTTPConnection(hostName,port);
      HTTPClient.Module.setPolicyHandler(null);
      connection.addDefaultModule(Class.forName("HTTPClient.Module"), 1);
      connection.addModule(Class.forName("HTTPClient.RedirectionModule"),2);
    }catch(Exception e){
      e.printStackTrace();
    }
  }
  return connection;
}

public void post(String subject,String body){
  NVPair[] form_data = new NVPair[5];
  form_data[0] = new NVPair("forumID","87");
  form_data[1] = new NVPair("subject",subject);
  form_data[2] = new NVPair("classifier","-1");
  form_data[3] = new NVPair("body",body);
  form_data[4] = new NVPair("doPost"," ??");
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);

}
public void reply(String thread,String subject,String body){
  //提交表单需要多项Q查看回复页面表单可以获?br />   NVPair[] form_data = new NVPair[7];
  form_data[0] = new NVPair("forumID","87");
  form_data[1] = new NVPair("subject",subject);
  form_data[2] = new NVPair("classifier","-1");
  form_data[3] = new NVPair("body",body);
  form_data[4] = new NVPair("reply","true");
  form_data[5] = new NVPair("threadID",thread);
  form_data[6] = new NVPair("doPost"," ??");
WebRequester.getInstance().request(connection,"post!post.jspa","post",form_data);

}
public void finish(){
  releaseConnection();
}
public void login(){

  WebRequester wr = WebRequester.getInstance();
  NVPair[] form_data = new NVPair[4];
  //对应登陆需要的表单字段填写
  form_data[0] = new NVPair("formUsername","user");
  form_data[1] = new NVPair("formPassword","pass");
  form_data[2] = new NVPair("formLogins cript","sitename.com/loginuser.jsp");
  form_data[3] = new NVPair("forumLogin","Y");
  //提交到指定登陆页?br />   wr.request(connection,"cgi-bin/gzhome/registration/LoginUser1.jsp","post",form_data);
  //假如重定向,必须用该链接再次h新的面
  wr.request(connection,"loginuser.jsp","get",null);
  wr.request(connection,"index.jspa","get",null);
}


public static void main(String[] args)
{  
  try{
  Flood f=new Flood();
  f.login();
  //post一个新主题Qidql自׃?br />   //f.post("friends","剧本");
  //得到某个主题idQ进行指定数量的跟帖
  for(int i=0;i<50;i++){
    f.reply("67145","Re: 警告Q在U朋友发a又少了,望奔走相?,"z水来了");
  }
  /*如下是读取某个文件每一行文字作为回帖进行灌?br />   BufferedReader br = new BufferedReader(new FileReader("E:""movie""101-105""Friends - 1x04 - TOW George Stephanopoulos.CHN.srt"));
  StringBuffer sb = new StringBuffer();
  String t = null;
  int counter=0;
  while((t=br.readLine())!=null){
  if(t.length()==0){
    //System.out.println(sb.toString());
      //System.out.println("====");
  counter++;
  f.reply("66617","" + counter,sb.toString());
  sb.delete(0,sb.length());
  }
  sb.append(t + ""n");
  
  }*/
  f.finish();
}catch(Exception e){
  e.printStackTrace();
}
}
}


OKOK~大家自己研究
我做好了

C物 2008-02-13 22:37 发表评论
]]>
httpclient中MultipartPostMethodcM传文?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:35:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179848.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179848.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/libin2722/services/trackbacks/179848.html</trackback:ping><description><![CDATA[<p>在文件上传过E中到很多问题Q首先是搞错了类Q刚开始时我用的是PostodMethod,以ؓ一? setrequestbodyQ)Ҏ可以搞定,l果改过来改q去也没改出来什么名堂,最后改用的是MultipartPostMethodc,呵呵Q? 问题解决了,关键ҎMultipartPostMethodc里的addParameter()和addPart()两个Ҏ都要用到Q而且要注意顺 序。不q马上又出现了新的问题,httpclient不支持中文名的文件上传,晕了。又在这上面费了一D|间。解决的途径是。找? httpclient3.0"rc"java"org"apache"commons"httpclient"util目录下的 EncodingUtil.java,打开Q找到文仉面这个地方:<br /> public static byte[] getAsciiBytes(final String data) {        <br /> if (data == null) {            <br /> throw new IllegalArgumentException("Parameter may not be null");       }        <br /> try {           return data.getBytes("US-ASCII");       } <br /> catch (UnsupportedEncodingException e) {throw new HttpClientError("HttpClient requires ASCII support");       }  <br /> }<br /> ? C没有Qreturn data.getBytes("US-ASCII");它的~码方式是US-ASCIIQ问题就出在q里了,把这个取掉,换成"GBK"或? "GB2312"保存以后~译Q重新运行程序,goooooooooooood。中文名文g现在可以上传了,呵呵</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 /> <HTML><br />   <HEAD><br />     < HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=windows-1252"/><br />     <TITLE>File Upload Page</TITLE><br />   </HEAD><br />   <BODY>Upload Files<br />     <FORM name="filesForm" action="ProcessFileUpload.jsp"<br />     method="post" enctype="multipart/form-data"><br />         File 1:<input type="file" name="file1"/><br/><br />         File 2:<input type="file" name="file2"/><br/><br />         File 3:<input type="file" name="file3"/><br/><br />         <input type="submit" name="Submit" ="Upload Files"/><br />     </FORM><br />   </BODY><br /> </HTML></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 /> <%@ page contentType="text/html;charset=windows-1252"%><br /> <%@ page import="org.apache.commons.fileupload.DiskFileUpload"%><br /> <%@ page import="org.apache.commons.fileupload.FileItem"%><br /> <%@ page import="jsp servlet ejb .util.List"%><br /> <%@ page import="jsp servlet ejb .util.Iterator"%><br /> <%@ page import="jsp servlet ejb .io.File"%><br /> html><br /> <head><br /> < http-equiv="Content-Type" content="text/html; charset=windows-1252"><br /> <title>Process File Upload</title><br /> </head><br /> <%<br />         System.out.println("Content Type ="+request.getContentType());</p> <p>        DiskFileUpload fu = new DiskFileUpload();<br />         // If file size exceeds, a FileUploadException will be thrown<br />         fu.setSizeMax(1000000);</p> <p>        List fileItems = fu.parseRequest(request);<br />         Iterator itr = fileItems.iterator();</p> <p>        while(itr.hasNext()) {<br />           FileItem fi = (FileItem)itr.next();</p> <p>          //Check if not form field so as to only handle the file inputs<br />           //else condition handles the submit button input<br />           if(!fi.isFormField()) {<br />             System.out.println(""nNAME: "+fi.getName());<br />             System.out.println("SIZE: "+fi.getSize());<br />             //System.out.println(fi.getOutputStream().toString());<br />             File fNew= new File(application.getRealPath("/"), fi.getName());</p> <p>            System.out.println(fNew.getAbsolutePath());<br />             fi.write(fNew);<br />           }<br />           else {<br />             System.out.println("Field ="+fi.getFieldName());<br />           }<br />         }<br /> %><br /> <body><br /> Upload Successful!!<br /> </body><br /> </html></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: “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.”</p> <p>This contrasting behavior on different browsers can cause problems. One workaround that I found in an article at <a 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…blaming Microsoft is always the easy way out) </p> <p>File tempFileRef  = 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 />     private static String url =<br />       "http://localhost/yaoliang/ProcessFileUpload.jsp";</p> <p>    public static void main(String[] args) throws IOException {<br />         HttpClient client = new HttpClient();<br />         MultipartPostMethod mPost = new MultipartPostMethod(url);<br />         client.setConnectionTimeout(8000);</p> <p>        // Send any XML file as the body of the POST request<br />         File f1 = new File("D:/students.xml");<br />         File f2 = new File("D:/demy.xml");<br />         File f3 = new File("D:/demyRules.xml");</p> <p>        System.out.println("File1 Length = " + f1.length());<br />         System.out.println("File2 Length = " + f2.length());<br />         System.out.println("File3 Length = " + f3.length());</p> <p>        mPost.addParameter(f1.getName(),f1.getName(),  f1);<br />         mPost.addParameter(f2.getName(), f2.getName(), f2);<br />         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>        int statusCode1 = client.executeMethod(mPost);</p> <p>        System.out.println("statusLine>>>" + mPost.getStatusLine());<br />         mPost.releaseConnection();<br />     }<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://m.tkk7.com/libin2722/aggbug/179848.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:35 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179848.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>应用HttpClient来对付各U顽固的WEB服务?/title><link>http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html</link><dc:creator>C物</dc:creator><author>C物</author><pubDate>Wed, 13 Feb 2008 14:34:00 GMT</pubDate><guid>http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html</guid><wfw:comment>http://m.tkk7.com/libin2722/comments/179847.html</wfw:comment><comments>http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://m.tkk7.com/libin2722/comments/commentRss/179847.html</wfw:commentRss><trackback:ping>http://m.tkk7.com/libin2722/services/trackbacks/179847.html</trackback:ping><description><![CDATA[<p>一般的情况下我们都是用IE或者Navigator览器来讉K一个WEB服务器,用来览面查看信息或者提交一些数据等{。所讉K的这些页? 有的仅仅是一些普通的面Q有的需要用L录后方可使用Q或者需要认证以及是一些通过加密方式传输Q例如HTTPS。目前我们用的览器处理这些情况都 不会构成问题。不q你可能在某些时候需要通过E序来访问这L一些页面,比如从别人的|页?#8220;?#8221;一些数据;利用某些站点提供的页面来完成某种功能Q例? 说我们想知道某个手机L的归属地而我们自己又没有q样的数据,因此只好借助其他公司已有的网站来完成q个功能Q这个时候我们需要向|页提交手机Lq从 q回的页面中解析出我们想要的数据来。如果对方仅仅是一个很单的面Q那我们的程序会很简单,本文也就没有必要大张旗鼓的在q里费口舌。但是考虑C 些服务授权的问题Q很多公司提供的面往往q不是可以通过一个简单的URL可以访问的Q而必ȝq注册然后登录后方可使用提供服务的页面,q个时候就? 及到问题的处理。我们知道目前流行的动态网|术例如ASP、JSP无不是通过来处理会话信息的。ؓ了我们的程序能使用别h所提供的服务页面,p求程 序首先登录后再访问服务页面,q过E就需要自行处理,x当你用java.net.HttpURLConnection来完成这些功能时是多么恐怖的事情 啊!况且q仅仅是我们所说的固的WEB服务器中的一个很常见?#8220;固”Q再有如通过HTTP来上传文件呢Q不需要头|q些问题有了“?#8221;很Ҏ解决 了! <br /> </p> <p><span style="font-size: 10pt; font-family: Courier New;">我们不可能列举所 有可能的固Q我们会针对几种最常见的问题进行处理。当然了Q正如前面说到的Q如果我们自׃用java.net.HttpURLConnection? 搞定q些问题是很恐怖的事情Q因此在开始之前我们先要介l一下一个开放源码的目Q这个项目就是Apache开源组l中的httpclientQ它隶属? Jakarta的commons目Q目前的版本?.0RC2。commons下本来已l有一个net的子目Q但是又把httpclient单独提出 来,可见http服务器的讉Kl非易事?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">Commons-httpclient 目是专门设计来简化HTTP客户端与服务器进行各U通讯~程。通过它可以让原来很头疼的事情现在L的解冻I例如你不再管是HTTP或者HTTPS? 通讯方式Q告诉它你想使用HTTPS方式Q剩下的事情交给httpclient替你完成。本文会针对我们在编写HTTP客户端程序时l常到的几个问题进 行分别介l如何用httpclient来解军_们,Z让读者更快的熟悉q个目我们最开始先l出一个简单的例子来读取一个网늚内容Q然后@序渐q解 x前进中的所有问题?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">1Q?d|页(HTTP/HTTPS)内容</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">下面是我们给出的一个简单的例子用来讉K某个面</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方式讉K某个面</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;">    public static void main(String[] args) throws IOException</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">    {</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        HttpClient client = new HttpClient();    </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //讄代理服务器地址和端?nbsp;    </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //client.getHostConfiguration().setProxy("proxy_host_addr",proxy_port);</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //使用GETҎQ如果服务器需要通过HTTPSq接Q那只需要将下面URL中的http换成https</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        HttpMethod method = new GetMethod("<a target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //使用POSTҎ</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //HttpMethod method = new PostMethod("<a target="_blank"><span style="color: #000000;">http://java.sun.com</span></a>"); </span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        client.executeMethod(method);</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //打印服务器返回的状?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        System.out.println(method.getStatusLine());</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //打印q回的信?/span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        System.out.println(method.getResponseBodyAsString());</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        //释放q接</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">        method.releaseConnection();</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">    }<br /> }</span></p> <p><span style="font-size: 10pt; font-family: Courier New;">在这个例子中首先创徏一? HTTP客户?HttpClient)的实例,然后选择提交的方法是GET或者POSTQ最后在HttpClient实例上执行提交的ҎQ最后从所? 择的提交Ҏ中读取服务器反馈回来的结果。这是使用HttpClient的基本流E。其实用一行代码也可以搞定整个请求的q程Q非常的单!</span></p> <span style="font-size: 10pt; font-family: Courier New;"> <p><br /> 2Q?以GET或者POST方式向网|交参?/p> <p>其实前面一个最单的CZ中我们已l介l了如何使用GET或者POST方式来请求一个页面,本小节与之不同的是多了提交时讑֮面所需的参敎ͼ我们 知道如果是GET的请求方式,那么所有参数都直接攑ֈ面的URL后面用问号与面地址隔开Q每个参数用&隔开Q例如:<a target="_blank"><span style="color: #000000;">http://java.sun.com?name=liudong&mobile=123456</span></a>Q但是当使用POSTҎ时就会稍微有一点点ȝ。本节的例子演C向如何查询手机L所在的城市Q代码如下:</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>* 以便查询LD?330227所在的省䆾以及城市</p> <p>* @author Liudong</p> <p>*/</p> <p>public class SimpleHttpClient {</p> <p>    public static void main(String[] args) throws IOException</p> <p>    {</p> <p>        HttpClient client = new HttpClient();</p> <p>        client.getHostConfiguration().setHost("<a target="_blank"><span style="color: #000000;">www.imobile.com.cn</span></a>", 80, "http");</p> <p>        HttpMethod method = getPostMethod();//使用POST方式提交数据</p> <p>        client.executeMethod(method);</p> <p>       //打印服务器返回的状?/p> <p>        System.out.println(method.getStatusLine());</p> <p>        //打印l果面</p> <p>        String response =</p> <p>           new String(method.getResponseBodyAsString().getBytes("8859_1"));</p> <p>       //打印q回的信?/p> <p>        System.out.println(response);</p> <p>        method.releaseConnection();</p> <p>    }</p> <p>    /**</p> <p>     * 使用GET方式提交数据</p> <p>     * @return</p> <p>     */</p> <p>    private static HttpMethod getGetMethod(){</p> <p>        return new GetMethod("/simcard.php?simcard=1330227");</p> <p>    }</p> <p>    /**</p> <p>     * 使用POST方式提交数据</p> <p>     * @return</p> <p>     */</p> <p>    private static HttpMethod getPostMethod(){</p> <p>        PostMethod post = new PostMethod("/simcard.php");</p> <p>        NamePair simcard = new NamePair("simcard","1330227");</p> <p>        post.setRequestBody(new NamePair[] { simcard});</p> <p>        return post;</p> <p>    }</p> <p>}</p> <p>在上面的例子中页?a target="_blank"><span style="color: #000000;">http://www.imobile.com.cn/simcard.php</span></a>需要一个参数是simcardQ这个参数gؓ手机LD,x机号码的前七位,服务器会q回提交的手机号码对应的省䆾、城市以及其他详l信息。GET的提交方法只需要在URL后加入参C息,而POST则需要通过NamePaircL讄参数名称和它所对应的?/p> <p>3Q?处理面重定?/p> <p>在JSP/Servlet~程中response.sendRedirectҎ是使用HTTP协议中的重定向机制。它与JSP中的< jsp:forward …>的区别在于后者是在服务器中实现页面的跌{Q也是说应用容器加载了所要蟩转的面的内容ƈq回l客LQ而前者是q回一个状态码Q这些状态码 的可能D下表Q然后客Ld需要蟩转到的页面的URLq新加载新的页面。就是这样一个过E,所以我们编E的时候就要通过 HttpMethod.getStatusCode()Ҏ判断q回值是否ؓ下表中的某个值来判断是否需要蟩转。如果已l确认需要进行页面蟩转了Q那么可 以通过dHTTP头中的location属性来获取新的地址?/p> </span> <img src ="http://m.tkk7.com/libin2722/aggbug/179847.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://m.tkk7.com/libin2722/" target="_blank">C物</a> 2008-02-13 22:34 <a href="http://m.tkk7.com/libin2722/archive/2008/02/13/179847.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Jakarta Commons HttpClient 学习W记(2)http://m.tkk7.com/libin2722/archive/2008/02/13/179846.htmlC物C物Wed, 13 Feb 2008 14:32:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179846.htmlhttp://m.tkk7.com/libin2722/comments/179846.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179846.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179846.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179846.html10、SSL
借助Java Secure Socket Extension (JSSE)QHttpClient全面支持Secure Sockets Layer (SSL)或IETF Transport Layer Security (TLS)协议上的HTTP。JSSE已经jre1.4及以后的版本中,以前的版本则需要手工安装设|,具体q程参见Sun|站或本学习W记?br /> HttpClient中用SSL非常单,参考下面两个例?
HttpClient httpclient = new HttpClient();
GetMethod httpget = new GetMethod("https://www.verisign.com/");
httpclient.executeMethod(httpget);
System.out.println(httpget.getStatusLine().toString());
Q如果通过需要授权的代理Q则如下Q?
HttpClient httpclient = new HttpClient();
httpclient.getHostConfiguration().setProxy("myproxyhost", 8080);
httpclient.getState().setProxyCredentials("my-proxy-realm", " myproxyhost",
new UsernamePasswordCredentials("my-proxy-username", "my-proxy-password"));
GetMethod httpget = new GetMethod("https://www.verisign.com/");
httpclient.executeMethod(httpget);
System.out.println(httpget.getStatusLine().toString());

在HttpClient中定制SSL的步骤如下:

  1. 提供了一个实C org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory接口? socket factory。这?socket factory负责打一个到服务器的端口Q用标准的或第三方的SSL函数库,q进行象q接握手{初始化操作。通常情况下,q个初始化操作在端口被创建时 自动q行的?br />
  2. 实例化一个org.apache.commons.httpclient.protocol.Protocol对象。创个实例时Q需要一个合法的协议cd(如https)Q一个定制的socket factoryQ和一个默认的端中?如https?43端口).
    Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
    然后Q这个实例可被设|ؓ协议的处理器?
    HttpClient httpclient = new HttpClient();
    httpclient.getHostConfiguration().setHost("www.whatever.com", 443, myhttps);
    GetMethod httpget = new GetMethod("/");
    httpclient.executeMethod(httpget);
  3. 通过调用Protocol.registerProtocolҎQ将此定制的实例Q注册ؓ某一特定协议的默认的处理器。由此,可以很方便地定制自己的协议类?如myhttps)?
    Protocol.registerProtocol("myhttps",
    new Protocol("https", new MySSLSocketFactory(), 9443));
    ...
    HttpClient httpclient = new HttpClient();
    GetMethod httpget = new GetMethod("myhttps://www.whatever.com/");
    httpclient.executeMethod(httpget);
    如果想用自己定制的处理器取代https默认的处理器Q只需要将其注册ؓ"https"卛_?
    Protocol.registerProtocol("https",
    new Protocol("https", new MySSLSocketFactory(), 443));
    HttpClient httpclient = new HttpClient();
    GetMethod httpget = new GetMethod("https://www.whatever.com/");
    httpclient.executeMethod(httpget);

已知的限制和问题

  1. 持箋的SSLq接在Sun的低?.4JVM上不能工作,q是׃JVM的bug造成?br />
  2. 通过代理讉K服务器时Q非抢先认证Q?Non-preemptive authenticationQ会p|Q这是由于HttpClient的设计缺陷造成的,以后的版本中会修攏V?/li>

遇到问题的处?br /> 很多问题Q特别是在jvm低于1.4Ӟ是由jsse的安装造成的?br /> 下面的代码,可作为最l的手Dc?br />
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.Socket; import javax.net.ssl.SSLSocketFactory; public class Test {

public static final String TARGET_HTTPS_SERVER = "www.verisign.com";
public static final int TARGET_HTTPS_PORT = 443;

public static void main(String[] args) throws Exception {

Socket socket = SSLSocketFactory.getDefault().
createSocket(TARGET_HTTPS_SERVER, TARGET_HTTPS_PORT);
try {
Writer out = new OutputStreamWriter(
socket.getOutputStream(), "ISO-8859-1");
out.write("GET / HTTP/1.1"r"n");
out.write("Host: " + TARGET_HTTPS_SERVER + ":" +
TARGET_HTTPS_PORT + ""r"n");
out.write("Agent: SSL-TEST"r"n");
out.write(""r"n");
out.flush();
BufferedReader in = new BufferedReader(
new InputStreamReader(socket.getInputStream(), "ISO-8859-1"));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
} finally {
socket.close();
}
}
}


11、httpclient的多U程处理


使用多线E的主要目的Q是Z实现q行的下载。在httpclientq行的过E? 中,每个http协议的方法,使用一个HttpConnection实例。由于连接是一U有限的资源Q每个连接在某一时刻只能供一个线E和Ҏ使用Q所? 需要确保在需要时正确地分配连接。HttpClient采用了一U类似jdbcq接池的Ҏ来管理连接,q个理工作? MultiThreadedHttpConnectionManager完成?
MultiThreadedHttpConnectionManager connectionManager =
new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
? 是,client可以在多个线E中被用来执行多个方法。每ơ调用HttpClient.executeMethod() ҎQ都会去链接理器申请一个连接实例,甌成功q个链接实例被签?checkout)Q随之在链接使用完后必须归还理器。管理器支持两个讄Q?
maxConnectionsPerHost 每个L的最大ƈ行链接数Q默认ؓ2
maxTotalConnections 客户端dƈ行链接最大数Q默认ؓ20

理器重新利用链接时Q采取早归还者先重用的方式(least recently used approachQ?br /> ׃是用HttpClient的程序而不是HttpClient本n来读取应{包的主体,所以HttpClient无法军_什么时间连接不再用了Q这也就要求在读完应{包的主体后必须手工昑ּ地调用releaseConnection()来释攄L链接?
MultiThreadedHttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
HttpClient client = new HttpClient(connectionManager);
...
// 在某个线E中?br /> GetMethod get = new GetMethod("http://jakarta.apache.org/");
try {
client.executeMethod(get);
// print response to stdout
System.out.println(get.getResponseBodyAsStream());
} finally {
// be sure the connection is released back to the connection
// manager
get.releaseConnection();
}
Ҏ一个HttpClient.executeMethodL一个method.releaseConnection()与之匚w.

12、HTTPҎ


HttpClient支持的HTTPҎ?U,下面分述之?br />
1、Options

HTTPҎOptions用来向服务器发送请求,希望获得针对p求URL(request url)标志的资源在h/应答的通信q程可以使用的功能选项。通过q个ҎQ客L可以在采取具体行动之前,可Ҏ一资源军_采取什么动作和/或以? 一些必要条Ӟ或者了解服务器提供的功能。这个方法最典型的应用,是用来获取服务器支持哪些HTTPҎ?br /> HttpClient中有一个类叫OptionsMethodQ来支持q个HTTPҎQ利用这个类的getAllowedMethodsҎQ就可以很简单地实现上述的典型应用?br />
OptionsMethod options = new OptionsMethod("http://jakarta.apache.org");
// 执行Ҏq做相应的异常处?br /> ...
Enumeration allowedMethods = options.getAllowedMethods();
options.releaseConnection();

2、Get

HTTPҎGET用来取回hURIQrequest-URIQ标志的M信息Q以实体(entity)的Ş式)Q?get"q个单词本意是”获取 “的意思。如果请求URI指向的一个数据处理过E,那这个过E生成的数据Q在应答中以实体的Ş式被q回Q而不是将q个q程的代码的q回?br /> 如果 HTTP包中含有If-ModifiedSince, If-Unmodified-Since, If-Match, If-None-Match, ? If-Range{头字段Q则GET也就变成?#8221;条gGET“Q即只有满上述字段描述的条件的实体才被取回Q这样可以减一些非必需的网l传输,或者减 ؓ获取某一资源的多ơ请求(如第一ơ检查,W二ơ下载)。(一般的览器,都有一个时目录,用来~存一些网信息,当再ơ浏览某个页面的时候,只下? 那些修改q的内容Q以加快览速度Q就是这个道理。至于检查,则常用比GET更好的方法HEAD来实现。)如果HTTP包中含有Range头字D,那么? 求URI指定的实体中Q只有决定范围条件的那部分才被取回来。(用过多线E下载工L朋友Q可能比较容易理解这一点)
q个Ҏ的典型应用,? 来从web服务器下载文档。HttpClient定义了一个类叫GetMethod来支持这个方法,用GetMethodcM getResponseBody, getResponseBodyAsStream ? getResponseBodyAsString函数可以取到应{包包体中的文档Q如HTML面Q信息。这q三个函CQ? getResponseBodyAsStream通常是最好的ҎQ主要是因ؓ它可以避免在处理下蝲的文档之前缓存所有的下蝲的数据?br />
GetMethod get = new GetMethod("http://jakarta.apache.org");
// 执行ҎQƈ处理p|的请?
...
InputStream in = get.getResponseBodyAsStream();
// 利用输入来处理信息?br /> get.releaseConnection();

对GetMethod的最常见的不正确的用,是没有将全部的应{主体的数据d来。还有,必须注意要手工明地链接释放?br />
3、Head

HTTP的HeadҎQ与GetҎ完全一_唯一的差别是服务器不能在应答包中包含M(message-body)Q而且一定不能包含主体。? q个ҎQ可以得客h需资源下载回可׃得到一些关于它的基本信息。这个方法常用来查超铄可访问性以及资源最q有没有被修攏V?br /> HTTP的headҎ最典型的应用,是获取资源的基本信息。HttpClient定义了HeadMethodcL持这个方法,HeadMethodcM其它*MethodcMP?getResponseHeaders()取回头部信息Q而没有自qҎҎ?br />
HeadMethod head = new HeadMethod("http://jakarta.apache.org");
// 执行ҎQƈ处理p|的请?
...
// 取回应答包的头字D信?
Header[] headers = head.getResponseHeaders(); // 只取回最后修Ҏ期字D늚信息.
String lastModified = head.getResponseHeader("last-modified").get();


4、Post

Post在英文有“zN”的意思,HTTPҎPOST是要求服务器接受请求包中的实体Qƈ其作ؓhURI的下属资源。从本质上说Q这意味着服务 器要保存q个实体信息Q而且通常由服务器端的E序q行处理。PostҎ的设计意图,是要以一U统一的方式实C列功能:
  1. 对已有的资源做评?br />
  2. 信息发布到BBS、新ȝ、邮件列表,或类似的文章l中

  3. 一块数据,提交l数据处理进E?br />
  4. 通过q加操作Q来扩展一个数据库
q些都操作期待着在服务器端生一定的“副作?#8221;Q如修改了数据库{?br /> HttpClient定义PostMethodcM支持该HTTPҎQ在httpclient中,使用postҎ有两个基本的步骤Qؓh包准备数 据,然后d服务器来的应{包的信息。通过调用 setRequestBody()函数Q来求包提供数据Q它可以接收三类参数Q输入流、名值对数组或字W串。至于读取应{包需要调? getResponseBody* 那一pd的方法,与GETҎ处理应答包的Ҏ相同?br /> 常见问题是,没有全部应{读取(无论它对E序是否有用Q,或没有释N接资源?br />

参考资料:

http://www.systinet.com/doc/wasp_uddi/uddi/igpreliminary.html

C物 2008-02-13 22:32 发表评论
]]>
Jakarta Commons HttpClient 学习W记(1)http://m.tkk7.com/libin2722/archive/2008/02/13/179845.htmlC物C物Wed, 13 Feb 2008 14:23:00 GMThttp://m.tkk7.com/libin2722/archive/2008/02/13/179845.htmlhttp://m.tkk7.com/libin2722/comments/179845.htmlhttp://m.tkk7.com/libin2722/archive/2008/02/13/179845.html#Feedback0http://m.tkk7.com/libin2722/comments/commentRss/179845.htmlhttp://m.tkk7.com/libin2722/services/trackbacks/179845.htmlhttpclient是q么一个包Q我怿可能有比它的实现更好的,但目前我只关注这个。:Q?br /> 下面是nogoop做的功能比较表:

Features nogoop Sun JRE < 1.4.2 Sun JRE 1.4.2 Innovation Apache/Jakarta
s


X X
plug compatible X X X X [partial]
true request output stream


X X
true response input stream X

X X
connection keep alive X X X X X
connection pool throttling X


X
connection/request timeout X
X [uns] X X
idle connection timeout X


X
pipelining of requests


X
alternate DNS resolution (dnsjava) X



SSL X X X X X
basic authentication X X X X X
digest authentication X X X X X
NTLM authentication X
[Windows only]
X
proxy authentication X X X X X
minimum JRE version 1.2 1 01q???/td> 1.2 1.2
price $499 free free free free
source available X

X X
diagnostic tracing X

X X
actively supported X X X
X
fix turnaround fast slow slow none medium
license purchase Sun JRE Sun JRE LGPL Apache

1、HttpClient的功?/h4>
  1. Z标准Q纯正javaQ实Chttp1.0?.1?br />
  2. 在一个可扩展的OO框架内,实现了HTTP的全部方?GET, POST,
    PUT, DELETE, HEAD, OPTIONS, and TRACE)

  3. 支持HTTPS(ssl上的HTTP)的加密操?br />
  4. 透明地穿qHTTP代理建立q接

  5. 通过CONNECTҎQ利用通过建立I过HTTP代理的HTTPSq接

  6. 利用本地Java socketQ透明地穿qSOCKS(版本5?Q代理徏立连?br />
  7. 支持利用Basic、Digest和NTLM加密的认?br />
  8. 支持用于上传大文件的Multi-Part表单POSTҎ

  9. 插g式安全socket实现Q易于用第三方的解x?br />
  10. q接理Q支持多U程应用Q支持设定单个主机总连接和最高连接数?自动和关闭失效q接

  11. 直接请求信息流送到服务器的端口

  12. 直接d从服务器的端口送出的应{信?br />
  13. 支持HTTP/1.0中用KeepAlive和HTTP/1.1中用persistance讄的持久连?br />
  14. 直接讉K由服务器送出的应{代码和头部信息

  15. 可设|连接超时时?

  16. HttpMethods 实现Command PatternQ以允许q行h或高效连接复?br />
  17. 遵@the Apache Software License协议Q源码免费可?

2、预备工?/h4>
对jre1.3.*Q如果要HttpClient支持httpsQ则需要下载ƈ安装jsse?a target="_blank">jce.安装的步骤如下:
1)下蝲jsse和jce.
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复制到目录:
UNIX:$JDK_HOME/jre/lib/ext
Windows:%JDK_HOME%"jre"lib"ext
4)修改下述目录下的java.security文g?br /> UNIX:$JDK_HOME/jre/lib/security/
Windows:%JDK_HOME%"jre"lib"security"
5)
?br /> #
# List of providers and their preference orders:
#
security.provider.1=sun.security.provider.Sun
security.provider.2=com.sun.rsajca.Provider
改ؓQ?br /> #
# List of providers and their preference orders:
#
security.provider.1=com.sun.crypto.provider.SunJCE
security.provider.2=sun.security.provider.Sun
security.provider.3=com.sun.rsajca.Provider
security.provider.4=com.sun.net.ssl.internal.ssl.Provider

HttpClientq要求安装commons-loggingQ下面跟httpclient一块安装?br />

3、取得源?/h4>
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic login
password: anoncvs
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/logging
cvs -d :pserver:anoncvs@cvs.apache.org:/home/cvspublic checkout jakarta-commons/httpclient

~译Q?
cd jakarta-commons/logging
ant dist
cp dis/*.jar ../httpclient/lib/
cd ../httpclient
ant dist

4、用HttpClient~程的基本步?/h4>
  1. 创徏 HttpClient 的一个实?

  2. 创徏某个ҎQDeleteMethodQEntityEnclosingMethodQExpectContinueMethodQ? GetMethodQHeadMethodQMultipartPostMethodQOptionsMethodQPostMethodQ? PutMethodQTraceMethodQ的一个实例,一般可用要目标URL为参数?br />
  3. ?HttpClient 执行q个Ҏ.

  4. d应答信息.

  5. 释放q接.

  6. 处理应答.

在执行方法的q程中,有两U异常,一U是HttpRecoverableExceptionQ表C偶然性错误发生,一般再试可能成功,另一U是IOExceptionQ严重错误?br /> q儿有这个教E中的一个例E,可以下蝲?

5、认?/h4>
HttpClient三种不同的认证方? Basic, Digest and NTLM. q些Ҏ可用于服务器或代理对客户端的认证Q简U服务器认证或代理认证?br /> 1)服务器认?Server Authentication)
HttpClient处理服务器认证几乎是透明的,仅需要开发h员提供登录信?login credentials)。登录信息保存在HttpStatecȝ实例中,可以通过 setCredentials(String realm, Credentials cred)和getCredentials(String realm)来获取或讄。注意,讑֮寚w特定站点讉K所需要的d信息Q将realm参数|ؓnull. HttpClient内徏的自动认证,可以通过HttpMethodcȝsetDoAuthentication(boolean doAuthentication)Ҏ关闭Q而且q次关闭只媄响HttpMethod当前的实例?br /> 抢先认证(Preemptive Authentication)可以通过下述Ҏ打开.
client.getState().setAuthenticationPreemptive(true);
在这U模式时QHttpClient会主动将basic认证应答信息传给服务器,即在某U情况下服务器可能返回认证失败的应答Q这样做主要是ؓ了减连接的建立。ؓ使每个新建的 HttpState实例都实行抢先认证,可以如下讄pȝ属性?
setSystemProperty(Authenticator.PREEMPTIVE_PROPERTY, "true");

Httpclient实现的抢先认证遵循rfc2617.
2)代理认证(proxy authentication)
除了d信息需单独存放以外Q代理认证与服务器认证几乎一致。用 setProxyCredentials(String realm, Credentials cred)?getProxyCredentials(String realm)设、取d信息?br /> 3)认证Ҏ(authentication schemes)
Basic
是HTTP中规定最早的也是最兼容(?)的方案,遗憾的是也是最不安全的一个方案,因ؓ它以明码传送用户名和密码。它要求一个UsernamePasswordCredentials实例Q可以指定服务器端的讉KI间或采用默认的d信息?br /> Digest
是在HTTP1.1中增加的一个方案,虽然不如Basic得到的Y件支持多Q但q是有广泛的使用。DigestҎ比BasicҎ安全得多Q因它根? ׃通过|络传送实际的密码Q传送的是利用这个密码对从服务器传来的一个随机数(nonce)的加密串。它要求一? UsernamePasswordCredentials实例Q可以指定服务器端的讉KI间或采用默认的d信息?br /> NTLM
q是 HttpClient支持的最复杂的认证协议。它M$设计的一个私有协议,没有公开的规范说明。一开始由于设计的~陷QNTLM的安全性比Digest 差,后来l过一个ServicePack补丁后,安全性则比较Digest高。NTLM需要一个NTCredentials实例. 注意Q由于NTLM不用访问空?realms)的概念,HttpClient利用服务器的域名作访问空间的名字。还需要注意,提供l? NTCredentials的用户名Q不要用域名的前~ - ? "adrian" 是正的Q?"DOMAIN"adrian" 则是错的.
NTLM认证的工作机制与basic和digest有很大的差别。这些差别一般由HttpClient处理Q但理解q些差别有助避免在用NTLM认证时出现错误?br />
  1. 从HttpClientAPI的角度来看,NTLM与其它认证方式一L工作Q差别是需要提?NTCredentials'实例而不?UsernamePasswordCredentials'(其实Q前者只是扩展了后?

  2. 对NTLM认证Q访问空间是q接到的机器的域名,q对多域名主Z有一些麻?只有HttpClientq接中指定的域名才是认证用的域名。徏议将realm设ؓnull以用默认的讄?br />
  3. NTLM只是认证了一个连接而不是一hQ所以每当一个新的连接徏立就要进行一ơ认证,且在认证的过E中保持q接是非帔R要的?因此QNTLM不能同时用于代理认证和服务器认证Q也不能用于http1.0q接或服务器不支持持久连接的情况?/li>

6、重定向


׃技术限Ӟ以及Z?.0发布版API的稳定,HttpClientq不能自动处重定向,但对重定向到同一L、同一端口且采用同一协议的情况HttpClient可以支持。不能自动的处理的情况,包括需要h工交互的情况Q或出httpclient的能力?br /> 当服务器重定向指令指C同的LӞHttpClient只是单地重定向状态码作ؓ应答状态。所有的300?99Q包含两端)的返回码Q都表示是重定向应答。常见的有:

  1. 301 怹Ud. HttpStatus.SC_MOVED_PERMANENTLY

  2. 302 临时Ud. HttpStatus.SC_MOVED_TEMPORARILY

  3. 303 See Other. HttpStatus.SC_SEE_OTHER

  4. 307 临时重定? HttpStatus.SC_TEMPORARY_REDIRECT

当收到简单的重定向时Q程序应从HttpMethod对象中抽取新的URLq将其下载。另?限制一下重定向ơ数是个好的LQ这可以避免递归循环。新的URL可以从头字段Location中抽取,如下Q?
String redirectLocation;
Header locationHeader = method.getResponseHeader("location");
if (locationHeader != null) {
redirectLocation = locationHeader.get();
} else {
// The response is invalid and did not provide the new location for
// the resource. Report an error or possibly handle the response
// like a 404 Not Found error.
}

Ҏ重定向:

  1. 300 多重选择. HttpStatus.SC_MULTIPLE_CHOICES

  2. 304 没有改动. HttpStatus.SC_NO T_MODIFIED

  3. 305 使用代理. HttpStatus.SC_USE_PROXY

7、字W编?character encoding)


一个HTTP协议的请求或应答的头?在http协议中,数据包分 Z部分Q一部分是头部,׃些名值对构成Q一部分是主?body)Q是真正传办理的数据Q如HTML面{)Q,必须以US-ASCII~码Q这是因 为头部不传数据而只描述被要传输的数据的一些信息,一个例外是Q它是数据但是通过头部q行传输的,所以它也要用US-ASCII~码?br /> HTTP数据包的M部分Q可以用M一U方式进行编码,默认是ISO-8859-1Q具体可以用头部字段Content-Type指定。可以利? addRequestHeaderҎQ设定编码方式;? getResponseCharSet取得~码方式。对HTML或XML{类型的文档Q它们的本n的Content-Type也可以指定编码方式,主要? 分两者的作用范围以得到正实的解码?br /> URL的编码标准,由RFC1738指定为,只能是由可打??字节的us-ascii字符l成Q?0-ff不是us-ascii字符Q?0-1F是控制字W,q两个区域中用的字符都须加以~码(encoded)?br />

8、s


HttpClient能自动管?包括允许服务器设|ƈ在需要的时候自动将q回服务器,它也支持手工讄后发送到服务器端。不q的是,对如何处理,有几? 规范互相冲突QNetscape 草案, RFC2109, RFC2965Q而且q有很大数量的Y件商的实C遵@M规范. Z处理q种状况QHttpClient提供了策略驱动的理方式。HttpClient支持的规范有Q?
  1. Netscape 草案Q是最早的规范Q基于rfc2109。尽这个规范与rc2109有较大的差别Q这样做可以与一些服务器兼容?

  2. rfc2109Q? 是w3c发布的第一个官方规范。理ZԌ所有的服务器在处理(版本1)Ӟ都要遵@此规范,正因如此QHttpClient其设ؓ默认的规范。遗憄 是,q个规范太严gQ以致很多服务器不正的实施了该规范或仍在作用Netscape规范。在q种情况下,应用兼容规范?br />
  3. 兼容性规范,设计用来兼容可能多的服务器Q即使它们ƈ没有遵@标准规范。当解析出现问题Ӟ应考虑采用兼容性规范?/li>

RFC2965规范暂时没有被HttpClient支持Q在以后的版本ؓ会加上)Q它定义了版?Qƈ说明了版?的不IRFC2965有意有久取代rfc2109.
在HttpClient中,有两U方法来指定规范的用,
  1. HttpClient client = new HttpClient();
    client.getState().setPolicy(Policy.COMPATIBILITY);
    q种Ҏ讄的规范只对当前的HttpState有效Q参数可取值Policy.COMPATIBILITYQPolicy.NETSCAPE_DRAFT或Policy.RFC2109?br />
  2. System.setProperty("apache.commons.httpclient.spec", "COMPATIBILITY");
    此法指的规范Q对以后每个新徏立的HttpState对象都有效,参数可取?COMPATIBILITY","NETSCAPE_DRAFT"?RFC2109"?br /> 常有不能解析的问题,但更换到兼容规范大都能解冟?br />

9、用HttpClient遇到问题怎么?

  1. 用一个浏览器讉K服务器,以确认服务器应答正常

  2. 如果在代理Q关掉代理试?br />
  3. 另找一个服务器来试试(如果q行着不同的服务器软g更好Q?br />
  4. 查代码是否按教程中讲的思\~写

  5. 讄logU别为debugQ找出问题出现的原因

  6. 打开wiretraceQ来q踪客户端与服务器的通信Q以实问题出现在什么地?br />
  7. 用telnet或netcat手工信息发送到服务器,适合于猜已l找C原因而进行试验时

  8. netcat以监听方式运行,用作服务器以查httpclient如何处理应答的?br />
  9. 利用最新的httpclient试试Qbug可能在最新的版本中修复了

  10. 向邮件列表求帮助

  11. 向bugzilla报告bug.


C物 2008-02-13 22:23 发表评论
]]>
վ֩ģ壺 aƵѹۿƵ| þŮcc98cm| AVӰԺۿ| Ƶ| ޹Ʒþҹ | 9ֻоƷ| ?VƷ| ͵Ƶ߹ۿ99| һɫƬ| һһ߹ۿƵ| Ļ| þþþùƷѿ| 91þ޹˾Ʒɫ| 16Ůǿڵ| ޾ƷۺӰԺ| ԲƵ| ɫaѿ| Ļһҳ| aƬ߲| þ޾ƷĻ| ԻȫƵ߹ۿ | ѾƷӰվ| һƷ| þ޾Ʒ| avƬһ| ձһvr| aëƬƵۿ| AVƷɫ| ߿ѹۿAVҹӰԺ| ޹ŷպƷһ| ޾Ʒ߹ۿ| ձѸƵ| ɫ͵͵ۺav78| ޸ۺ԰Ƶ| һ| պĻһ| ˳77777߲վ| ŷ| gogo߹ۿ| Ů18ëƬˮ| ޹Ʒ˾þ|