2007年5月30日星期三

三只小猪

有一天要狼吃三只小猪,三只小猪有两只在门口,一只在房顶,猪A和猪B在门口,猪C在房顶,猪A叫"谁"。猪B叫"哪儿",猪C叫"什么"。于是精彩的对话就有了。
狼:你是谁?
猪A:对~我是谁!
狼:什么?
猪A:我不是"什么",什么在屋顶````
狼:我问你的名字叫什么?
猪A:我叫"谁",什么在屋顶上。
狼又问猪B
狼:你是谁?
猪B:我不是"谁",他是"谁"〈指着猪A〉
狼:你认识它?
猪B:是的
狼:什么?
猪B:"什么"在屋顶!
狼:哪儿?
猪B:"哪儿"是我
狼:谁?
猪B:他是"谁"<又指了下猪A>。
狼:我哪知道!
猪B:你找"谁"。
狼:什么?
猪B:"什么"在屋顶。
狼;哪儿/
猪B;"哪儿"是我!
狼:谁?
猪B:我不是"谁"。他是"谁"。
狼:你怎么@#¥%*^~.。。。(之乎者也云云哉)
猪A和猪B:"什么"是我们的爸爸~
狼;什么?是你们爸爸
猪B:不是。什么在上面。
狼受不了了仰天长叹:为什么?
猪A,B,C:"为什么"是我们爷爷
狼:什么?
猪A:不是,我们爷爷是"为什么"
狼:为什么?
猪A:是!
狼:是什么?
猪A;不,"为什么"
狼:谁?
猪A:我是"谁"!
狼:你是谁?
猪A:对!我是"谁"
狼:什么?
猪A,B:"什么"在屋顶!
狼:``````````````````````````````死了

2007年5月29日星期二

有一个躲猫猫社团,他们团长现在还没找到

 
  一个人骑摩托车喜欢反穿衣服,就是把口子在后面扣上,可以挡风。一天他酒后驾驶,翻了,一头栽在路旁。警察赶到。
  
  警察甲:好严重的车祸。
  
  警察乙:是啊,脑袋都撞到后面去了。
  
  警察甲:嗯,还有呼吸,我们帮他把头转回来吧。
  
  警察乙:好.....一、二使劲,转回来了。
  
  警察甲:嗯,没有呼吸了.......
百万富翁开着豪华的加长"林肯"轿车经过一个村落时,看见路旁有两个乞丐正在拔草吃,百万富翁随即停下车。
      
      "你们为什么吃草?"
      
      "我们实在是没有钱......"一个乞丐答道。
      
      "真是的,上车吧,到我家去。"
      
      "我家里还有老婆和两个孩子......"一个乞丐嘟囔道。
      
      "把他们叫来1富翁指了指另一个乞丐。"还有你,把你的家属也叫来。"
      
      "我家人口可多,除了老婆外,还有五个孩子。"另一个乞丐说道。
      
      "没关系,都叫来,快去1
      
      就这样,两个乞丐和他们的家属都上了车,好在是加长车。行使途中,一个乞丐的老婆感激的说道:"老板,您人真好,连我们这样的贫穷的人您都能请到家."
      
      百万富翁答道:"没什么,我刚刚从国外回来,家宅一直没人照看,院子里的草坪可能有一米多高了,你们可以吃个够
熊和兔子在森林里,捡到一个瓶子,打开瓶子,冒出一个仙人,仙人说,谢谢你们放我出来,我能满足你们每个人的3个愿望。
  
  熊说:我希望这个森林里除我以外都是母熊。好,仙人帮他实现了愿望。
  熊又说:不,我希望全世界除我以外都是母熊。好,仙人帮他实现了愿望。
  熊最后说:我希望这些母熊都爱我。好,仙人实现了他的愿望。
  
  接下来是兔子。
  兔子说:我要一辆小摩托。仙人给了兔子一辆摩托。
  兔子又说:我要一定安全帽。仙人给了兔子一顶安全帽。
  兔子最后说:我希望这只熊是个同性恋。
  
有一天,魔王抓走公主,公主一直在叫"救命".
  魔王:你尽管叫破喉咙吧,没有人会来救你的!
  公主:破喉咙!破喉咙!
  没有人:公主,我来救你了!
  魔王:说曹操曹操到!
  曹操:魔王,你叫我干嘛?
  魔王:哇呀!看到鬼了!
  鬼:呵~被发现了!
  呵:胡说,谁发现我了?
  谁:关我屁事!
  魔王:oh~my god!
  上帝:谁叫我!?
  谁:没有人叫你啊!
  没有人:我哪有!!
  中国人法国人英国人在沙漠里走,这时他们遇见了个魔鬼。魔鬼说可以满足他们一人三个愿望。英国人:我要很多很多的钱。得到很多很多的钱。我还要很多很多的钱。又得到很多很多的钱。我想回到英国的老家去。于是英国人就回去了。
  法国人:我要很多很多的美女。得到很多很多的美女。我还要很多很多的美女。又得到很多很多的美女。我想去我法国的住所。于是法国人也回去了。
  中国人:我要二锅头。得到一瓶二锅头。我还要二锅头。又得到瓶二锅头。我有点想那个英国人和那个法国人了。于是三个人继续在沙漠里面走。
  他们又走又遇见个魔鬼。他说他是刚才魔鬼的徒弟,只能满足他们一人两个愿望。于是法国人和英国人都要中国人先说。中国人说我要二锅头。得到二锅头。他又说好了,没事了,你可以走了。法国人和英国人……
  
  他们继续在沙漠里走。遇见一个魔鬼,说是徒弟的徒弟,只能满足一人一个愿望。法国人:中国人说的不算!英国人:中国人说的不算!中国人:我希望英国人可以回老家,法国人能回自己的住所不要再和我一起在这里受苦了。法国人和英国人……
  他们只有继续在沙漠走。又遇见一个说是徒弟的徒弟的徒弟的魔鬼,能满足他们共同的愿望。法国人:我再也不要看见中国人了!英国人:我再也不要看见中国人了!中国人:他们说的都不算。
  还是最喜欢小白兔系列:(强烈推荐)
    蚂蚁在森林里走,突然遇到一只大象,蚂蚁连忙一头钻进土里,伸出一只腿。
    小白兔见了很好奇,问: 你在干什么?
    蚂蚁悄悄对它说:
    嘘……别出声,看我绊丫一跟头……


一天,袋鼠开着车在乡村小路上转悠,突然看到小白兔在路中央,耳朵及身体几乎完全趴在地上似乎在听什么...
      于是..袋鼠停下车很好奇地问:"小白兔,请问一下你在听什么?"
      "半小时前这里有一辆大货车经过..."
      "哇靠..这么神!..你是怎么知道的?.."
      "他XX的!我的脖子和腿就是这么断的.."


长颈鹿说:"小兔子,真希望你能知道有一个长脖子是多么的好。无论什么好吃的东西,我吃的时候都会慢慢的通过我的长脖子,那美味可以长时间的享受。"
      小白兔毫无表情的看着他。
      "并且,在夏天,那凉水慢慢的流过我的长脖子,是那么的可口。有个长脖子真是太好了!小白兔,你能想象吗?"
      小白兔慢悠悠地说:"你吐过吗?"

2007年5月28日星期一

郭德纲相声

现在中国日本人挺多, 我挺讨厌日本人的。我住的地方就有不少日本人。
其中有一对夫妻,别看日本人一般都不高不过这对夫妻特高 属于日本人里特高的了,男的1.2米
女的1.1米。他们还老玩高尚的运动,爱打高尔夫球,没事的时候俩人老拿根小棍打小钢珠 打完了再捡去,这球打出去10米 俩人得半天才能捡回来。
这一次打完了去找 发现把人家玻璃打碎了隔着玻璃一看,里面有个古董花瓶也打碎了,他们那个小球就在旁边地上。俩人赶紧去敲门,看见里面有个男的,就说:对不起,我们打球不
小心把玻璃和那个古董都打碎了,我们来赔礼道歉。那男的说了,不用赔礼道歉,我得谢谢你们两位。俩日本人不明白了,这怎么回事?
那男的说了,我不是普通人,我是个神仙我一直在那个花瓶里呆着,今天你们把我救了,花瓶不碎我出不来。嗬,两口子高兴,对那神仙说,都说救了神仙能许愿,能帮助我们什么事吗?神仙说,行啊,你们有什么要求就提吧。
那男的就说了,我想要中国的土地和资源,您看行吗?神仙说,行等你回家就有了。那女的又说了,我想要中国所有的黄金和珠宝。神仙说,行回家以后就有黄金和
珠宝了。这时候,神仙说了,我这神仙法力有限,我只能答应你们1人1个我还得自己留1个,你们能满足我吗?这两口子说,没问题我们日本人最讲诚信的我们答
应你,你说吧。神仙说,我在花瓶里1000年了,我今天看见你夫人很高兴,希望能不能和你的夫人一起在床上躺一会。日本男人很不高兴说,你得再加5元钱。神仙说好,你回家钱就在你床上。神仙领着这女的就进屋去了。
这男的就在外面等着,等了2小时门开了,神仙和那夫人都出来了,坐下休息,神仙抽烟说,你们多大岁数了?日本男的说,我们一样
都27了。神仙说,27还这么缺心眼,还相信世界上有神仙?
说完观众叫好。郭大师说,相声是劝人向善,但是做为演员,有义务宣传爱国主义精神。

2007年5月23日星期三

辞职

今天辞职了,在这里工作了三年,宴席终于散了,新的开始即将来临

2007年5月15日星期二

一种新的选择----stax创建XML文档

Streaming API for XML (StAX) 不仅能解析 XML 文档,而且可以把 XML 文档写入一个输出流。这篇技巧展示了客户应用程序如何使用底层的、基于指针的 StAX API 有效地创建 XML 文档。

直到最近,程序员通过编程创建 XML 文档还只有两种选择。一种是把序列化的 XML 内容写入输出流,第二种是使用 DOM。

这 两种方法都有严重的缺陷。对于第一种情况,程序员完全负责保证结果文档是格式正规的。程序员必须处理其中的细节,比如起始标签和结束标签的匹配,以及字符 内容中特殊字符的转义,如小于号(<)和逻辑与(&)。这可能造成程序的实现冗长乏味而且容易出错。另一方面,尽管 DOM 把程序员从这种沉重的负担中解放出来,但是引入了巨大的开销:在序列化到输出流之前,整个文档必须首先在内存中构造一棵节点树。

进入 StAX

Streaming API for XML (StAX) 彻底改变这一切。与 Simple API for XML (SAX) 不同,StAX 提供了编写 XML 文档的 API。更具体地说,它提供了两种 API:底层的、基于指针的 API( XMLStreamWriter )和高级的、基于事件的 API( XMLEventWriter )。基于指针的 API 最适合用于数据绑定的情况(比如从应用程序数据创建文档),而基于事件的 API 则通常用于管道式的情况,从输入文档中的数据构造新的文档。

下面的例子是使用基于指针的 API 实现的。(我将在下篇技巧中讨论基于事件的 API。)基于指针的 API 为创建 XML 信息集中的不同元素提供了各种专门的方法,比如元素、属性、处理指令、数据类型声明和字符内容。这些方法解决了许多格式化问题。比如, writeCharacters() 方法自动转义像小于号(<)、大于号(>)和逻辑与(&)这样的特殊字符。而 writeEndDocument() 则自动关闭所有打开的结构。因此即使把本例中最后一次对 writeEndElement() 的调用注释掉也没有关系。

StAX 甚至可以为没有正式声明的名称空间生成名称空间前缀。但是只有在输出工厂的 javax.xml.stream.isPrefixDefaulting 属性设为 true 时才会这么做。如果该属性被设为 false ,您就必须明确地声明每个名称空间前缀,并对每个名称空间使用 setPrefix()writeNamespace() 方法。清单 1 中,我已经把这些方法调用注释掉了,因为我已经把前缀默认设置为 true



清单 1. 编写文档
import javax.xml.stream.*;
public class XMLWriter {
// Namespaces
private static final String GARDENING = "
http://com.bdaum.gardening";
private static final String XHTML = "http://www.w3.org/1999/xhtml";
public static void main(String[] args) throws XMLStreamException {


// Create an output factory
XMLOutputFactory xmlof = XMLOutputFactory.newInstance();
// Set namespace prefix defaulting for all created writers
xmlof.setProperty("javax.xml.stream.isPrefixDefaulting
",Boolean.TRUE);

// Create an XML stream writer
XMLStreamWriter xmlw =
xmlof.createXMLStreamWriter(System.out);
// Write XML prologue
xmlw.writeStartDocument();

// Write a processing instruction
xmlw.writeProcessingInstruction(
"xml-stylesheet href='catalog.xsl' type='text/xsl'");
// Now start with root element
xmlw.writeStartElement("product");
// Set the namespace definitions to the root element
// Declare the default namespace in the root element
xmlw.writeDefaultNamespace(GARDENING);

// Writing a few attributes
xmlw.writeAttribute("productNumber","3923-1");
xmlw.writeAttribute("name","Nightshadow");
// Declare XHTML prefix
// xmlw.setPrefix("xhtml",XHTML);
// Different namespace for description element
xmlw.writeStartElement(XHTML,"description");
// Declare XHTML namespace in the scope of the description element

// xmlw.writeNamespace("xhtml",XHTML);
xmlw.writeCharacters(
"A tulip of almost black color. nBlossoms in April & May");
xmlw.writeEndElement();
// Shorthand for empty elements

xmlw.writeEmptyElement("supplier");
xmlw.writeAttribute("name","Floral22");
// xmlw.writeEndElement();
// Write document end. This closes all open structures

xmlw.writeEndDocument();
// Close the writer to flush the output
xmlw.close();
}
}

注意,StAX 不能保证文档的格式正规性。仍然可能生成违反 XML 推荐标准的文档,比如一个文档中有多个根元素或者多个 XML 序言,标签名和属性名中包含空格或 XML 不支持的字符。StAX 实现可以检查这些问题,但并不要求这么做(参考实现中就没有这样做)。尽管如此,StAX XMLStreamWriter 对于输出原始 XML 数据仍然是一个很大的改进,而且开销只是 DOM 的一个零头。





回页首


结束语

这篇技巧说明了如何使用 StAX 基于指针的 API 有效地编写 XML 文档。在下一篇文章中,我将介绍如何使用基于事件的 API 合并两个 XML 文档。

2007年5月13日星期日

dom4j(Version 1.6.1)快速入门

Parsing XML

或许你想要做的第一件事情就是解析一个某种类型的XML文档,用dom4j很容易做到。请看下面的示范代码:

import java.net.URL;

import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.io.SAXReader;

public class Foo {

  public Document parse(URL url) throws DocumentException {
    SAXReader reader = new SAXReader();
    Document document = reader.read(url);
    return document;
  }
}

使用迭代器(Iterators)

我们可以通过多种方法来操作XML文档,这些方法返回java里标准的迭代器(Iterators)。例如:

public void bar(Document document) throws DocumentException {
  Element root = document.getRootElement();
  //迭代根元素下面的所有子元素
  for ( Iterator i = root.elementIterator(); i.hasNext(); ) {
    Element element = (Element) i.next();
    //处理代码
  }

  //迭代根元素下面名称为"foo"的子元素
  for ( Iterator i = root.elementIterator( "foo" ); i.hasNext(); ) {
    Element foo = (Element) i.next();
    //处理代码
  }

  // 迭代根元素的属性attributes)元素
  for ( Iterator i = root.attributeIterator(); i.hasNext(); ) {
    Attribute attribute = (Attribute) i.next();
    // do something
  }
}

强大的XPath导航

在dom4j中XPath可以表示出在XML树状结构中的Document或者任意的节点(Node)(例如:Attribute,Element 或者 ProcessingInstruction等)。它可以使在文档中复杂的操作仅通过一行代码就可以完成。例如:

public void bar(Document document) {
  List list = document.selectNodes( "//foo/bar" );

  Node node = document.selectSingleNode( "//foo/bar/author" );

  String name = node.valueOf( "@name" );
}

如果你想得到一个XHTML文档中的所有超文本链接(hypertext links)你可以使用下面的代码:

public void findLinks(Document document) throws DocumentException {

  List list = document.selectNodes( "//a/@href" );

  for (Iterator iter = list.iterator(); iter.hasNext(); ) {
    Attribute attribute = (Attribute) iter.next();
    String url = attribute.getValue();
  }
}

如果你需要关于XPath语言的任何帮助,我们强烈推荐这个站点Zvon tutorial他会通过一个一个的例子引导你学习。

快速遍历(Fast Looping)


如果你不得不遍历一个非常大的XML文档,然后才去执行,我们建议你使用快速遍历方法(fast looping method),它可以避免为每一个循环的节点创建一个迭代器对象,如下所示:

public void treeWalk(Document document) {
  treeWalk( document.getRootElement() );
}

public void treeWalk(Element element) {
  for ( int i = 0, size = element.nodeCount(); i < size; i++ ) {
    Node node = element.node(i);
    if ( node instanceof Element ) {
      treeWalk( (Element) node );
    }
    else {
      // do something....
    }
  }
}

生成一个新的XML文档对象

在dom4j中你可能常常希望用程序生成一个XML文档对象,下面的程序为你进行了示范:

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;

public class Foo {

  public Document createDocument() {
    Document document = DocumentHelper.createDocument();
    Element root = document.addElement( "root" );

    Element author1 = root.addElement( "author" )
              .addAttribute( "name", "James" )
              .addAttribute( "location", "UK" )
              .addText( "James Strachan" );

    Element author2 = root.addElement( "author" )
              .addAttribute( "name", "Bob" )
              .addAttribute( "location", "US" )
              .addText( "Bob McWhirter" );

    return document;
  }
}

将一个文档对象写入文件中

将一个文档对象写入Writer对象的一个简单快速的途径是通过write()方法。

FileWriter out = new FileWriter( "foo.xml" );
document.write( out );

如果你想改变输出文件的排版格式,比如你想要一个漂亮的格式或者是一个紧凑的格式,或者你想用Writer 对象或者OutputStream 对象来操作,那么你可以使用XMLWriter 类。

import org.dom4j.Document;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

public class Foo {

  public void write(Document document) throws IOException {

    // 写入文件
    XMLWriter writer = new XMLWriter(new FileWriter( "output.xml" ));
    writer.write( document );
    writer.close();


    // 以一种优雅的格式写入System.out对象
    OutputFormat format = OutputFormat.createPrettyPrint();
    writer = new XMLWriter( System.out, format );
    writer.write( document );

    // 以一种紧凑的格式写入System.out对象
    format = OutputFormat.createCompactFormat();
    writer = new XMLWriter( System.out, format );
    writer.write( document );
  }
}

转化为字符串,或者从字符串转化

如果你有一个文档(Document)对象或者任何一个节点(Node)对象的引用(reference),象属性(Attribute)或者元素(Element),你可以通过asXML()方法把它转化为一个默认的XML字符串:

Document document = ...;
String text = document.asXML();

如果你有一些XML内容的字符串表示,你可以通过DocumentHelper.parseText()方法将它重新转化为文档(Document)对象:

String text = " James ";
Document document = DocumentHelper.parseText(text);

通过XSLT样式化文档(Document)


使用Sun公司提供的JAXP API将XSLT 应用到文档(Document)上是很简单的。它允许你使用任何的XSLT引擎(例如:Xalan或SAXON等)来开发。下面是一个使用JAXP创建一个转化器(transformer),然后将它应用到文档(Document)上的例子:

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;

import org.dom4j.Document;
import org.dom4j.io.DocumentResult;
import org.dom4j.io.DocumentSource;

public class Foo {

  public Document styleDocument(Document document, String stylesheet)throws Exception {

    // 使用 JAXP 加载转化器
    TransformerFactory factory = TransformerFactory.newInstance();
    Transformer transformer = factory.newTransformer(new StreamSource( stylesheet ));

    // 现在来样式化一个文档(Document)
    DocumentSource source = new DocumentSource( document );
    DocumentResult result = new DocumentResult();
    transformer.transform( source, result );

    // 返回经过样式化的文档(Document)
    Document transformedDoc = result.getDocument();
    return transformedDoc;
  }
}



需要加入的包:
dom4j
saxpath
jaxen

package com.freezingxu.testDom4J;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class TestDom4J {
  /**
  * 获得XML文档
  * @param url
  * @return
  * @throws DocumentException
  * @throws FileNotFoundException
  */
  public Document parse(String url) throws DocumentException,FileNotFoundException{
    SAXReader saxReader = new SAXReader();
    File file = new File(url);
    InputStream in = new FileInputStream(file);
    Document doc = saxReader.read(in);
    return doc;
  }

  /**
   * 获得XML文件中的根节点
   * @param doc
   * @return
   */
  public Element getRootElement(Document doc){
    Element element = doc.getRootElement();
    System.out.println( "Root=" +element.getName());
    return element;
   }

  /**
  * 获得指定根节点下的所有节点
  * @param root
  */
  public Collection print(Element root){
    Collection coll = new ArrayList();
     Iterator itor = root.elementIterator();
     while(itor.hasNext()){
      Element e = (Element)itor.next();
      coll.add(e);
       System.out.println( "Element=" + e.getName());
    }

     return coll;
  }

   /**
  * 获得指定根节点下的指定节点
   * @param root
   * @param name
   * @return
   */
   public Collection getElement(Element root,String name){
    Collection coll = new ArrayList();
     Iterator itor = root.elementIterator(name);

     while(itor.hasNext()){
      Element e = (Element)itor.next();
       coll.add(e);
      System.out.println( "Element=" + e.getName());
     }
    return coll;
   }

  /**
   * 获得指定节点的所有属性
   * @param root
   */
  public void printAttribute(Element root){
     Iterator itor = root.attributeIterator();
     while(itor.hasNext()){
       Attribute attr = (Attribute)itor.next();
      String attributeName = attr.getName();
       String attributeValue = attr.getValue();
       System.out.println( "Name=" + attributeName + " and Value=" + attributeValue);
     }
  }

   /**
   * 使用xPath直接获得节点
  * @param doc
   * @param xPath
   * @return
   */
  public List getNodes(Document doc,String xPath){
     List list = doc.selectNodes(xPath);
     return list;
  }

   /**
  * 使用xPath获得指定节点的指定属性
   * @param node
   * @param xPath
   * @return
   */
  public String getNodeAttribute(Element node,String xPath){
     String attributeValue = node.valueOf(xPath); //获得属性的值
     String attributeText = node.getText(); //获得属性的文本
     return attributeValue;
  }

   /**
   * main
   * @param args
   * @throws FileNotFoundException
   * @throws DocumentException
  */
   public static void main(String []args) throws FileNotFoundException, DocumentException{
    TestDom4J t = new TestDom4J();
    Document doc = t.parse( "d:/query.xml" );
     Element rootElement = t.getRootElement(doc);
    t.print(rootElement);
    t.printAttribute(rootElement);
     Collection elmtColl = t.getElement(rootElement, "dwlx" );
    Iterator elmtItor = elmtColl.iterator();
     while(elmtItor.hasNext()){
      Element e = (Element)elmtItor.next();
       Collection coll = t.print(e);
       Iterator itor = coll.iterator();
      while(itor.hasNext()){
         Element e2 = (Element)itor.next();
         t.printAttribute(e2);
       }
     }

     //xPath
     List list = t.getNodes(doc, "//root/dwlx/value" );
    Iterator xPathItor = list.iterator();
    while(xPathItor.hasNext()){
       Element node = (Element)xPathItor.next();
       String s = t.getNodeAttribute(node, "@name" );
       System.out.println(s);
     }
   }
}

//////////附件:query.xml//////////



 
  all
  00
  68
 

 
   all
   0
   1
 

 
  all
  0
   1
  2
  3
  4
  5
  6
 

2007年5月9日星期三

用GWT(GoogleWebToolkit)开发Ajax-GetTime

摘要: 前边已经有了两篇文章, 用GWT(Google Web Toolkit)开发Ajax-HelloWorld,用GWT(Google Web Toolkit)开发Ajax-你好,前边两个例子,都是只用了客户端的代码,并没有客户端和服务器端的交互过程。本文将会介绍一个简单的客户-服务器交互过程。客户端一样会显示一个按钮,点击的时候会返回服务器时间。并一同介绍一下简单的调试过程。
关键字: GWT Google Web Toolkit Ajax 入门应用 rpc调用 RemoteService RemoteServiceServlet

介绍

GWT(GoogleWebToolkit)是一个由Google开发提供的Java Ajax开发框架,已经用于开发GoogleMaps,GMail等应用了,它帮助开发者从各个不同的浏览器的诡异中解脱出来。现在写一个动态的Ajax 应用是一个令人郁闷,有严重错误倾向的过程,可能要花上90%的时间来处理那些敏感的,易错的浏览器之间的兼容性和跨平台,并且javascript的难 以调试性更加增加了整个开发过程的难度,和应用的健壮性。
GWT可以让你提供同样的即时的,有良好用户体验的应用的时候,避免很多这样令人头痛的事情。开发者可以用java语言来写界面,然后GWT提供的编译器会把他们编译成javascript和HTML。
假如说前面的两个例子,只是一个依样画葫芦的,从今天开始,就需要更多地去考虑一些Ajax的模式和GWT提供的便利的背后的原理。
GWT应用和传统的HTML页面应用的根本的区别就是,GWT在执行过程不需要获取新的页面来更新信息。尽管如此,向所有的客户端/服务端应用程序一样, GWT应用也要在执行过程,不断地才服务器取得数据,这种由一种叫RPC(远端过程调用)的机制来实现,也有时叫做服务端调用。GWT让这个RPC过程可 以直接引用一些Java对象来实现。(注:这里是只是一些,并不是所有的)。
恰当的利用好这个特性可以提供应用的效率,减少客户端服务器端的数据交换,更能提供友好的用户体验。
这些服务器端的代码,或是操作,被称为一个service,这个不同于SOAP(简单对象访问协议)中的Web Service。这是一个需要区别的概念。
本文将会介绍一个简单的客户-服务器交互过程。客户端一样会显示一个按钮,点击的时候会返回服务器时间。并一同介绍一下简单的调试过程。

实现过程

1、如用GWT(Google Web Toolkit)开发Ajax-HelloWorld创建应用。
应用名为org.jmg.client.GetTime
2、创建Service

创建两个接口和一个实现:
interface:org.jmg.client.GetTimeService extends RemoteService
interface:org.jmg.client.GetTimeServiceAsync
class:org.jmg.server.GetTimeServiceImpl extends RemoteServiceServlet implements RemoteServcie
在接口GetService中添加 String getTime()方法。
GetTimeServiceAsync中添加 void getTime(AsyncCallback callback)方法。
在类GetTimeServiceImpl中实现获取时间的方法:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return sdf.format(new Date());
注意:
a.GetTimeService 必须扩展RemoteService这个标志接口
b.GetTimeServiceAsync 的命名规则,只能在GetTimeService 后边添加 Async
c.GetTimeServiceAsync 的 getTime 这个方法不能有返回值,实际上,这个接口的所有的方法都不能有返回值,只能void。这里的原因会在以后的慢慢解释。
d.GetTimeServiceImpl 必须继承 RemoteServiceServlet
e.GetTimeServiceAsync 不需要实现,GWT会在编译的时候帮你实现。 f.以上的三个类的包都不能修改

3、修改部署文件:
修改WEB-INFweb.xml:
添加
<servlet>
<servlet-name>GetTimeServcie</servlet-name>
<servlet-class>org.jmg.server.GetTimeServiceImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>GetTimeServcie</servlet-name>
<url-pattern>/timeService</url-pattern>
</servlet-mapping>
GetTimeServiceImpl继承了RemoteServiceServlet(这个类扩展java的HttpServlet),它将需要部署成一个servlet。

4、修改GetTime
和前面的两个例子一样,默认创建的应用的GetTime中按钮的动作就是在页面上显示"hello world"。现在我们需要改变这个按钮的点击时候行为,要把从服务器获取时间显示出来。
a.找到我们定义的timeServcie的Servlet。 在GetTime中添加一个方法:initiailizeServiceEntryPoint
private final GetTimeServiceAsync initiailizeServiceEntryPoint() {
GetTimeServiceAsync timeService = (GetTimeServiceAsync) GWT.create(GetTimeService.class);(注意,这里create参数是GetTimeService.class,但是返回的实例是一个GetTimeServiceAsync)
ServiceDefTarget target = (ServiceDefTarget) timeService;(这里又把timeService,强换型成ServiceDefTarget)
String staticResponseURL = GWT.getModuleBaseURL();(取得应用的基路径,这个可能会导致之不到servlet,只要把它改成应用的路径,例如/gwt/)
staticResponseURL += "/timeService";
target.setServiceEntryPoint(staticResponseURL);(把刚刚定义的servlet的path和应用基路径两者组合,得到最后的servlet路径)
return timeService;
}
一直都保持这么一个概念,所有client中的代码都GWT都会编译成合适js,HTML,都会在客户端执行。会对整个过程的理解有很好的帮助。
b.修改onModuleLoad:
public void onModuleLoad() {
final Button button = new Button("Click me");
final Label label = new Label();
final GetTimeServiceAsync gtsa = initiailizeServiceEntryPoint();
button.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
gtsa.getTime(new AsyncCallback() {
public void onFailure(Throwable caught) {
label.setText(caught.getLocalizedMessage());(调用失败的时候,把错误信息显示出来)
}
public void onSuccess(Object result) {
label.setText((String) result);(这里为什么可以强换型到String?这里的值就是GetTimeService.getTime()方法的返回值)
);
}
});

5、编译与部署:
a.老习惯,用GetTime-compile.cmd用编译客户端代码(注意,这里只是编译客户端代码),会在wwworg.jmg.GetTime 目录生成客户端所合适的html和js,复制wwworg.jmg.GetTime下所有的文件到tomcat应用的webappsgwt gettime目录下。
b.复制elipse编译输出目录下的类到tomcat应用webappsgwtWEB-INFclasses目录。
c.检查web.xml文件是否已经复制,或是已经修改。
部署完成。
6、运行测试:
启动tomcat
访问http://localhost:8080/gwt/gettime/GetTime.html
点击click me 按钮,显示服务器时间


参考: Google Web Toolkit

Remote Procedure Calls
更多文章: 用GWT(GoogleWebToolkit)开发Ajax-HelloWorld

用GWT(GoogleWebToolkit)开发Ajax-你好,世界

2007年5月3日星期四

GWT中文支持

将java代码改为UTF-8
中文显示正确!!