修改httpd.conf中文编码
 
AddDefaultCharset GB2312
DefaultLanguage GB2312
AddLanguage zh-cn .cn
下载 mod_jk2.so 并加载mod_jk2.so
 
LoadModule jk2_module modules/mod_jk2.so
在conf目录新建workers2.properties文件
 
 
[shm]
file=${serverRoot}/logs/shm.file
size=1048576
#The socket channel
[channel.socket:localhost:8009]
port=8009
host=127.0.0.1
#define the worker
[ajp13:localhost:8009]
channel=channel.socket:localhost:8009
#uri mapping
[uri:/*.jsp]
worker=ajp13:localhost:8009

虚拟主机
 
<VirtualHost *:80>
    ServerAdmin wweidong@sina.com
    DocumentRoot "I:/Job/Java"
    ServerName localhost
    ErrorLog logs/sdg.com-error_log
    CustomLog logs/sdg.com-access_log common
</VirtualHost>
posted @ 2006-12-18 17:28 edsonjava 阅读(251) | 评论 (0)编辑 收藏
 
Log4j基本使用方法

  Log4j由三个重要的组件构成:日志级别ERROR、WARN、INFO、DEBUG,分别用来指定这条日志信息的重要程度;日志信息的输出目的地指定了日志将打印到控制台还是文件中;而输出格式则控制了日志信息的显示内容。

  一、定义配置文件

  其实您也可以完全不使用配置文件,而是在代码中配置Log4j环境。但是,使用配置文件将使您的应用程序更加灵活。Log4j支持两种配置文件格式,一种是XML格式的文件,一种是Java特性文件(键=值)。下面我们介绍使用Java特性文件做为配置文件的方法:

  1.配置根Logger,其语法为:

  log4j.rootLogger = [ level ] , appenderName, appenderName, …

  其中,level 是日志记录的优先级,分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别,您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序中所有DEBUG级别的日志信息将不被打印出来。 appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。

  2.配置日志信息输出目的地Appender,其语法为:

  log4j.appender.appenderName = fully.qualified.name.of.appender.class
  log4j.appender.appenderName.option1 = value1
  …
  log4j.appender.appenderName.option = valueN

  其中,Log4j提供的appender有以下几种:
  org.apache.log4j.ConsoleAppender(控制台),
  org.apache.log4j.FileAppender(文件),
  org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件),
  org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件),
  org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)

  3.配置日志信息的格式(布局),其语法为:

  log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class
  log4j.appender.appenderName.layout.option1 = value1
  …
  log4j.appender.appenderName.layout.option = valueN

  其中,Log4j提供的layout有以下几种:
  org.apache.log4j.HTMLLayout(以HTML表格形式布局),
  org.apache.log4j.PatternLayout(可以灵活地指定布局模式),
  org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串),
  org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)

  Log4J采用类似C语言中的printf函数的打印格式格式化日志信息,打印参数如下: %m 输出代码中指定的消息

  %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL
  %r 输出自应用启动到输出该log信息耗费的毫秒数
  %c 输出所属的类目,通常就是所在类的全名
  %t 输出产生该日志事件的线程名
  %n 输出一个回车换行符,Windows平台为“\r\n”,Unix平台为“\n”
  %d 输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,比如:%d{yyy MMM dd HH:mm:ss,SSS},输出类似:2002年10月18日 22:10:28,921
  %l 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。举例:Testlog4.main(TestLog4.java:10)

  二、在代码中使用Log4j

  1.得到记录器

  使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息。其语法为:

  public static Logger getLogger( String name)

  通过指定的名字获得记录器,如果必要的话,则为这个名字创建一个新的记录器。Name一般取本类的名字,比如:

  static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )

  2.读取配置文件

  当获得了日志记录器之后,第二步将配置Log4j环境,其语法为:

  BasicConfigurator.configure (): 自动快速地使用缺省Log4j环境。
  PropertyConfigurator.configure ( String configFilename) :读取使用Java的特性文件编写的配置文件。
  DOMConfigurator.configure ( String filename ) :读取XML形式的配置文件。

  3.插入记录信息(格式化日志信息)

  当上两个必要步骤执行完毕,您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方,其语法如下:

  Logger.debug ( Object message ) ;
  Logger.info ( Object message ) ;
  Logger.warn ( Object message ) ;
  Logger.error ( Object message ) ;

posted @ 2006-11-21 17:04 edsonjava 阅读(154) | 评论 (0)编辑 收藏
 

说来奇怪,昨夜调了很久没成功,今天上来第一次就成功了。

这次的实验是为了获得WS提供的一个person复杂对象其中的某一属性。

服务端提供getPerson,getPersons接口。getPerson根据PersonId提供一个Person对象。而Person包含三个属性,personid,firstname,lastname所以说这个实验的主要目的就是去实验一下非纯字符或数字操作的WS服务的客户端怎么做。

具体是这么来做的:

1、在ECLIPSE里新建一个JAVA PROJECT

 

2、在项目名称上点右键,加入add xfire nature将xfire所需要的库导入进来。关于XFIRE的ECLIPSE插件可以参看这篇文章http://xfire.codehaus.org/Eclipse+Plugin

 

3、点击新建->其他,选择xfire的eclipse插件提供的代码生成工具

 

4、填入WSDL的URL以及选择要将代码输出的项目名称

 

5、确定后就能够看到生成的代码了,生成了很多文件,这些都是根据WSDL生成的,因为服务端提供的person是个复杂对象,不是简单的一个加减操作,所以需要对复杂对象进行生成。

这里最关键的是两个文件,PersonWebServiceClient以及PersonWebServicePortType(interface)。

PersonWebServiceImpl是PersonWebServicePortType的实现。

 

6、下面这部当然就是我们自己开始写客户端了,我们写个junit的测试

先将junit库导入到项目中,右键项目名称,选择properties-->java build path-->libraries-->add library-->JUNIT导入JUNIT库,然后就能看到:

准备工作还没有完成,但是先不做了,等一会再回来做。

现在开始写case吧。

我建立了一个命叫motion.test的package,在里面加入文件WebServiceTest.java

package motion.test;

import junit.framework.TestCase;

public class WebServiceTest extends TestCase {

}

现在我们加入test:

 public void testShow(){
  
  PersonWebServiceClient service = new PersonWebServiceClient();
  PersonWebServicePortType client = service.getPersonWebServiceHttpPort();
  
  System.out.print(client.getPerson("1").getFirstName());
  
 }

这个test的目的是想打印出personid为1的那个person的firstname。

现在运行一下,如果不出意外肯定有错误

看下错误怎么说吧:

原来是有些包没导进来。

然后我们再右键点击项目,选xfire那项。

将Commons Codec 和Commons HttpClient前面的勾打上,确定返回,run WebServiceTest.java as junit test

在Console里我们就能看到这么一行:javax.xml.bind.JAXBElement@198cb3d

惊喜了一会突然发现这不是我们要的结果啊,我们是要显示那个personid为1的那个人的firstname,难道他的firstname是这种奇怪的东西吗?

其实这只是xml元素的JAXB的表示形式。如果我们需要得到具体的值,要用getValue()方法,修改刚才的显示语句如下:

System.out.print(client.getPerson("1").getFirstName().getValue());

再次run WebServiceTest.java as junit test

Console里出现:yang

这是便正确的结果。

 

这个实验其实是非常简单的,但是通过这个实验能够看出很多细节是需要去考虑的。

对于选了web service课程或者想了解这方面的内容的人来说,我希望通过这个能够帮助你掌握一些客户端的制作技术。

在工具盛行的今天,做个服务端已经是一项再简单不过的事情了,而客户端要相对麻烦一些。

这篇就是一个入门级的复杂对象客户端的制作过程。我也是刚刚开始学习这方面的知识,所以如果我有什么错误欢迎您来指出,我也很乐意与你讨论这些问题,希望大家都能一点一点的进步。

posted @ 2006-11-13 17:01 edsonjava 阅读(399) | 评论 (0)编辑 收藏
 

常听大家讨论哪个 Java 开发工具比较好,JBuilder,Virtual Cafe ?

今天介绍一个简单易用的 Java 开发,编译,集成,测试工具:Jakarta Ant

他被称为 java 环境里的 make (make 在 C 程序开发里人人皆知)

Java 程序编辑器爱用啥用啥,我喜欢用 UltraEdit。

以 HelloWorld 为例介绍他的使用。

此示例可在此下载:

ftp://cinc.dns2go.com/pub/doc/code/ant/HelloWorld.zip

.下载 ant :(最新版 1.5)

http://jakarta.apache.org/builds/jakarta-ant/release/v1.5/bin/

windows 下请下载 zip 文件

unix 下请下载 tar.gz 文件

.安装 JDK:

安装到 c:/jdk,并确认能找到 c:/jdk/bin/java

.安装 ant:

把 ant 解压到本地硬盘 c:/ant,并确认能找到 c:/ant/bin/ant.bat

.设置环境变量:

JDK_HOME:c:/jdk

ANT_HOME:c:/ant

PATH:在原来的 PATH 开头加上 c:/ant/bin;c:/jdk/bin

注:

windows 下做操作:我的电脑 -> 属性 -> 高级 -> 环境变量 -> 用户变量

每次修改完环境变量,要重新打开 MS-DOS 窗口才能生效

.开始开发:

一个 ant 项目目录结构:

c:/HelloWorld :项目主目录

/src :源程序目录

/classes :编译后的 class 文件目录

/lib :开发项目所需要的类库目录,比如开发数据库时所需要的 jdbc lib(这次没用到)

/jar :打包好的 jar 程序目录(这次没用到)

/build.xml :项目配置文件

1.建立一个项目的主目录

mkdir c:/Helloworld

2.创建项目配置文件:

c:/HelloWorld/builder.xml

-----------------------------------------------------------------------------

-----------------------------------------------------------------------------

3.建立源代码目录,所有的 Java 程序放在里面

mkdir c:/HelloWorld/src

4.创建 HelloWorld.java

c:/HelloWorld/src/HelloWorld.java

-----------------------------------------------------------------------------

/**

* Demo class for run HelloWorld by ANT

*/

public class HelloWorld {

public static void main(String args[]){

System.out.println ("Hello World!");

}

} //EOC

-----------------------------------------------------------------------------

5.编译 HelloWorld

C:/HelloWorld>ant build

Buildfile: build.xml

build:

BUILD SUCCESSFUL

Total time: 2 seconds

说明:

调用 builder.xml 中的 target build

在 c:/HelloWorld/classes 里会出现 HelloWorld.class

此命令会把 src 目录下所有的 java 文件(包括子目录下的)都编译

6.运行 HelloWorld

C:/HelloWorld>ant run

Buildfile: build.xml

build:

run:

[exec] Hello World!

BUILD SUCCESSFUL

Total time: 2 seconds

调用 builder.xml 中的 target run

注意 target run 后的 depends="build",只有 build 成功后 run 才可以被调用

7.清除 class 文件:

C:/HelloWorld>ant clean

Buildfile: build.xml

clean:

[delete] Deleting 1 files from C:/Helloworld/classes

[delete] Deleted 1 directory from C:/Helloworld/classes

BUILD SUCCESSFUL

Total time: 2 seconds

使用 ANT 的好处:

1.相对于其他项目管理工具,只有一个文本配置文件 build.xml,配置简单

2.命令简单,一学就会,ant run, ant clean ...

3.安装简单,占用资源少,只要安装 Jdk, ANT 就可以运行

用 ANT 进行 Java 程序开发,已经成了 Java 界的一个共识。

在此基础上,可以建立更复杂的项目

在以后会继续介绍:

用 ANT 开发 数据库项目

用 ANT 开发 WEB 应用

用 ANT 和 CVS 开发多人项目,并进行项目版本管理。

推荐阅读:

Apache Ant 1.5 Manual

http://jakarta.apache.org/ant/manual/index.html

如果有时间,应该阅读,能发现许多 ant 的强大功能。

posted @ 2006-11-13 16:32 edsonjava 阅读(269) | 评论 (1)编辑 收藏
 
在平时工作中,难免会遇到把 XML 作为数据存储格式。面对目前种类繁多的解决方案,哪个最适合我们呢?在这篇文章中,我对这四种主流方案做一个不完全评测,仅仅针对遍历 XML 这块来测试,因为遍历 XML 是工作中使用最多的(至少我认为)。

  预 备

  测试环境:

  AMD 毒龙1.4G OC 1.5G、256M DDR333、Windows2000 Server SP4、Sun JDK 1.4.1+Eclipse 2.1+Resin 2.1.8,在 Debug 模式下测试。

  XML 文件格式如下:

  <?xml version="1.0" encoding="GB2312"?>
  <RESULT>
  <VALUE>
  <NO>A1234</NO>
  <ADDR>四川省XX县XX镇XX路X段XX号</ADDR>
  </VALUE>
  <VALUE>
  <NO>B1234</NO>
  <ADDR>四川省XX市XX乡XX村XX组</ADDR>
  </VALUE>
  </RESULT>

  测试方法:

  采用 JSP 端调用Bean(至于为什么采用JSP来调用,请参考:http://blog.csdn.net/rosen/archive/2004/10/15/138324.aspx),让每一种方案分别解析10K、100K、1000K、10000K的 XML 文件,计算其消耗时间(单位:毫秒)。

  JSP 文件:

  <%@ page contentType="text/html; charset=gb2312" %>
  <%@ page import="com.test.*"%>

  <html>
  <body>
  <%
  String args[]={""};
  MyXMLReader.main(args);
  %>
  </body>
  </html>

  测 试

  首先出场的是 DOM(JAXP Crimson 解析器)

  DOM 是用与平台和语言无关的方式表示 XML 文档的官方 W3C 标准。DOM 是以层次结构组织的节点或信息片断的集合。这个层次结构允许开发人员在树中寻找特定信息。分析该结构通常需要加载整个文档和构造层次结构,然后才能做任何工作。由于它是基于信息层次的,因而 DOM 被认为是基于树或基于对象的。DOM 以及广义的基于树的处理具有几个优点。首先,由于树在内存中是持久的,因此可以修改它以便应用程序能对数据和结构作出更改。它还可以在任何时候在树中上下导航,而不是像 SAX 那样是一次性的处理。DOM 使用起来也要简单得多。

  另一方面,对于特别大的文档,解析和加载整个文档可能很慢且很耗资源,因此使用其他手段来处理这样的数据会更好。这些基于事件的模型,比如 SAX。

  Bean文件:

  package com.test;

  import java.io.*;
  import java.util.*;
  import org.w3c.dom.*;
  import javax.xml.parsers.*;

  public class MyXMLReader{

  public static void main(String arge[]){
  long lasting =System.currentTimeMillis();
  try{
   File f=new File("data_10k.xml");
   DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
   DocumentBuilder builder=factory.newDocumentBuilder();
   Document doc = builder.parse(f);
   NodeList nl = doc.getElementsByTagName("VALUE");
   for (int i=0;i<nl.getLength();i++){
    System.out.print("车牌号码:" + doc.getElementsByTagName("NO").item(i).getFirstChild().getNodeValue());
    System.out.println(" 车主地址:" + doc.getElementsByTagName("ADDR").item(i).getFirstChild().getNodeValue());
  }
  }catch(Exception e){
   e.printStackTrace();
  }
  System.out.println("运行时间:"+(System.currentTimeMillis() - lasting)+" 毫秒");
  }
  }


  10k消耗时间:265 203 219 172
  100k消耗时间:9172 9016 8891 9000
  1000k消耗时间:691719 675407 708375 739656
  10000k消耗时间:OutOfMemoryError

  接着是 SAX

  这种处理的优点非常类似于流媒体的优点。分析能够立即开始,而不是等待所有的数据被处理。而且,由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中。这对于大型文档来说是个巨大的优点。事实上,应用程序甚至不必解析整个文档;它可以在某个条件得到满足时停止解析。一般来说,SAX 还比它的替代者 DOM 快许多。

   选择 DOM 还是选择 SAX ?

  对于需要自己编写代码来处理 XML 文档的开发人员来说,选择 DOM 还是 SAX 解析模型是一个非常重要的设计决策。

  DOM 采用建立树形结构的方式访问 XML 文档,而 SAX 采用的事件模型。

  DOM 解析器把 XML 文档转化为一个包含其内容的树,并可以对树进行遍历。用 DOM 解析模型的优点是编程容易,开发人员只需要调用建树的指令,然后利用navigation APIs访问所需的树节点来完成任务。可以很容易的添加和修改树中的元素。然而由于使用 DOM 解析器的时候需要处理整个 XML 文档,所以对性能和内存的要求比较高,尤其是遇到很大的 XML 文件的时候。由于它的遍历能力,DOM 解析器常用于 XML 文档需要频繁的改变的服务中。

  SAX 解析器采用了基于事件的模型,它在解析 XML 文档的时候可以触发一系列的事件,当发现给定的tag的时候,它可以激活一个回调方法,告诉该方法制定的标签已经找到。SAX 对内存的要求通常会比较低,因为它让开发人员自己来决定所要处理的tag。特别是当开发人员只需要处理文档中所包含的部分数据时,SAX 这种扩展能力得到了更好的体现。但用 SAX 解析器的时候编码工作会比较困难,而且很难同时访问同一个文档中的多处不同数据。

  Bean文件:

  package com.test;
  import org.xml.sax.*;
  import org.xml.sax.helpers.*;
  import javax.xml.parsers.*;

  public class MyXMLReader extends DefaultHandler {

  java.util.Stack tags = new java.util.Stack();

  public MyXMLReader() {
  super();
  }

  public static void main(String args[]) {
  long lasting = System.currentTimeMillis();
  try {
   SAXParserFactory sf = SAXParserFactory.newInstance();
   SAXParser sp = sf.newSAXParser();
   MyXMLReader reader = new MyXMLReader();
   sp.parse(new InputSource("data_10k.xml"), reader);
  } catch (Exception e) {
   e.printStackTrace();
  }
  System.out.println("运行时间:" + (System.currentTimeMillis() - lasting) + " 毫秒");
  }

  public void characters(char ch[], int start, int length) throws SAXException {
  String tag = (String) tags.peek();
  if (tag.equals("NO")) {
   System.out.print("车牌号码:" + new String(ch, start, length));
  }
  if (tag.equals("ADDR")) {
  System.out.println(" 地址:" + new String(ch, start, length));
  }
  }

  public void startElement(
  String uri,
  String localName,
  String qName,
  Attributes attrs) {
  tags.push(qName);
  }
  }

  10k消耗时间:110 47 109 78
  100k消耗时间:344 406 375 422
  1000k消耗时间:3234 3281 3688 3312
  10000k消耗时间:32578 34313 31797 31890 30328

  然后是 JDOM http://www.jdom.org/

  JDOM 的目的是成为 Java 特定文档模型,它简化与 XML 的交互并且比使用 DOM 实现更快。由于是第一个 Java 特定模型,JDOM 一直得到大力推广和促进。正在考虑通过“Java 规范请求 JSR-102”将它最终用作“Java 标准扩展”。从 2000 年初就已经开始了 JDOM 开发。

  JDOM 与 DOM 主要有两方面不同。首先,JDOM 仅使用具体类而不使用接口。这在某些方面简化了 API,但是也限制了灵活性。第二,API 大量使用了 Collections 类,简化了那些已经熟悉这些类的 Java 开发者的使用。

  JDOM 文档声明其目的是“使用 20%(或更少)的精力解决 80%(或更多)Java/XML 问题”(根据学习曲线假定为 20%)。JDOM 对于大多数 Java/XML 应用程序来说当然是有用的,并且大多数开发者发现 API 比 DOM 容易理解得多。JDOM 还包括对程序行为的相当广泛检查以防止用户做任何在 XML 中无意义的事。然而,它仍需要您充分理解 XML 以便做一些超出基本的工作(或者甚至理解某些情况下的错误)。这也许是比学习 DOM 或 JDOM 接口都更有意义的工作。

  JDOM 自身不包含解析器。它通常使用 SAX2 解析器来解析和验证输入 XML 文档(尽管它还可以将以前构造的 DOM 表示作为输入)。它包含一些转换器以将 JDOM 表示输出成 SAX2 事件流、DOM 模型或 XML 文本文档。JDOM 是在 Apache 许可证变体下发布的开放源码。

  Bean文件:

  package com.test;

  import java.io.*;
  import java.util.*;
  import org.jdom.*;
  import org.jdom.input.*;

  public class MyXMLReader {

  public static void main(String arge[]) {
  long lasting = System.currentTimeMillis();
  try {
   SAXBuilder builder = new SAXBuilder();
   Document doc = builder.build(new File("data_10k.xml"));
   Element foo = doc.getRootElement();
   List allChildren = foo.getChildren();
   for(int i=0;i<allChildren.size();i++) {
    System.out.print("车牌号码:" + ((Element)allChildren.get(i)).getChild("NO").getText());
    System.out.println(" 车主地址:" + ((Element)allChildren.get(i)).getChild("ADDR").getText());
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  System.out.println("运行时间:" + (System.currentTimeMillis() - lasting) + " 毫秒");
  }
  }

  10k消耗时间:125 62 187 94
  100k消耗时间:704 625 640 766
  1000k消耗时间:27984 30750 27859 30656
  10000k消耗时间:OutOfMemoryError

  最后是 DOM4J http://dom4j.sourceforge.net/

  虽然 DOM4J 代表了完全独立的开发结果,但最初,它是 JDOM 的一种智能分支。它合并了许多超出基本 XML 文档表示的功能,包括集成的 XPath 支持、XML Schema 支持以及用于大文档或流化文档的基于事件的处理。它还提供了构建文档表示的选项,它通过 DOM4J API 和标准 DOM 接口具有并行访问功能。从 2000 下半年开始,它就一直处于开发之中。

  为支持所有这些功能,DOM4J 使用接口和抽象基本类方法。DOM4J 大量使用了 API 中的 Collections 类,但是在许多情况下,它还提供一些替代方法以允许更好的性能或更直接的编码方法。直接好处是,虽然 DOM4J 付出了更复杂的 API 的代价,但是它提供了比 JDOM 大得多的灵活性。

  在添加灵活性、XPath 集成和对大文档处理的目标时,DOM4J 的目标与 JDOM 是一样的:针对 Java 开发者的易用性和直观操作。它还致力于成为比 JDOM 更完整的解决方案,实现在本质上处理所有 Java/XML 问题的目标。在完成该目标时,它比 JDOM 更少强调防止不正确的应用程序行为。

  DOM4J 是一个非常非常优秀的Java XML API,具有性能优异、功能强大和极端易用使用的特点,同时它也是一个开放源代码的软件。如今你可以看到越来越多的 Java 软件都在使用 DOM4J 来读写 XML,特别值得一提的是连 Sun 的 JAXM 也在用 DOM4J。

  Bean文件:

  package com.test;

  import java.io.*;
  import java.util.*;
  import org.dom4j.*;
  import org.dom4j.io.*;

  public class MyXMLReader {

  public static void main(String arge[]) {
  long lasting = System.currentTimeMillis();
  try {
   File f = new File("data_10k.xml");
   SAXReader reader = new SAXReader();
   Document doc = reader.read(f);
   Element root = doc.getRootElement();
   Element foo;
   for (Iterator i = root.elementIterator("VALUE"); i.hasNext();) {
    foo = (Element) i.next();
    System.out.print("车牌号码:" + foo.elementText("NO"));
    System.out.println(" 车主地址:" + foo.elementText("ADDR"));
   }
  } catch (Exception e) {
   e.printStackTrace();
  }
  System.out.println("运行时间:" + (System.currentTimeMillis() - lasting) + " 毫秒");
  }
  }

  10k消耗时间:109 78 109 31
  100k消耗时间:297 359 172 312
  1000k消耗时间:2281 2359 2344 2469
  10000k消耗时间:20938 19922 20031 21078

  JDOM 和 DOM 在性能测试时表现不佳,在测试 10M 文档时内存溢出。在小文档情况下还值得考虑使用 DOM 和 JDOM。虽然 JDOM 的开发者已经说明他们期望在正式发行版前专注性能问题,但是从性能观点来看,它确实没有值得推荐之处。另外,DOM 仍是一个非常好的选择。DOM 实现广泛应用于多种编程语言。它还是许多其它与 XML 相关的标准的基础,因为它正式获得 W3C 推荐(与基于非标准的 Java 模型相对),所以在某些类型的项目中可能也需要它(如在 JavaScript 中使用 DOM)。

  SAX表现较好,这要依赖于它特定的解析方式。一个 SAX 检测即将到来的XML流,但并没有载入到内存(当然当XML流被读入时,会有部分文档暂时隐藏在内存中)。

  无疑,DOM4J是这场测试的获胜者,目前许多开源项目中大量采用 DOM4J,例如大名鼎鼎的 Hibernate 也用 DOM4J 来读取 XML 配置文件。如果不考虑可移植性,那就采用DOM4J吧!

posted @ 2006-11-08 11:47 edsonjava 阅读(188) | 评论 (0)编辑 收藏
 

HTTP 1.1状态代码及其含义

  

下表显示了常见的HTTP 1.1状态代码以及它们对应的状态信息和含义。

应当谨慎地使用那些只有HTTP 1.1支持的状态代码,因为许多浏览器还只能够支持HTTP 1.0。如果你使用了HTTP 1.1特有的状态代码,最好能够检查一下请求的HTTP版本号。

状态代码 状态信息 含义
100 Continue 初始的请求已经接受,客户应当继续发送请求的其余部分。(HTTP 1.1新)
101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议(HTTP 1.1新)
200 OK 一切正常,对GET和POST请求的应答文档跟在后面。
201 Created 服务器已经创建了文档,Location头给出了它的URL。
202 Accepted 已经接受请求,但处理尚未完成。
203 Non-Authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝(HTTP 1.1新)。
204 No Content 没有新文档,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的。
205 Reset Content 没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容(HTTP 1.1新)。
206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它(HTTP 1.1新)。
300 Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明。
301 Moved Permanently 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
302 Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。注意,在HTTP1.0中对应的状态信息是“Moved Temporatily”。

出现该状态代码时,浏览器能够自动访问新的URL,因此它是一个很有用的状态代码。

注意这个状态代码有时候可以和301替换使用。例如,如果浏览器错误地请求http://host/~user(缺少了后面的斜杠),有的服务器返回301,有的则返回302。

严格地说,我们只能假定只有当原来的请求是GET时浏览器才会自动重定向。请参见307。

303 See Other 类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取(HTTP 1.1新)。
304 Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取(HTTP 1.1新)。
307 Temporary Redirect 和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是POST,即使它实际上只能在POST请求的应答是303时才能重定向。由于这个原因,HTTP 1.1新增了307,以便更加清除地区分几个状态代码:当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只能跟随对GET请求的重定向。(HTTP 1.1新)
400 Bad Request 请求出现语法错误。
401 Unauthorized 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。
403 Forbidden 资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器上文件或目录的权限设置导致。
404 Not Found 无法找到指定位置的资源。这也是一个常用的应答。
405 Method Not Allowed 请求方法(GET、POST、HEAD、DELETE、PUT、TRACE等)对指定的资源不适用。(HTTP 1.1新)
406 Not Acceptable 指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容(HTTP 1.1新)。
407 Proxy Authentication Required 类似于401,表示客户必须先经过代理服务器的授权。(HTTP 1.1新)
408 Request Timeout 在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。(HTTP 1.1新)
409 Conflict 通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。(HTTP 1.1新)
410 Gone 所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址。它和404的不同在于,返回407表示文档永久地离开了指定的位置,而404表示由于未知的原因文档不可用。(HTTP 1.1新)
411 Length Required 服务器不能处理请求,除非客户发送一个Content-Length头。(HTTP 1.1新)
412 Precondition Failed 请求头中指定的一些前提条件失败(HTTP 1.1新)。
413 Request Entity Too Large 目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头(HTTP 1.1新)。
414 Request URI Too Long URI太长(HTTP 1.1新)。
416 Requested Range Not Satisfiable 服务器不能满足客户在请求中指定的Range头。(HTTP 1.1新)
500 Internal Server Error 服务器遇到了意料不到的情况,不能完成客户的请求。
501 Not Implemented 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求。
502 Bad Gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答。
503 Service Unavailable 服务器由于维护或者负载过重未能应答。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头。
504 Gateway Timeout 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答。(HTTP 1.1新)
505 HTTP Version Not Supported 服务器不支持请求中所指明的HTTP版本。(HTTP 1.1新)
posted @ 2006-11-08 11:25 edsonjava 阅读(229) | 评论 (0)编辑 收藏
 

HttpClient入门

developerWorks
文档选项
将此页作为电子邮件发送

将此页作为电子邮件发送

未显示需要 JavaScript 的文档选项


拓展 Tomcat 应用

下载 IBM 开源 J2EE 应用服务器 WAS CE 新版本 V1.1


级别: 高级

金发华 , 软件工程师,IBM CSDL, IBM
陈樟洪 , 软件工程师,IBM CSDL, IBM

2005 年 11 月 10 日

HttpClient 是 Apache Jakarta Common 下的子项目,可以用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。本文首先介绍 HTTPClient,然后根据作者实际工作经验给出了一些常见问题的解决方法。

HttpClient简介

HTTP 协议可能是现在 Internet 上使用得最多、最重要的协议了,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java.net 包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 Cactus 和 HTMLUnit 都使用了 HttpClient,更多使用 HttpClient 的应用可以参见http://wiki.apache.org/jakarta-httpclient/HttpClientPowered。HttpClient 项目非常活跃,使用的人还是非常多的。目前 HttpClient 版本是在 2005.10.11 发布的 3.0 RC4 。





回页首


HttpClient 功能介绍

以下列出的是 HttpClient 提供的主要的功能,要知道更多详细的功能可以参见 HttpClient 的主页。

  • 实现了所有 HTTP 的方法(GET,POST,PUT,HEAD 等)
  • 支持自动转向
  • 支持 HTTPS 协议
  • 支持代理服务器等

下面将逐一介绍怎样使用这些功能。首先,我们必须安装好 HttpClient。





回页首


HttpClient 基本功能的使用

GET 方法

使用 HttpClient 需要以下 6 个步骤:

1. 创建 HttpClient 的实例

2. 创建某种连接方法的实例,在这里是 GetMethod。在 GetMethod 的构造函数中传入待连接的地址

3. 调用第一步中创建好的实例的 execute 方法来执行第二步中创建好的 method 实例

4. 读 response

5. 释放连接。无论执行方法是否成功,都必须释放连接

6. 对得到后的内容进行处理

根据以上步骤,我们来编写用GET方法来取得某网页内容的代码。

  • 大部分情况下 HttpClient 默认的构造函数已经足够使用。
    HttpClient httpClient = new HttpClient();
    

  • 创建GET方法的实例。在GET方法的构造函数中传入待连接的地址即可。用GetMethod将会自动处理转发过程,如果想要把自动处理转发过程去掉的话,可以调用方法setFollowRedirects(false)。
    GetMethod getMethod = new GetMethod("http://www.ibm.com/");
    

  • 调用实例httpClient的executeMethod方法来执行getMethod。由于是执行在网络上的程序,在运行executeMethod方法的时候,需要处理两个异常,分别是HttpException和IOException。引起第一种异常的原因主要可能是在构造getMethod的时候传入的协议不对,比如不小心将"http"写成"htp",或者服务器端返回的内容不正常等,并且该异常发生是不可恢复的;第二种异常一般是由于网络原因引起的异常,对于这种异常 (IOException),HttpClient会根据你指定的恢复策略自动试着重新执行executeMethod方法。HttpClient的恢复策略可以自定义(通过实现接口HttpMethodRetryHandler来实现)。通过httpClient的方法setParameter设置你实现的恢复策略,本文中使用的是系统提供的默认恢复策略,该策略在碰到第二类异常的时候将自动重试3次。executeMethod返回值是一个整数,表示了执行该方法后服务器返回的状态码,该状态码能表示出该方法执行是否成功、需要认证或者页面发生了跳转(默认状态下GetMethod的实例是自动处理跳转的)等。
    //设置成了默认的恢复策略,在发生异常时候将自动重试3次,在这里你也可以设置成自定义的恢复策略
    getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, 
        		new DefaultHttpMethodRetryHandler()); 
    //执行getMethod
    int statusCode = client.executeMethod(getMethod);
    if (statusCode != HttpStatus.SC_OK) {
      System.err.println("Method failed: " + getMethod.getStatusLine());
    }
    

  • 在返回的状态码正确后,即可取得内容。取得目标地址的内容有三种方法:第一种,getResponseBody,该方法返回的是目标的二进制的byte流;第二种,getResponseBodyAsString,这个方法返回的是String类型,值得注意的是该方法返回的String的编码是根据系统默认的编码方式,所以返回的String值可能编码类型有误,在本文的"字符编码"部分中将对此做详细介绍;第三种,getResponseBodyAsStream,这个方法对于目标地址中有大量数据需要传输是最佳的。在这里我们使用了最简单的getResponseBody方法。
    byte[] responseBody = method.getResponseBody();
    

  • 释放连接。无论执行方法是否成功,都必须释放连接。
    method.releaseConnection();
    

  • 处理内容。在这一步中根据你的需要处理内容,在例子中只是简单的将内容打印到控制台。
    System.out.println(new String(responseBody));
    

下面是程序的完整代码,这些代码也可在附件中的test.GetSample中找到。


												
														package test;
import java.io.IOException;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;

public class GetSample{
  public static void main(String[] args) {
  //构造HttpClient的实例
  HttpClient httpClient = new HttpClient();
  //创建GET方法的实例
  GetMethod getMethod = new GetMethod("http://www.ibm.com");
  //使用系统提供的默认的恢复策略
  getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
    new DefaultHttpMethodRetryHandler());
  try {
   //执行getMethod
   int statusCode = httpClient.executeMethod(getMethod);
   if (statusCode != HttpStatus.SC_OK) {
    System.err.println("Method failed: "
      + getMethod.getStatusLine());
   }
   //读取内容 
   byte[] responseBody = getMethod.getResponseBody();
   //处理内容
   System.out.println(new String(responseBody));
  } catch (HttpException e) {
   //发生致命的异常,可能是协议不对或者返回的内容有问题
   System.out.println("Please check your provided http address!");
   e.printStackTrace();
  } catch (IOException e) {
   //发生网络异常
   e.printStackTrace();
  } finally {
   //释放连接
   getMethod.releaseConnection();
  }
 }
}

												
										

POST方法

根据RFC2616,对POST的解释如下:POST方法用来向目的服务器发出请求,要求它接受被附在请求后的实体,并把它当作请求队列(Request-Line)中请求URI所指定资源的附加新子项。POST被设计成用统一的方法实现下列功能:

  • 对现有资源的注释(Annotation of existing resources)
  • 向电子公告栏、新闻组,邮件列表或类似讨论组发送消息
  • 提交数据块,如将表单的结果提交给数据处理过程
  • 通过附加操作来扩展数据库

调用HttpClient中的PostMethod与GetMethod类似,除了设置PostMethod的实例与GetMethod有些不同之外,剩下的步骤都差不多。在下面的例子中,省去了与GetMethod相同的步骤,只说明与上面不同的地方,并以登录清华大学BBS为例子进行说明。

  • 构造PostMethod之前的步骤都相同,与GetMethod一样,构造PostMethod也需要一个URI参数,在本例中,登录的地址是http://www.newsmth.net/bbslogin2.php。在创建了PostMethod的实例之后,需要给method实例填充表单的值,在BBS的登录表单中需要有两个域,第一个是用户名(域名叫id),第二个是密码(域名叫passwd)。表单中的域用类NameValuePair来表示,该类的构造函数第一个参数是域名,第二参数是该域的值;将表单所有的值设置到PostMethod中用方法setRequestBody。另外由于BBS登录成功后会转向另外一个页面,但是HttpClient对于要求接受后继服务的请求,比如POST和PUT,不支持自动转发,因此需要自己对页面转向做处理。具体的页面转向处理请参见下面的"自动转向"部分。代码如下:
    String url = "http://www.newsmth.net/bbslogin2.php";
    PostMethod postMethod = new PostMethod(url);
    // 填入各个表单域的值
    NameValuePair[] data = { new NameValuePair("id", "youUserName"),				
    new NameValuePair("passwd", "yourPwd") };
    // 将表单的值放入postMethod中
    postMethod.setRequestBody(data);
    // 执行postMethod
    int statusCode = httpClient.executeMethod(postMethod);
    // HttpClient对于要求接受后继服务的请求,象POST和PUT等不能自动处理转发
    // 301或者302
    if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY || 
    statusCode == HttpStatus.SC_MOVED_TEMPORARILY) {
        // 从头中取出转向的地址
        Header locationHeader = postMethod.getResponseHeader("location");
        String location = null;
        if (locationHeader != null) {
         location = locationHeader.getValue();
         System.out.println("The page was redirected to:" + location);
        } else {
         System.err.println("Location field value is null.");
        }
        return;
    }
    

完整的程序代码请参见附件中的test.PostSample





回页首


使用HttpClient过程中常见的一些问题

下面介绍在使用HttpClient过程中常见的一些问题。

字符编码

某目标页的编码可能出现在两个地方,第一个地方是服务器返回的http头中,另外一个地方是得到的html/xml页面中。

  • 在http头的Content-Type字段可能会包含字符编码信息。例如可能返回的头会包含这样子的信息:Content-Type: text/html; charset=UTF-8。这个头信息表明该页的编码是UTF-8,但是服务器返回的头信息未必与内容能匹配上。比如对于一些双字节语言国家,可能服务器返回的编码类型是UTF-8,但真正的内容却不是UTF-8编码的,因此需要在另外的地方去得到页面的编码信息;但是如果服务器返回的编码不是UTF-8,而是具体的一些编码,比如gb2312等,那服务器返回的可能是正确的编码信息。通过method对象的getResponseCharSet()方法就可以得到http头中的编码信息。
  • 对于象xml或者html这样的文件,允许作者在页面中直接指定编码类型。比如在html中会有<meta http-equiv="Content-Type" content="text/html; charset=gb2312"/>这样的标签;或者在xml中会有<?xml version="1.0" encoding="gb2312"?>这样的标签,在这些情况下,可能与http头中返回的编码信息冲突,需要用户自己判断到底那种编码类型应该是真正的编码。

自动转向

根据RFC2616中对自动转向的定义,主要有两种:301和302。301表示永久的移走(Moved Permanently),当返回的是301,则表示请求的资源已经被移到一个固定的新地方,任何向该地址发起请求都会被转到新的地址上。302表示暂时的转向,比如在服务器端的servlet程序调用了sendRedirect方法,则在客户端就会得到一个302的代码,这时服务器返回的头信息中location的值就是sendRedirect转向的目标地址。

HttpClient支持自动转向处理,但是象POST和PUT方式这种要求接受后继服务的请求方式,暂时不支持自动转向,因此如果碰到POST方式提交后返回的是301或者302的话需要自己处理。就像刚才在POSTMethod中举的例子:如果想进入登录BBS后的页面,必须重新发起登录的请求,请求的地址可以在头字段location中得到。不过需要注意的是,有时候location返回的可能是相对路径,因此需要对location返回的值做一些处理才可以发起向新地址的请求。

另外除了在头中包含的信息可能使页面发生重定向外,在页面中也有可能会发生页面的重定向。引起页面自动转发的标签是:<meta http-equiv="refresh" content="5; url=http://www.ibm.com/us">。如果你想在程序中也处理这种情况的话得自己分析页面来实现转向。需要注意的是,在上面那个标签中url的值也可以是一个相对地址,如果是这样的话,需要对它做一些处理后才可以转发。

处理HTTPS协议

HttpClient提供了对SSL的支持,在使用SSL之前必须安装JSSE。在Sun提供的1.4以后的版本中,JSSE已经集成到JDK中,如果你使用的是JDK1.4以前的版本则必须安装JSSE。JSSE不同的厂家有不同的实现。下面介绍怎么使用HttpClient来打开Https连接。这里有两种方法可以打开https连接,第一种就是得到服务器颁发的证书,然后导入到本地的keystore中;另外一种办法就是通过扩展HttpClient的类来实现自动接受证书。

方法1,取得证书,并导入本地的keystore:

  • 安装JSSE (如果你使用的JDK版本是1.4或者1.4以上就可以跳过这一步)。本文以IBM的JSSE为例子说明。先到IBM网站上下载JSSE的安装包。然后解压开之后将ibmjsse.jar包拷贝到<java-home>\lib\ext\目录下。
  • 取得并且导入证书。证书可以通过IE来获得:

    1. 用IE打开需要连接的https网址,会弹出如下对话框:



    2. 单击"View Certificate",在弹出的对话框中选择"Details",然后再单击"Copy to File",根据提供的向导生成待访问网页的证书文件



    3. 向导第一步,欢迎界面,直接单击"Next",



    4. 向导第二步,选择导出的文件格式,默认,单击"Next",



    5. 向导第三步,输入导出的文件名,输入后,单击"Next",



    6. 向导第四步,单击"Finish",完成向导



    7. 最后弹出一个对话框,显示导出成功



  • 用keytool工具把刚才导出的证书倒入本地keystore。Keytool命令在<java-home>\bin\下,打开命令行窗口,并到<java-home>\lib\security\目录下,运行下面的命令:

    																
    																		keytool -import -noprompt -keystore cacerts -storepass changeit -alias yourEntry1 -file your.cer
    
    																
    														

    其中参数alias后跟的值是当前证书在keystore中的唯一标识符,但是大小写不区分;参数file后跟的是刚才通过IE导出的证书所在的路径和文件名;如果你想删除刚才导入到keystore的证书,可以用命令:

    																
    																		keytool -delete -keystore cacerts -storepass changeit -alias yourEntry1
    
    																
    														

  • 写程序访问https地址。如果想测试是否能连上https,只需要稍改一下GetSample例子,把请求的目标变成一个https地址。
    GetMethod getMethod = new GetMethod("https://www.yourdomain.com");
    

    运行该程序可能出现的问题:

    1. 抛出异常java.net.SocketException: Algorithm SSL not available。出现这个异常可能是因为没有加JSSEProvider,如果用的是IBM的JSSE Provider,在程序中加入这样的一行:

     if(Security.getProvider("com.ibm.jsse.IBMJSSEProvider") == null)
     Security.addProvider(new IBMJSSEProvider());
     

    或者也可以打开<java-home>\lib\security\java.security,在行

    security.provider.1=sun.security.provider.Sun
    security.provider.2=com.ibm.crypto.provider.IBMJCE
    

    后面加入security.provider.3=com.ibm.jsse.IBMJSSEProvider

    2. 抛出异常java.net.SocketException: SSL implementation not available。出现这个异常可能是你没有把ibmjsse.jar拷贝到<java-home>\lib\ext\目录下。

    3. 抛出异常javax.net.ssl.SSLHandshakeException: unknown certificate。出现这个异常表明你的JSSE应该已经安装正确,但是可能因为你没有把证书导入到当前运行JRE的keystore中,请按照前面介绍的步骤来导入你的证书。

方法2,扩展HttpClient类实现自动接受证书

因为这种方法自动接收所有证书,因此存在一定的安全问题,所以在使用这种方法前请仔细考虑您的系统的安全需求。具体的步骤如下:

  • 提供一个自定义的socket factory(test.MySecureProtocolSocketFactory)。这个自定义的类必须实现接口org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory,在实现接口的类中调用自定义的X509TrustManager(test.MyX509TrustManager),这两个类可以在随本文带的附件中得到
  • 创建一个org.apache.commons.httpclient.protocol.Protocol的实例,指定协议名称和默认的端口号
    Protocol myhttps = new Protocol("https", new MySecureProtocolSocketFactory (), 443);
    

  • 注册刚才创建的https协议对象
    Protocol.registerProtocol("https ", myhttps);
    

  • 然后按照普通编程方式打开https的目标地址,代码请参见test.NoCertificationHttpsGetSample

处理代理服务器

HttpClient中使用代理服务器非常简单,调用HttpClient中setProxy方法就可以,方法的第一个参数是代理服务器地址,第二个参数是端口号。另外HttpClient也支持SOCKS代理。


												
														httpClient.getHostConfiguration().setProxy(hostName,port);

												
										





回页首


结论

从上面的介绍中,可以知道HttpClient对http协议支持非常好,使用起来很简单,版本更新快,功能也很强大,具有足够的灵活性和扩展性。对于想在Java应用中直接访问http资源的编程人员来说,HttpClient是一个不可多得的好工具。





回页首


参考资料

  • Commons logging包含了各种各样的日志API的实现,读者可以通过站点http://jakarta.apache.org/commons/logging/得到详细的内容

  • Commons codec包含了一些一般的解码/编码算法。包含了语音编码、十六进制、Base64和URL编码等,通过http://jakarta.apache.org/commons/codec/可以得到详细的内容

  • rfc2616是关于HTTP/1.1的文档,可以在http://www.faqs.org/rfcs/rfc2616.html上得到详细的内容,另外rfc1945是关于HTTP/1.0的文档,通过http://www.faqs.org/rfcs/rfc1945.html可以得到详细内容

  • SSL――SSL 是由 Netscape Communications Corporation 于 1994 年开发的,而 TLS V1.0 是由 Internet Engineering Task Force(IETF)定义的标准,它基于 SSL V3.0,并且在使用的加密算法上与其有些许的不同。例如,SSL 使用 Message Authentication Code(MAC)算法来生成完整性校验值,而 TLS 应用密钥的 Hashing for Message Authentication Code(HMAC)算法。

  • IBM JSSE提供了SSL(Secure Sockets Layer)和TLS(Transport Layer Security)的java实现,在http://www-03.ibm.com/servers/eserver/zseries/software/java/jsse.html中可以得到详细的信息

  • Keytool是一个管理密钥和证书的工具。关于它详细的使用信息可以在http://www.doc.ic.ac.uk/csg/java/1.3.1docs/tooldocs/solaris/keytool.html上得到

  • HTTPClient的主页是http://jakarta.apache.org/commons/httpclient/,你可以在这里得到关于HttpClient更加详细的信息
posted @ 2006-11-08 11:21 edsonjava 阅读(273) | 评论 (0)编辑 收藏
 


//以下部分为通过AJAX读取商品信息
var req;

function Change_Select()
{
    var useTypeID=document.getElementById("msgtype1").value;
 var flowerTypeID=document.getElementById("msgtype2").value;
 var flowerPriceID=document.getElementById("msgtype3").value;
 var url="/12580/jsp/ShowProductServlet?msgtype1="+ useTypeID +"&msgtype2="+flowerTypeID+"&msgtype3="+flowerPriceID;
     if(window.XMLHttpRequest)
        {
            req=new XMLHttpRequest();
        }else if(window.ActiveXObject)
        {
            req=new ActiveXObject("Microsoft.XMLHTTP");
        }
       
        if(req)
        {
            req.open("GET",url,true);
            req.onreadystatechange = callback;
            req.send(null);
        }
}

function callback()
{
    if(req.readyState == 4)
    {
        if(req.status == 200)
        {
           var dataTableBody=document.getElementById("tbProduct");
           dataTableBody.innerHTML=req.responseText;
        }else{
            alert("Not able to retrieve description:"+req.statusText);
        }
    }
}

 


//--------------------------------------------
//以下部分为通过AJAX动态显示小窗口内容

function distChange(htmlStr){
 distHelp.innerHTML = htmlStr;
}

var req1;

function Change_Select1()

    var cityID=document.getElementById("stage2").value.substr(0,document.getElementById("stage2").value.indexOf("/"));
 var url="/12580/jsp/SelectCityChangeServlet?isFront=1&id="+cityID;
     if(window.XMLHttpRequest)
        {
            req1=new XMLHttpRequest();
        }else if(window.ActiveXObject)
        {
            req1=new ActiveXObject("Microsoft.XMLHTTP");
        }
       
        if(req1)
        {
            req1.open("GET",url,true);
            req1.onreadystatechange = callback1;
            req1.send(null);
        }
}

function callback1()
{
    if(req1.readyState == 4)
    {
        if(req1.status == 200)
        {
           var dataTableBody=document.getElementById("distHelp");
           dataTableBody.innerHTML=req1.responseText;
        }else{
            alert("Not able to retrieve description:"+req1.statusText);
        }
    }
}

posted @ 2006-10-27 23:55 edsonjava 阅读(594) | 评论 (0)编辑 收藏
 
1.用keytool生成server.keystore文件:
C:\Documents and Settings\new>keytool -genkey -alias tc-ssl -keyalg RSA -keystor
e c:\server.keystore -validity 3650

生成完后放入C:\jboss-3.2.6\server\default\conf中。

2。配置server.xml文件
<!-- SSL/TLS Connector configuration using the admin devl guide keystore-->
      <Connector port="8443" address="${jboss.bind.address}"
           maxThreads="100" minSpareThreads="5" maxSpareThreads="15"
           scheme="https" secure="true" clientAuth="false"
           keystoreFile="${jboss.server.home.dir}/conf/server.keystore"
           keystorePass="111111" sslProtocol = "TLS" />
3。访问https://localhost:8443/jmx-console/index.jsp,可以了。
同时http://localhost:8080/jmx-console/index.jsp也可以访问,
如果将http转向到https: 修改WEB应用的web.xml
=========web.xml==================
<security-constraint>
     <web-resource-collection>
       <web-resource-name>HtmlAdaptor</web-resource-name>
       <description>An example security config that only allows users with the
         role JBossAdmin to access the HTML JMX console web application
       </description>
       <url-pattern>/</url-pattern>
       <!-- <http-method>GET</http-method>
       <http-method>POST</http-method> -->
     </web-resource-collection>
     <!--<auth-constraint>
       <role-name>JBossAdmin</role-name>
     </auth-constraint> -->
     <user-data-constraint>
            <description>Protection should be CONFIDENTIAL</description>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
   </security-constraint>
posted @ 2006-07-20 23:15 edsonjava 阅读(862) | 评论 (0)编辑 收藏
 
     摘要: 这些天稍微玩了一下 Axis ,以前做 WebServices 都使用 JBuilder ,感觉做 WebServices 如此简单,现在自己手动做,原来也是如此简单。高兴之余写一个简单的初学手册,就算是学习成果吧。当然对 Axis ...  阅读全文
posted @ 2006-07-14 17:23 edsonjava 阅读(250) | 评论 (0)编辑 收藏
仅列出标题
共7页: 上一页 1 2 3 4 5 6 7 下一页