﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-坚持学习，每天进步一些-文章分类-OpenSource</title><link>http://www.blogjava.net/leitianguang/category/11806.html</link><description>第一天</description><language>zh-cn</language><lastBuildDate>Wed, 07 Mar 2007 11:24:28 GMT</lastBuildDate><pubDate>Wed, 07 Mar 2007 11:24:28 GMT</pubDate><ttl>60</ttl><item><title>Lucene-2.0学习文档-4[转]</title><link>http://www.blogjava.net/leitianguang/articles/101837.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Mon, 05 Mar 2007 02:11:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/101837.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/101837.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/101837.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/101837.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/101837.html</trackback:ping><description><![CDATA[public void SearchSort1() throws IOException, ParseException<br />{<br />        IndexSearcher indexSearcher = new IndexSearcher("C:\\indexStore");<br />        QueryParser queryParser = new QueryParser("sort",new StandardAnalyzer());<br />        Query query = queryParser.parse("4");<br />       <br />        Hits hits = indexSearcher.search(query);<br />        System.out.println("有"+hits.length()+"个结果");<br />        Document doc = hits.doc(0);<br />        System.out.println(doc.get("sort"));<br />}<br />public void SearchSort2() throws IOException, ParseException<br />{<br />        IndexSearcher indexSearcher = new IndexSearcher("C:\\indexStore");<br />        Query query = new RangeQuery(new Term("sort","1"),new Term("sort","9"),true);//这个地方前面没有提到，它是用于范围的Query可以看一下帮助文档.<br />        Hits hits = indexSearcher.search(query,new Sort(new SortField("sort",new MySortComparatorSource())));<br />        System.out.println("有"+hits.length()+"个结果");<br />        for(int i=0;i<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("sort"));<br />        }<br />}<br />public class MyScoreDocComparator implements ScoreDocComparator<br />{<br />    private Integer[]sort;<br />    public MyScoreDocComparator(String s,IndexReader reader, String fieldname) throws IOException<br />    {<br />        sort = new Integer[reader.maxDoc()];<br />        for(int i = 0;i<br />        {<br />            Document doc =reader.document(i);<br />            sort[i]=new Integer(doc.get("sort"));<br />        }<br />    }<br />    public int compare(ScoreDoc i, ScoreDoc j)<br />    {<br />        if(sort[i.doc]&gt;sort[j.doc])<br />            return 1;<br />        if(sort[i.doc]<sort><br />            return -1;<br />        return 0;<br />    }<br />    public int sortType()<br />    {<br />        return SortField.INT;<br />    }<br />    public Comparable sortValue(ScoreDoc i)<br />    {<br />        // TODO 自动生成方法存根<br />        return new Integer(sort[i.doc]);<br />    }<br />}<br />public class MySortComparatorSource implements SortComparatorSource<br />{<br />    private static final long serialVersionUID = -9189690812107968361L;<br />    public ScoreDocComparator newComparator(IndexReader reader, String fieldname)<br />            throws IOException<br />    {<br />        if(fieldname.equals("sort"))<br />            return new MyScoreDocComparator("sort",reader,fieldname);<br />        return null;<br />    }<br />}[/code]<br />SearchSort1()输出的结果没有排序,SearchSort2()就排序了。<br />2.多域搜索MultiFieldQueryParser<br />如果想输入关键字而不想关心是在哪个Field里的就可以用MultiFieldQueryParser了<br />用它的构造函数即可后面的和一个Field一样。<br />MultiFieldQueryParser. parse(String[] queries, String[] fields, BooleanClause.Occur[] flags, Analyzer analyzer)                                          ~~~~~~~~~~~~~~~~~<br />第三个参数比较特殊这里也是与以前lucene1.4.3不一样的地方<br />看一个例子就知道了<br />String[] fields = {"filename", "contents", "description"};<br /> BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,<br />                BooleanClause.Occur.MUST,//在这个Field里必须出现的<br />                BooleanClause.Occur.MUST_NOT};//在这个Field里不能出现<br /> MultiFieldQueryParser.parse("query", fields, flags, analyzer);<br /></sort><img src ="http://www.blogjava.net/leitianguang/aggbug/101837.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2007-03-05 10:11 <a href="http://www.blogjava.net/leitianguang/articles/101837.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene-2.0学习文档-3[转]</title><link>http://www.blogjava.net/leitianguang/articles/101836.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Mon, 05 Mar 2007 02:10:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/101836.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/101836.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/101836.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/101836.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/101836.html</trackback:ping><description><![CDATA[到现在我们已经可以用lucene建立索引了<br />下面介绍一下几个功能来完善一下：<br />1．索引格式<br />其实索引目录有两种格式，一种是除配置文件外，每一个Document独立成为一个文件（这种搜索起来会影响速度）。另一种是全部的Document成一个文件，这样属于复合模式就快了。<br />2.索引文件可放的位置：<br />索引可以存放在两个地方1.硬盘，2.内存<br />放在硬盘上可以用FSDirectory()，放在内存的用RAMDirectory()不过一关机就没了<br />FSDirectory.getDirectory(File file, boolean create)<br />FSDirectory.getDirectory(String path, boolean create)两个工厂方法返回目录<br />New RAMDirectory()就直接可以<br />再和IndexWriter(Directory d, Analyzer a, boolean create)一配合就行了<br />如：<br />IndexWrtier indexWriter = new IndexWriter(FSDirectory.getDirectory(“c:\\index”,true),new StandardAnlyazer(),true);<br />IndexWrtier indexWriter = new IndexWriter(new RAMDirectory(),new StandardAnlyazer(),true);<br />3.索引的合并<br />这个可用IndexWriter.addIndexes(Directory[] dirs)将目录加进去<br />来看个例子:<br />[code]<br />public void UniteIndex() throws IOException<br />    {<br />        IndexWriter writerDisk = new IndexWriter(FSDirectory.getDirectory("c:\\indexDisk", true),new StandardAnalyzer(),true);<br />        Document docDisk = new Document();<br />        docDisk.add(new Field("name","程序员之家",Field.Store.YES,Field.Index.TOKENIZED));<br />        writerDisk.addDocument(docDisk);<br />        RAMDirectory ramDir = new RAMDirectory();<br />        IndexWriter writerRam = new IndexWriter(ramDir,new StandardAnalyzer(),true);<br />        Document docRam = new Document();<br />        docRam.add(new Field("name","程序员杂志",Field.Store.YES,Field.Index.TOKENIZED));<br />        writerRam.addDocument(docRam);<br />        writerRam.close();//这个方法非常重要，是必须调用的<br />        writerDisk.addIndexes(new Directory[]{ramDir});<br />        writerDisk.close();<br />    }<br />    public void UniteSearch() throws ParseException, IOException<br />    {<br />        QueryParser queryParser = new QueryParser("name",new StandardAnalyzer());<br />        Query query = queryParser.parse("程序员");<br />        IndexSearcher indexSearcher =new IndexSearcher("c:\\indexDisk");<br />        Hits hits = indexSearcher.search(query);<br />        System.out.println("找到了"+hits.length()+"结果");<br />        for(int i=0;i<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("name"));<br />        }<br />}<br />[/code]<br />这个例子是将内存中的索引合并到硬盘上来.<br />注意：合并的时候一定要将被合并的那一方的IndexWriter的close()方法调用。<br />4.对索引的其它操作:<br />IndexReader类是用来操作索引的，它有对Document,Field的删除等操作。<br />下面一部分的内容是：全文的搜索<br />全文的搜索主要是用：IndexSearcher,Query,Hits,Document(都是Query的子类),有的时候用QueryParser<br />主要步骤：<br />1.new QueryParser(Field字段，new 分析器)<br />2.Query query = QueryParser.parser(“要查询的字串”);这个地方我们可以用反射api看一下query究竟是什么类型<br />3.new IndexSearcher(索引目录).search(query);返回Hits<br />4.用Hits.doc(n);可以遍历出Document<br />5.用Document可得到Field的具体信息了。<br />其实1　，2两步就是为了弄出个Query 实例，究竟是什么类型的看分析器了。<br />拿以前的例子来说吧<br />QueryParser queryParser = new QueryParser("name",new StandardAnalyzer());<br />        Query query = queryParser.parse("程序员");<br />/*这里返回的就是org.apache.lucene.search.PhraseQuery*/<br />        IndexSearcher indexSearcher =new IndexSearcher("c:\\indexDisk");<br />        Hits hits = indexSearcher.search(query);<br />不管是什么类型，无非返回的就是Query的子类，我们完全可以不用这两步直接new个Query的子类的实例就ok了，不过一般还是用这两步因为它返回的是PhraseQuery这个是非常强大的query子类它可以进行多字搜索用QueryParser可以设置各个关键字之间的关系这个是最常用的了。<br />IndexSearcher:<br />其实IndexSearcher它内部自带了一个IndexReader用来读取索引的，IndexSearcher有个close()方法，这个方法不是用来关闭IndexSearche的是用来关闭自带的IndexReader。<br /><br />QueryParser呢可以用parser.setOperator()来设置各个关键字之间的关系（与还是或）它可以自动通过空格从字串里面将关键字分离出来。<br />注意：用QueryParser搜索的时候分析器一定的和建立索引时候用的分析器是一样的。<br />Query:<br />可以看一个lucene2.0的帮助文档有很多的子类:<br />BooleanQuery, ConstantScoreQuery, ConstantScoreRangeQuery, DisjunctionMaxQuery, FilteredQuery, MatchAllDocsQuery, MultiPhraseQuery, MultiTermQuery, PhraseQuery, PrefixQuery, RangeQuery, SpanQuery, TermQuery<br />各自有用法看一下文档就能知道它们的用法了<br />下面一部分讲一下lucene的分析器:<br />分析器是由分词器和过滤器组成的，拿英文来说吧分词器就是通过空格把单词分开，过滤器就是把the,to,of等词去掉不被搜索和索引。<br />我们最常用的是StandardAnalyzer()它是lucene的标准分析器它集成了内部的许多的分析器。<br />最后一部分了：lucene的高级搜索了<br />1.排序<br />Lucene有内置的排序用IndexSearcher.search(query,sort)但是功能并不理想。我们需要自己实现自定义的排序。<br />这样的话得实现两个接口: ScoreDocComparator, SortComparatorSource<br />用IndexSearcher.search(query,new Sort(new SortField(String Field,SortComparatorSource)));<br />就看个例子吧：<br />这是一个建立索引的例子：<br />[code]<br />public void IndexSort() throws IOException<br />{<br />        IndexWriter writer = new IndexWriter("C:\\indexStore",new StandardAnalyzer(),true);<br />        Document doc = new Document()<br />        doc.add(new Field("sort","1",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        doc = new Document();<br />        doc.add(new Field("sort","4",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        doc = new Document();<br />        doc.add(new Field("sort","3",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        doc = new Document();<br />        doc.add(new Field("sort","5",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        doc = new Document();<br />        doc.add(new Field("sort","9",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        doc = new Document();<br />        doc.add(new Field("sort","6",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        doc = new Document();<br />        doc.add(new Field("sort","7",Field.Store.YES,Field.Index.TOKENIZED));<br />        writer.addDocument(doc);<br />        writer.close();<br />}<br /><img src ="http://www.blogjava.net/leitianguang/aggbug/101836.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2007-03-05 10:10 <a href="http://www.blogjava.net/leitianguang/articles/101836.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene-2.0学习文档2[转]</title><link>http://www.blogjava.net/leitianguang/articles/101835.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Mon, 05 Mar 2007 02:08:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/101835.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/101835.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/101835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/101835.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/101835.html</trackback:ping><description><![CDATA[(File path, Analyzer a, boolean create)<br />IndexWriter(String path, Analyzer a, boolean create)<br />可见构造它需要一个索引文件目录，一个分析器(一般用标准的这个)，最后一个参数是标识是否清空索引目录<br />它有一些设置参数的功能如：设置Field的最大长度<br />看个例子：<br />[code]<br />public void IndexMaxField() throws IOException<br />{<br />        IndexWriter indexWriter= new IndexWriter("c:\\index",new StandardAnalyzer(),true);<br />        Document doc1 = new Document();<br />        doc1.add(new Field("name1","程序员之家",Field.Store.YES,Field.Index.TOKENIZED));<br />        Document doc2 = new Document();<br />        doc2.add(new Field("name2","Welcome to the Home of programers",Field.Store.YES,Field.Index.TOKENIZED));<br />        indexWriter.setMaxFieldLength(5);<br />        indexWriter.addDocument(doc1);<br />        indexWriter.setMaxFieldLength(3);<br />        indexWriter.addDocument(doc1);<br />        indexWriter.setMaxFieldLength(0);<br />        indexWriter.addDocument(doc2);<br />        indexWriter.setMaxFieldLength(3);<br />        indexWriter.addDocument(doc2);<br />        indexWriter.close();<br />}<br />public void SearcherMaxField() throws ParseException, IOException<br />{<br />        Query query = null;<br />        Hits hits = null;<br />        IndexSearcher indexSearcher= null;<br />        QueryParser queryParser= null;<br />        queryParser = new QueryParser("name1",new StandardAnalyzer());<br />        query = queryParser.parse("程序员");<br />        indexSearcher= new IndexSearcher("c:\\index");<br />        hits = indexSearcher.search(query);<br />        System.out.println("您搜的是：程序员");<br />        System.out.println("找到了"+hits.length()+"个结果");<br />        System.out.println("它们分别是：");<br />        for (int i = 0; i &lt; hits.length(); i++)<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("name1"));<br />        }<br />        query = queryParser.parse("程序员之家");<br />        indexSearcher= new IndexSearcher("c:\\index");<br />        hits = indexSearcher.search(query);<br />        System.out.println("您搜的是：程序员之家");<br />        System.out.println("找到了"+hits.length()+"个结果");<br />        System.out.println("它们分别是：");<br />        for (int i = 0; i &lt; hits.length(); i++)<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("name1"));<br />        }<br />        queryParser = new QueryParser("name2",new StandardAnalyzer());<br />        query = queryParser.parse("Welcome");<br />        indexSearcher= new IndexSearcher("c:\\index");<br />        hits = indexSearcher.search(query);<br />        System.out.println("您搜的是：Welcome");<br />        System.out.println("找到了"+hits.length()+"个结果");<br />        System.out.println("它们分别是：");<br />        for (int i = 0; i &lt; hits.length(); i++)<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("name2"));<br />        }           <br />        query = queryParser.parse("the");<br />        indexSearcher= new IndexSearcher("c:\\index");<br />        hits = indexSearcher.search(query);<br />        System.out.println("您搜的是：the");<br />        System.out.println("找到了"+hits.length()+"个结果");<br />        System.out.println("它们分别是：");<br />        for (int i = 0; i &lt; hits.length(); i++)<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("name2"));<br />        }<br />        query = queryParser.parse("home");<br />        indexSearcher= new IndexSearcher("c:\\index");<br />        hits = indexSearcher.search(query);<br />        System.out.println("您搜的是：home");<br />        System.out.println("找到了"+hits.length()+"个结果");<br />        System.out.println("它们分别是：");<br />        for (int i = 0; i &lt; hits.length(); i++)<br />        {<br />            Document doc = hits.doc(i);<br />            System.out.println(doc.get("name2"));<br />        }<br />}<br />[/code]<br />它的运行结果为:<br />总结一下：<br />1.设置Field的长度限制只是限制了搜索。如果用了Field.Store.YES的话还是会<br />全部被保存进索引目录里的。<br />2.为什么搜the没有搜出来呢是因为lucene分析英文的时候不会搜索the to of 等无<br />用的词(搜这些词是无意义的)。<br />3.New StandardAnlayzer()对于英文的分词是按空格和一些无用的词，而中文呢是全部的单个<br />的字。<br />4.设置Field的最大长度是以0开头和数组一样。<br />程序员之家----------3--------程序员之<br />                                    0 1 2  3<br />Welcome to the home of programmers------3------Welcome to the home of programmers<br /><br />                                                   0           1         2<br />大家还可以试一下别的，以便加深一下印象<br />(未完) 
<div style="PADDING-RIGHT: 10px; BORDER-TOP: gray 1px solid; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: 15px 0px 0px 10px; PADDING-TOP: 10px"><table class="attach" cellspacing="0" cellpadding="2" width="95%" align="center" border="1"><tbody><tr><td class="attachrow" style="BACKGROUND: #d1d7dc" align="middle" width="100%" colspan="2"><b><span class="gen">Lucene.JPG</span></b></td></tr><tr><td class="attachrow" width="15%"><span class="genmed"> 描述:</span></td><td class="attachrow" width="75%"> lucene讲解图片 </td></tr><tr><td class="attachrow" width="15%"><span class="genmed"> 文件大小:</span></td><td class="attachrow" width="75%"><span class="genmed"> 39 KB</span></td></tr><tr><td class="attachrow" width="15%"><span class="genmed"> 看过的:</span></td><td class="attachrow" width="75%"><span class="genmed"> 文件被下载或查看 171 次</span></td></tr><tr><td align="middle" colspan="2"><br /><a href="http://www.javaeye.com/topics/download/02dd2dac-b8d4-4333-a78b-ffe0d9d70b34" target="_blank"><img alt="Lucene.JPG" src="http://www.javaeye.com/upload/attachment/pic/3189/266ae1ee-e0bc-4b1a-8016-99a9156c4ab4-thumb.jpg" border="0" /></a><br /><a href="javascript:login_show();"><b>下载</b></a><br /></td></tr></tbody></table></div><img src ="http://www.blogjava.net/leitianguang/aggbug/101835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2007-03-05 10:08 <a href="http://www.blogjava.net/leitianguang/articles/101835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Lucene-2.0学习文档-1[转]</title><link>http://www.blogjava.net/leitianguang/articles/101833.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Mon, 05 Mar 2007 02:05:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/101833.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/101833.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/101833.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/101833.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/101833.html</trackback:ping><description><![CDATA[
		<span lang="EN-US" style="FONT-SIZE: 14pt"> 
<p><font face="Arial" size="3">Lucene是apache组织的一个用java实现全文搜索引擎的开源项目。</font></p><p><font face="Arial" size="3">其功能非常的强大，api也很简单。总得来说用Lucene来进行建立</font></p><p><font face="Arial" size="3">和搜索和操作数据库是差不多的(有点像)，Document可以看作是</font></p><p><font face="Arial" size="3">数据库的一行记录，Field可以看作是数据库的字段。用lucene实</font></p><p><font face="Arial"><font size="3">现搜索引擎就像用JDBC实现连接数据库一样简单。</font><br /></font></p></span>
		<p class="MsoNormal">
				<font size="3">
						<span>
						</span>
				</font>
		</p>
		<p class="MsoNormal">
				<font size="3">
						<span>
						</span>
				</font>
				<span lang="EN-US">
						<?XML:NAMESPACE PREFIX = O /?>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span>Lucene2.0，它与以前广泛应用和介绍的Lucene <?XML:NAMESPACE PREFIX = ST1 /?><st1:chsdate month="12" islunardate="False" day="30" year="1899" w:st="on" isrocdate="False">1.4.3</st1:chsdate>并不兼容。</span>
		</p>
		<p class="MsoNormal">
				<span>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span>Lucene2.0的下载地址是<a href="http://apache.justdn.org/lucene/java/">http://apache.justdn.org/lucene/java/</a></span>
		</p>
		<p class="MsoNormal">
				<span>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span>
						</span>
				</span>
				<span>大家先看一个例子，通过这个例子来对</span>
				<span lang="EN-US">lucene</span>
				<span>的一个大概的认识。</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span style="FONT-FAMILY: 宋体">一个</span>
				<span lang="EN-US">Junit</span>
				<span>测试用例：</span>
				<span lang="EN-US">(</span>
				<span>为了让代码清晰好看，我们将异常都抛出</span>
				<span lang="EN-US">)<o:p></o:p></span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">a)<span>    </span></span>
				<strong>
						<span>这是一个建立文件索引的例子</span>
				</strong>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">public</span>
				</strong>
				<span lang="EN-US">
				</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">void</span>
				</strong>
				<span lang="EN-US"> testIndexHello() </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">throws</span>
				</strong>
				<span lang="EN-US"> IOException</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>    </span>{</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>Date date1 = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> Date();</span>
				<span lang="EN-US">
						<span> </span>
				</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">可以说是创建一个新的写入工具</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">第一个参数是要索引建立在哪个目录里</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">第二个参数是新建一个文本分析器<span lang="EN-US">,</span>这里用的是标准的大家也可以自己写一个</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">第三个参数如果是<span lang="EN-US">true</span>，在建立索引之前先将<span lang="EN-US">c:\\index</span>目录清空。</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>IndexWriter writer = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> IndexWriter(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"c:\\index"</span>
				<span lang="EN-US">,</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> StandardAnalyzer(),</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">true</span>
				</strong>
				<span lang="EN-US">);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: rgb(63,127,95); FONT-FAMILY: 宋体">//<span>      </span></span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">这个是数据源的文件夹</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>File file = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> File(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"c:\\file"</span>
				<span lang="EN-US">);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 95,="" 191);="">/**</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
						<span> </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 95,="" 191);="">*</span>
				<span lang="EN-US">
				</span>
				<span font-family:="" 宋体;?="" 95,="" 191);="">例子主要是将<span lang="EN-US">C:\\file</span>目录下的文件的内容进行建立索引，将文件路径作为搜索内容的附属<span lang="EN-US">.</span></span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
						<span> </span>
				</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 95,="" 191);="">*/</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">if</span>
				</strong>
				<span lang="EN-US">(file.isDirectory())</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>{</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>String[] fileList = file.list();</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>
				</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">for</span>
				</strong>
				<span lang="EN-US"> (</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">int</span>
				</strong>
				<span lang="EN-US"> i = 0; i &lt; fileList.</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">length</span>
				<span lang="EN-US">; i++)</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>{</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: rgb(63,127,95); FONT-FAMILY: 宋体">//<span>              </span></span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">建立一个新的文档<span lang="EN-US">,</span>它可以看作是数据库的一行记录</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>Document doc = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> Document();</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>File f = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> File(file,</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>
						<span>        </span>fileList[i]);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>Reader reader = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> BufferedReader(</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> FileReader(f));</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>doc.add(</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> Field(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"file"</span>
				<span lang="EN-US">,reader));</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">为<span lang="EN-US">doument</span>添加<span lang="EN-US">field</span></span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>doc.add(</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> Field(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"path"</span>
				<span lang="EN-US">,f.getAbsolutePath(),Field.Store.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">YES</span>
				</em>
				<span lang="EN-US">,Field.Index.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">NO</span>
				</em>
				<span lang="EN-US">));</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>writer.addDocument(doc);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>}</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>
				</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>}</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>writer.close();</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">这一步是必须的，只有这样数据才会被写入索引的目录里</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>Date date2 = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> Date();</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>System.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">out</span>
				</em>
				<span lang="EN-US">.println(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"</span>
				<span 0,="" font-family:="" 宋体;?="" 255);="">用时<span lang="EN-US">"</span></span>
				<span lang="EN-US">+(date2.getTime()-date1.getTime())+</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"</span>
				<span 0,="" font-family:="" 宋体;?="" 255);="">毫秒<span lang="EN-US">"</span></span>
				<span lang="EN-US">);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">}</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">注意：因为建立索引本来就是费时，所以说最后输出的用时会比较长，请不要奇怪。</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">b)</span>
				<span>一个通过索引来全文检索的例子<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">public</span>
				</strong>
				<span lang="EN-US">
				</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">void</span>
				</strong>
				<span lang="EN-US"> HelloSearch() </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">throws</span>
				</strong>
				<span lang="EN-US"> IOException, ParseException</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>    </span>{</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>IndexSearcher indexSearcher = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> IndexSearcher(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"c:\\index"</span>
				<span lang="EN-US">);</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">和上面的<span lang="EN-US">IndexWriter</span>一样是一个工具</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>QueryParser queryParser = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> QueryParser(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"file"</span>
				<span lang="EN-US">,</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">这是一个分词器</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>                </span>
				</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US">
						<span style="BACKGROUND: silver 0% 50%; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">StandardAnalyzer</span>());</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>BufferedReader br = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> BufferedReader(</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">new</span>
				</strong>
				<span lang="EN-US"> InputStreamReader(System.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">in</span>
				</em>
				<span lang="EN-US">));</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>Query query = queryParser.parse(br.readLine());</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">这个地方<span lang="EN-US">Query</span>是抽象类大家也注意一下，下面会讲到的</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>Hits hits = indexSearcher.search(query);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>Document doc = </span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">null</span>
				</strong>
				<span lang="EN-US">;</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>System.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">out</span>
				</em>
				<span lang="EN-US">.print(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"</span>
				<span 0,="" font-family:="" 宋体;?="" 255);="">正搜索<span lang="EN-US">................"</span></span>
				<span lang="EN-US">);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>
				</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">for</span>
				</strong>
				<span lang="EN-US"> (</span>
				<strong>
						<span lang="EN-US" 0,="" 85);="" font-family:="" 宋体;?="">int</span>
				</strong>
				<span lang="EN-US"> i = 0; i &lt; hits.length(); i++)</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>{</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>doc = hits.doc(i);</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>System.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">out</span>
				</em>
				<span lang="EN-US">.println(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"</span>
				<span 0,="" font-family:="" 宋体;?="" 255);="">内容是：<span lang="EN-US">"</span></span>
				<span lang="EN-US">+doc.get(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"file"</span>
				<span lang="EN-US">));</span>
				<span lang="EN-US" font-family:="" 宋体;?="" 127,="" 95);="">//</span>
				<span font-family:="" 宋体;?="" 127,="" 95);="">注意这里输出的是什么</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>            </span>System.</span>
				<em>
						<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 192);="">out</span>
				</em>
				<span lang="EN-US">.println(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"</span>
				<span 0,="" font-family:="" 宋体;?="" 255);="">文件的路径是：<span lang="EN-US">"</span></span>
				<span lang="EN-US"> + doc.get(</span>
				<span lang="EN-US" 0,="" font-family:="" 宋体;?="" 255);="">"path"</span>
				<span lang="EN-US">));</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>        </span>}</span>
				<span lang="EN-US">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">
						<span>    </span>}<o:p></o:p></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">通过上面的两个例子应该可以看出<span lang="EN-US">Lucene</span>还是比较简单的。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体">运行一下上面的两个例子，大家可能会说怎么<span lang="EN-US">doc.get(</span></span>
				<span lang="EN-US">“</span>
				<span lang="EN-US">file</span>
				<span lang="EN-US">”</span>
				<span lang="EN-US">);</span>
				<span>返回的是空呢<span lang="EN-US">,</span>我们马上会讲到。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<strong>
						<span>下面讲一下索引的建立<span lang="EN-US"><o:p></o:p></span></span>
				</strong>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">其实从上面的例子就可以看出建立索引就用到<span lang="EN-US">Document,IndexWriter,Field</span>。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">最简单的步骤就是：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">首先分别<span lang="EN-US">new </span>一个<span lang="EN-US">Document</span>，<span lang="EN-US">IndexWriter,Field<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">然后用<span lang="EN-US">Doument.add()</span>方法加入<span lang="EN-US">Field,<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span>其次用IndexWrtier.addDocument()方法加入Document。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">最后调用一下<span lang="EN-US">IndexWriter.close()</span>方法关闭输入索引，这一步非常的重要只有调用这个方法索引才会被写入索引的目录里，而这是被很多初学的人所忽略的。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体">Document</span>
				<span>没有什么好介绍的，把它的作用看成数据库中的一行记录就行。<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体">Field</span>
				<span>是一个比较重要的也是比较复杂的：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">看一下它的构造函数有<span lang="EN-US">5</span>个：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20byte%5B%5D,%20org.apache.lucene.document.Field.Store%29">
												<span new="" roman="" times="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> name, byte[] value, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html"><span new="" roman="" times="">Field.Store</span></a> store)<o:p></o:p></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader%29">
												<span new="" roman="" times="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> name, <a title="class or interface in java.io" href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html"><span new="" roman="" times="">Reader</span></a> reader)<o:p></o:p></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader,%20org.apache.lucene.document.Field.TermVector%29">
												<span new="" roman="" times="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> name, <a title="class or interface in java.io" href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html"><span new="" roman="" times="">Reader</span></a> reader, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.TermVector.html"><span new="" roman="" times="">Field.TermVector</span></a> termVector)<o:p></o:p></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.lang.String,%20org.apache.lucene.document.Field.Store,%20org.apache.lucene.document.Field.Index%29">
												<span new="" roman="" times="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> name, <a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> value, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html"><span new="" roman="" times="">Field.Store</span></a> store, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html"><span new="" roman="" times="">Field.Index</span></a> index)<o:p></o:p></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.lang.String,%20org.apache.lucene.document.Field.Store,%20org.apache.lucene.document.Field.Index,%20org.apache.lucene.document.Field.TermVector%29">
												<span new="" roman="" times="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> name, <a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> value, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html"><span new="" roman="" times="">Field.Store</span></a> store, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html"><span new="" roman="" times="">Field.Index</span></a> index, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.TermVector.html"><span new="" roman="" times="">Field.TermVector</span></a> termVector)<o:p></o:p></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<span>在<span lang="EN-US">Field</span>中有三个内部类：<span lang="EN-US">Field.Index,Field.Store,Field.termVector</span>，而构造函数也用到了它们。<span lang="EN-US"><o:p></o:p></span></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span>注意：</span>
						</strong>
				</code>
				<code>
						<strong>
								<span lang="EN-US">termVector</span>
						</strong>
				</code>
				<code>
						<strong>
								<span>是<span lang="EN-US">Lucene 1.4</span></span>
						</strong>
				</code>
				<code>
						<strong>
								<span>新增的它提供一种向量机制来进行模糊查询的这个不常用，默认是<span lang="EN-US">false</span>不过是什么对于一般查询无影响。<span lang="EN-US"><o:p></o:p></span></span>
						</strong>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<span>它们的不同的组合，在全文检索中有着不同的作用。看看下面的表吧<span lang="EN-US">:<o:p></o:p></span></span>
				</code>
		</p>
		<table class="MsoTableGrid" cellspacing="0" cellpadding="0" width="691" border="1">
				<tbody>
						<tr>
								<td valign="top" width="175">
										<p class="MsoNormal" align="left">
												<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体">Field.Index<o:p></o:p></span>
										</p>
								</td>
								<td valign="top" width="132">
										<p class="MsoNormal" align="left">
												<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体">Field.Store<o:p></o:p></span>
										</p>
								</td>
								<td valign="top" width="384">
										<p class="MsoNormal" align="left">
												<span style="COLOR: black; FONT-FAMILY: 宋体">说明<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="175">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#TOKENIZED">
																				<span new="" roman="" times="">TOKENIZED</span>
																		</a>(</span>
														</strong>
												</code>
												<code>
														<strong>
																<span>分词<span lang="EN-US">)</span></span>
														</strong>
												</code>
												<span lang="EN-US">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td valign="top" width="132">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html#YES">
																				<span new="" roman="" times="">YES</span>
																		</a>
																</span>
														</strong>
												</code>
												<span lang="EN-US">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td valign="top" width="384">
										<p class="MsoNormal" align="left">
												<span style="COLOR: black; FONT-FAMILY: 宋体">文章的标题或内容<span lang="EN-US">(</span>如果是内容的话不能太长<span lang="EN-US">)</span>是可以被搜索的<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="175">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#TOKENIZED">
																				<span new="" roman="" times="">TOKENIZED</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="132">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO">
																				<span new="" roman="" times="">NO</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="384">
										<p class="MsoNormal" align="left">
												<span style="COLOR: black; FONT-FAMILY: 宋体">文章的标题或内容<span lang="EN-US">(</span>内容可以很长<span lang="EN-US">)</span>也是可以被看过的<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="175">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO">
																				<span new="" roman="" times="">NO</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="132">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Store.html#YES">
																				<span new="" roman="" times="">YES</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="384">
										<p class="MsoNormal" align="left">
												<span style="COLOR: black; FONT-FAMILY: 宋体">这是不能被搜索的，它只是被搜索内容的附属物。如<span lang="EN-US">URL</span>等<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="175">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#UN_TOKENIZED">
																				<span new="" roman="" times="">UN_TOKENIZED</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="132">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">YES/NO<o:p></o:p></span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="384">
										<p class="MsoNormal" align="left">
												<span style="COLOR: black; FONT-FAMILY: 宋体">不被分词，它作为一个整体被搜索<span lang="EN-US">,</span>搜一部分是搜不出来的<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
						<tr>
								<td valign="top" width="175">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO">
																				<span new="" roman="" times="">NO</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="132">
										<p class="MsoNormal" align="left">
												<code>
														<strong>
																<span lang="EN-US">
																		<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.Index.html#NO">
																				<span new="" roman="" times="">NO</span>
																		</a>
																		<o:p>
																		</o:p>
																</span>
														</strong>
												</code>
										</p>
								</td>
								<td valign="top" width="384">
										<p class="MsoNormal" align="left">
												<span style="COLOR: black; FONT-FAMILY: 宋体">没有这种用法<span lang="EN-US"><o:p></o:p></span></span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">而对于</span>
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader%29">
												<span new="" roman="" times="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="">String</span></a> name, <a title="class or interface in java.io" href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html"><span new="" roman="" times="">Reader</span></a> reader)<o:p></o:p></span>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.html#Field%28java.lang.String,%20java.io.Reader,%20org.apache.lucene.document.Field.TermVector%29">
												<span new="" roman="" times="" red="" color="">Field</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<strong>
								<span lang="EN-US">(<a title="class or interface in java.lang" href="http://java.sun.com/j2se/1.4/docs/api/java/lang/String.html"><span new="" roman="" times="" red="" color="">String</span></a> name, <a title="class or interface in java.io" href="http://java.sun.com/j2se/1.4/docs/api/java/io/Reader.html"><span new="" roman="" times="" red="" color="">Reader</span></a> reader, <a title="class in org.apache.lucene.document" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/document/Field.TermVector.html"><span new="" roman="" times="" red="" color="">Field.TermVector</span></a> termVector)<o:p></o:p></span>
						</strong>
				</code>
		</p>
		<p class="MsoNormal" align="left">
				<strong>
						<span>他们是<span lang="EN-US">Field.Index.TOKENIZED</span>和<span lang="EN-US">Field.Store.NO</span>的。这就是为什么我们在上面的例子中会出现文章的内容为<span lang="EN-US">null</span>了。因为它只是被索引了，而并没有被存储下来。如果一定要看到文章的内容的话可以通过文章的路径得到毕竟文章的路径是作为搜索的附属物被搜索出来了。<u><span 217,="" 217)="" none="" repeat="" scroll="" 0%="" 50%;="" -moz-background-clip:="" -moz-background-origin:="" -moz-initial;="" -moz-background-inline-policy:="" -moz-initial;?="">而我们在<span lang="EN-US">Web</span>开发的时候一般是将大数据放在数据库中，不会放在文件系统中，更不会放在索引目录里，因为它太大了操作会加大服务器的负担</span></u><em>。</em></span>
				</strong>
				<strong>
						<span lang="EN-US">
								<o:p>
								</o:p>
						</span>
				</strong>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">下面介绍一下<span lang="EN-US">IndexWriter:<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">它就是一个写入索引的写入器<span lang="EN-US">,</span>它的任务比较简单：<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体">1.</span>
				<span>用<span lang="EN-US">addDocument()</span>将已经准备好写入索引的<span lang="EN-US">document</span>们加入<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span lang="EN-US" style="COLOR: black; FONT-FAMILY: 宋体">2.</span>
				<span>调用<span lang="EN-US">close()</span>将索引写入索引目录<span lang="EN-US"><o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<span style="COLOR: black; FONT-FAMILY: 宋体">先看一下它的构造函数<span lang="EN-US">:<o:p></o:p></span></span>
		</p>
		<p class="MsoNormal" align="left">
				<code>
						<strong>
								<span lang="EN-US">
										<a href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/index/IndexWriter.html#IndexWriter%28org.apache.lucene.store.Directory,%20org.apache.lucene.analysis.Analyzer,%20boolean%29">
												<span new="" roman="" times="">IndexWriter</span>
										</a>
								</span>
						</strong>
				</code>
				<code>
						<span lang="EN-US">(<a title="class in org.apache.lucene.store" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/store/Directory.html"><span new="" roman="" times="">Directory</span></a> d, <a title="class in org.apache.lucene.analysis" href="http://www.javaeye.com/article/Ñ§Ï°×ÊÁÏ/luence/lucene-2.0.0/docs/api/org/apache/lucene/analysis/Analyzer.html"><span new="" roman="" times="">Analyzer</span></a> a, boolean create)</span>
				</code>
		</p>
		<p class="MsoNormal" align="left">（未完）<code><span lang="EN-US"><o:p></o:p></span></code></p>
<img src ="http://www.blogjava.net/leitianguang/aggbug/101833.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2007-03-05 10:05 <a href="http://www.blogjava.net/leitianguang/articles/101833.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Apache SOAP介绍1 [转]</title><link>http://www.blogjava.net/leitianguang/articles/96559.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Mon, 29 Jan 2007 09:49:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/96559.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/96559.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/96559.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/96559.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/96559.html</trackback:ping><description><![CDATA[SOAP（简单对象访问协议）是一种利用XML编码数据的有线协议。它是同类协议中要求最低的一个规范，只定义了有线协议所要求的最关键的部分，有意地忽略了垃圾收集、对象激活等方面的细节。 <br /><br />SOAP对于Java开发者来说尤其重要，因为它让平台无关和可移植的Java程序更容易协同操作，使得Java的宝贵特性进一步增值。事实上，如果Java 2平台企业版（J2EE）的下一个版本让SOAP成为一种必须遵循的有线协议，规定所有遵从J2EE规范的应用服务器都必须支持SOAP协议，我也不会感到奇怪。不过就现在来说，我想我的猜想应该暂停了。 <br /><br />这个系列的文章总共四篇，这是第二篇。在这里，我要介绍Apache SOAP介绍的是Apache SOAP实现。 <br /><br /><strong>一、Apache SOAP概述</strong><br />Apache SOAP，即Apache Software Foundation对SOAP规范的实现，建立在IBM的SOAP4J的基础上。和所有其他Apache工程类似，Apache SOAP源代码开放，按照Apache许可协议发行。我觉得这是当前最好的SOAP实现之一。然而，虽然Apache SOAP遵从SOAP规范1.1版本，但它缺乏SOAP 1.1所包含的某些功能（参见本文最后的“参考资源”，了解Apache SOAP支持功能的清单）。 <br /><br /><strong>1.1、下载和安装Apache SOAP</strong><br />如前所述，Apache SOAP可以免费下载（参见“参考资源”中提供的下载链接）。我为我的Windows NT便携机下载了soap-bin-2.0.zip文件，该文件包含Apache SOAP 2.0，这是写作本文时的最新版本。安装Apache SOAP可谓轻而易举，共包含如下三个简单的步骤： <br /><br /><ol><li>解开下载所得文件的ZIP压缩：解开压缩之后就得到了一个soap-2_0子目录。我把ZIP文件的内容解压缩到E盘的根目录下，因此有了一个包含Apache SOAP的E:\soap-2_0目录。 
</li><li>配置Web环境：要有一个支持Servlet和JSP的Web服务器。至此，你可能遇到下面两种情况之一： 
<ul><li>情况1：已经有一个支持Servlet和JSP的Web服务器，而且你觉得配置这个服务器没有问题。在这种情况下，请配置服务器，使得浏览器可以访问http://localhost:8080/apache-soap/，打开soap-2_0 \webapps\soap\目录下面的index.html文件。 
</li><li>情况2：没有支持Servlet和JSP的Web服务器，或者虽然有这样一个服务器，却不想拿它做试验。在这种情况下，我建议你下载Tomcat的最新版本（写作本文时，最新版本是3.1）（参见“参考资源”中的链接）。Tomcat是Apache创建和免费提供给软件开发者的又一个优秀软件。下载合适的ZIP文件之后（jakarta-tomcat-3.1.1.zip），解开压缩时创建一个jakarta-tomcat子目录。和前面相似，我把解压缩得到的文件放入E盘的根目录之下。在jakarta-tomcat\conf\server.xml配置文件中增加一个新的&lt;Context&gt;标记，如下所示： 
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="400" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6">&lt;Context path="/apache-soap" docBase="E:/soap-2_0/webapps/soap"<br />debug="1" reloadable="true"&gt;<br />&lt;/Context&gt;</td></tr></tbody></table>在Context元素的docBase属性中，你应该在指定soap-2_0目录时把E:替换成合适的盘符。要启动Tomcat，执行startup.bat（对于Unix，执行startup.sh）。要关闭Tomcat，执行shutdown.bat（对于Unix，执行shutdown.sh）。但请稍等——现在请不要启动Tomcat。 </li></ul></li><li>设置Web服务器classpath：Apache SOAP要求有1.1.2版本或更高的Apache Xerces（Java），它支持DOM（文档对象模型）Level 2规范，支持名称空间。我使用1.2版本的Xerces，即Apache网站的Xerces-J-bin.1.2.0.zip。解开这个压缩文件，得到xerces-1_2_0子目录。和前面一样，我把解压缩得到的文件放到了E:盘的根目录之下。你应该配置Web服务器，使它能够用xerces.jar（它在xerces-1_2_0子目录下）进行所有XML解析——而不是用服务器附带的库或jar解析XML。例如，Tomcat附带了一个XML解析器（jakarta-tomcat\lib\xml.jar），支持DOM Level 1接口。即使你把xerces.jar放入了classpath，Tomcat下运行的Java代码也可能找错接口，因为在用来启动Tomcat的Shell脚本/批命令文件中，xerces.jar被放到了classpath的最后。因此，必须编辑jakarta-tomcat\bin目录下的tomcat.bat（对于Unix，则是tomcat.sh），把xerces.jar放到classpath的前面。下面是我在jakarta-tomcat\bin\tomcat.bat文件中所作的修改： 
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="450" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6">set CLASSPATH=E:\xerces-1_2_0\xerces.jar;%CLASSPATH%;%cp%</td></tr></tbody></table></li></ol>如果你在第二个步骤中属于情况2，也必须配置服务器，使它能够使用xerces.jar。 <br /><br />不管你属于哪一种情况，除了配置xerces.jar之外，你还必须配置Web服务器的classpath使它能够使用soap-2_0\lib\目录下的soap.jar。 <br /><br /><strong>1.2、检查安装是否成功</strong><br />现在，启动Web服务器，用浏览器打开http://localhost:8080/apache-soap/admin，验证安装是否成功。这时，你应该看到下图所示的管理屏幕。 <br /><br /><div align="center"><a href="http://www0.ccidnet.com/tech/app/2001/09/21/image/JavaAndSOAP2_1.gif" target="_blank"><img src="http://www0.ccidnet.com/tech/app/2001/09/21/image/JavaAndSOAP2_1-s.gif" border="0" /></a><br /><b>图一：Web界面的Apache SOAP管理工具</b></div><br /><strong>二、实例：HelloWorld</strong><br />现在你已经设置好了Apache SOAP，我们来实际使用一下，构造一个简单的HelloWorld应用。在SOAP术语中，应用称为服务。一般地，创建服务分两个步骤，这两个步骤可能由同一个人或组织实施，也可能不是。第一个步骤是在选定的语言中定义和实现服务本身，这里我们选择Java语言。第二个步骤是创建实际调用服务的客户程序。首先我们来看HelloWorld服务。 <br /><br /><strong>2.1、HelloWorld服务</strong><br />我在第一篇文章中讨论了一个用SOAP实现的HelloWorld服务实例。这个服务要求输入一个用户名字，返回一个定制的Hello消息给调用者。下面的代码显示了HelloWorld服务的完整Java代码。 <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>package hello;<br />public class HelloServer<br />{<br />public String sayHelloTo(String name)<br />{<br />System.out.println("sayHelloTo(String name)");<br />return "Hello " + name + ", How are you doing?";<br />}<br />}</p></td></tr></tbody></table><br />这就是全部的代码吗？如果这是真的话，实在太简单了！ <br /><br />Apache SOAP使创建服务变得极其简单。服务主要由业务逻辑构成，不管服务以哪种方式提供给外界使用，业务逻辑代码都是必须编写的。换句话说，服务不会和任何SOAP相关的代码混合，因为Apache SOAP底层体系——它由rpcrouter Servlet和soap.jar构成——帮助我们完成了所有错综复杂的工作。我们来简要地探讨一下这些错综复杂的工作究竟包含些什么，例如，Apache SOAP如何处理HTTP上的远程过程调用（RPC）请求？理解这一点将给创建客户程序带来方便（不错，是客户程序）。 <br /><br />在Apache SOAP中，org.apache.soap.rpc包支持在SOAP上进行RPC调用。Apache RPC支持的关键在于对象ID。所有的Apache SOAP服务必须有一个唯一的ID，它被视为服务的对象ID。众所周知，唯一性是一个相对的概念；在Apache SOAP中，对象ID的唯一性相对于服务所部署的Apache SOAP服务器而言。也就是说，部署在不同Apache SOAP服务器上的两个服务可能有同样的对象ID。 <br /><br />想要使用服务的客户程序设置一个org.apache.soap.rpc.Call对象，指定目标服务的对象ID、待调用方法的名字以及提供给方法的参数（如果有的话）。设置好Call对象之后，客户程序调用它的invoke()方法。invoke()方法需要两个参数，第一个参数是一个执行rpcrouter Servlet的URL，如http://localhost:8080/apache-soap/servlet/rpcrouter；第二个参数是SOAPAction头（请参考本系列的第一篇文章，了解SOAPAction头的重要性和可能的取值）。 <br /><br />invoke()方法把Call对象转换成XML SOAP请求（类似第一篇文章所提供的示例），把请求发送给第一个参数中的URL所指定的rpcrouter Servlet。当Servlet返回应答，invoke()方法返回一个org.apache.soap.rpc.Response对象，这个对象包含了服务的应答（如果有的话）或错误信息（如果出现了错误）。HTTP规定每一个请求都必须有一个应答；因此，即使服务本身不返回任何东西，rpcrouter Servlet总是会返回一些内容。因此，invoke()方法总是返回一个Response对象。 <br /><br />在服务端，Apache SOAP服务器（也就是rpcrouter Servlet）接收客户程序发送的SOAP请求，重新构造出Call对象。Servlet使用重新构造得到的Call对象中的对象ID在服务管理器中确定具体的对象。 <br /><br />接下来，Servlet在已经确定的对象上检验被调用方法的名字并调用方法。完成后，Servlet串行化该调用的返回值，在HTTP应答中把它发送给客户程序。 <br /><br />从上述讨论中，我们可以发现一个有趣的问题：Apache SOAP如何知道串行化某种给定数据类型的方法？Apache SOAP通过一个类型注册器（org.apache.soap.encoding.SOAPMappingRegistry），以及通过所有装配器（marshaller）和反装配器（marshaller）分别必须实现的串行化（org.apache.soap.util.xml.Serializer）和反串行化（org.apache.soap.util.xml.Deserialization）接口，实现Java数据类型和XML之间的装配和反装配。Apache SOAP提供了许多实现这些接口的内建的装配器和反装配器。例如，我们可以用org.apache.soap.encoding.soapenc.BeanSerializer类装配和反装配JavaBean。本文后面我将介绍如何使用这个类。 <br /><br />对于Java基本数据类型（int，long，double，等等）及其对应的对象化形式（Integer，Long，Double，等等）来说，它们的串行化器和反串行化器已经预先在类型映射注册器中注册。因此，对于客户程序来说，用Java基本数据类型及其对象形式作为方法参数是无缝的。然而，如果服务所要求的参数是一个JavaBean，则必须手工在类型映射注册器中注册BeanSerializer。服务永远不会做任何额外的工作，最后客户程序的负担总是较多。在这个系列的第四篇文章中，我将介绍用动态代理构造的框架，它将使创建客户程序和创建服务程序一样简单。 <br /><br /><strong>2.2、部署HelloWorld服务</strong><br />部署Apache SOAP服务有两种方法：使用Web界面的管理工具，或通过命令行进行部署。所有这两种方法都可以部署服务，使服务可被客户程序访问。 <br /><br />■ 使用管理工具部署服务 <br /><br />要使用管理工具，用浏览器打开http://localhost:8080/apache-soap/admin。浏览器将显示出图一所示的界面。点击窗口左边的Deploy按钮，一个带有许多输入框的窗口就会出现。并非所有的输入框现在都要用到。我将在用到这些输入框的时候介绍它们的含义。由于本文无需用到所有的输入框，所以我们将忽略部分输入框的含义。但不用担心，到第三篇文章结束时，我将介绍完所有的输入框。 <br /><br />ID输入框用来设置对象ID；如前所述，SOAP基础设施利用对象ID把RPC请求绑定到SOAP服务。我在前面已经提到，所有Apache SOAP服务必须有一个对象ID，这个对象ID在该服务器上部署的所有服务之间唯一。我通常使用“urn:&amp;lt;UniqueServiceID&amp;gt;”格式，其中UniqueServiceID是服务的唯一对象ID。在本例中，把ID设置成“urn:hello”。 <br /><br />Scope输入框用来定义响应调用请求的服务实例的生存范围和时间。Scope可以是下列值之一： <br /><br /><li>page：服务实例一直有效，直至应答发送完毕或把请求传递给了另一个页面——如果使用标准的部署机制，向前传递请求不太可能发生。 
</li><li>request：服务实例在请求处理期间一直有效，不管是否出现请求传递。 
</li><li>session：服务实例对于整个会话都有效。 
</li><li>application：服务实例被用于所有对服务的调用请求。 
<ul></ul>Scope的值对安全有着重要的影响，记住这一点很重要。page和request值确保了连续调用之间的隔离。在另一个极端，application值意味着所有SOAP的用户共享服务实例。细心的读者可能已经注意到，JSP的&lt;jsp:useBean&gt;标记同样要用到这些值。事实上，rpcrouter Servlet曾经就是一个JSP页面，这也许是这些值被选用的原因。在本例中，我们把Scope的值设置成application。 <br /><br />在Methods输入框中，输入用空白字符分隔的方法名字，这些方法名字指示出当前部署的服务上允许调用的方法。我们的服务示例只支持一个方法，即sayHelloTo()。 <br /><br />把Provider Type设置成Java。它意味着服务用Java实现，而且你必须为Apache SOAP提供服务完整的类名。这个任务在Provider Class输入框完成，我们把它设置成hello.HelloServer。由于sayHelloTo()方法不是静态的，保持Static输入框原来的值，即no。 <br /><br />现在滚动到页面的下方，点击表单下面的Deploy按钮（不是左边的Deploy按钮）。要验证服务已经部署完毕，点击左边的List按钮，这时列表所显示的服务中应该包含一个urn:Hello服务。 <br /><br />■ 从命令行部署服务 <br /><br />部署服务除了可以用Web界面的管理工具，还可以用命令行Java工具org.apache.soap.server.ServiceManagerClient，它是一个Apache SOAP附带的类。这个类要求有两个必不可少的参数，一个指向Apache SOAP路由Servlet（即rpcrouter）的URL，以及一个动作。这个动作可以是以下四者之一：deploy，undeploy，list，或query。根据指定动作的不同，有时候还要提供额外的参数。例如，如果动作是deploy，则必须提供XML部署描述器文件的名字。部署描述器文件应该包含Apache SOAP服务器成功部署服务所需要的全部信息。例如，描述HelloWorld部署细节的部署XML文件可以如下： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>&lt;isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment"<br />id="urn:Hello"&gt;<br />&lt;isd:provider type="java" scope="Application" methods="sayHelloTo"&gt;<br />&lt;isd:java class="hello.HelloServer" static="false"/&gt;<br />&lt;/isd:provider&gt;<br />&lt;/isd:service&gt;</p></td></tr></tbody></table><br />上述XML代码所包含的信息和我们在Web界面的管理工具中所输入的信息一样。接下来，输入下面的命令，从命令行部署HelloWorld服务： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>java org.apache.soap.server.ServiceManagerClient<br />http://localhost:8080/apache-soap/servlet/rpcrouter<br />deploy DeploymentDescriptor.xml</p></td></tr></tbody></table><br />DeploymentDescriptor.xml是上面显示的描述部署信息的XML文件名字。要验证服务是否部署成功，输入以下命令： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>java org.apache.soap.server.ServiceManagerClient<br />http://localhost:8080/apache-soap/servlet/rpcrouter query urn:Hello</p></td></tr></tbody></table><br />这时，我们应该看到和DeploymentDescriptor.xml文件内一样的XML。 <br /><br /><strong>2.3、HelloWorld客户程序</strong><br />编写客户程序要比编写HelloWorld服务复杂得多。不过，你应该不会对此感到奇怪，因为前面已经提到，客户程序（至少）必须负责设置Call对象，这需要不少工作。顺便说一下，本系列文章的第四篇将介绍一个框架，这个框架以Java 2 1.3版新引入的动态代理类为基础，使创建客户程序和创建服务一样简单。 <br /><br />Listing 1显示了完整的客户程序。接下来我们一步一步地仔细看看这个程序。这个程序需要一个必不可少的参数：程序要向他说Hello信息的用户名字。 <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>Listing 1: Client.java</p><p>package hello;</p><p>import java.net.URL;<br />import java.util.Vector;<br />import org.apache.soap.SOAPException;<br />import org.apache.soap.Constants;<br />import org.apache.soap.Fault;<br />import org.apache.soap.rpc.Call;<br />import org.apache.soap.rpc.Parameter;<br />import org.apache.soap.rpc.Response;<br /><br />public class Client<br />{<br />public static void main(String[] args) throws Exception<br />{<br />if(args.length == 0)<br />{<br />System.err.println("Usage: java hello.Client [SOAP-router-URL] ");<br />System.exit (1);<br />}</p><p>try<br />{<br />URL url = null;<br />String name = null;<br />if(args.length == 2)<br />{<br />url = new URL(args[0]);<br />name = args[1];<br />}<br />else<br />{<br />url = new URL("http://localhost:8080/apache-soap/servlet/rpcrouter");<br />name = args[0];<br />}</p><p>// 构造Call对象<br />Call call = new Call();<br />call.setTargetObjectURI("urn:Hello");<br />call.setMethodName("sayHelloTo");<br />call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);<br />Vector params = new Vector();<br />params.addElement(new Parameter("name", String.class, name, null));<br />call.setParams(params);</p><p>// 发出调用<br />Response resp = null;<br />try<br />{<br />resp = call.invoke(url, "");<br />}<br />catch( SOAPException e )<br />{<br />System.err.println("Caught SOAPException (" + e.getFaultCode() + "): " +<br />e.getMessage());<br />System.exit(-1);<br />}<br /><br />// 检查应答<br />if( !resp.generatedFault() )<br />{<br />Parameter ret = resp.getReturnValue();<br />Object value = ret.getValue();<br />System.out.println(value);<br />}<br />else<br />{<br />Fault fault = resp.getFault();<br />System.err.println("Generated fault: ");<br />System.out.println (" Fault Code = " + fault.getFaultCode());<br />System.out.println (" Fault String = " + fault.getFaultString());<br />}<br />}<br />catch(Exception e)<br />{<br />e.printStackTrace();<br />}<br />}<br />}</p></td></tr></tbody></table><br />客户程序首先设置Call对象，它需要如下信息： <br /><br /></li><li>被调用服务的对象ID，它通过Call对象的setTargetObjectURI()方法设置。本例的对象ID是urn:Hello。 
</li><li>待调用方法的名字，它通过Call对象的setMethodName()方法设置。本例的方法名字是sayHelloTo()。 
</li><li>参数的编码方式，它通过Call对象的setEncodingStyleURI()方法设置。本例我们使用标准的SOAP编码方式，这种编码方式由名称空间http://schemas.xmlsoap.org/soap/encoding/定义。 
</li><li>方法调用的参数通过Call对象的setParams()方法设置。setParams()方法的参数是一个Java Vector（向量）。这个向量包含所有的参数，向量中索引为0的参数是被调用方法从左边数起的第一个参数，索引为1的参数是被调用方法从左边数起的第二个参数，依此类推。向量中的每一个元素都是一个org.apache.soap.rpc.Parameter的实例。Parameter构造函数要求指定参数的名字、Java类型和值，还有一个可选的编码方式。如果指定了null编码方式（正如本例所做的那样），则默认使用Call对象的编码方式。虽然每一个参数对应着一个名字，但这个名字可以设置成任何内容，Apache SOAP服务器调用方法时不会用到这个名字。因此，绝对有必要让向量中参数的次序和被调用方法的参数次序一致。 
<ul></ul>下面的代码片断显示了客户程序创建Call对象的过程： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>// 构造Call对象<br />Call call = new Call();<br />call.setTargetObjectURI("urn:Hello");<br />call.setMethodName("sayHelloTo");<br />call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);<br />Vector params = new Vector();<br />params.addElement(new Parameter("name", String.class, name, null));<br />call.setParams(params);</p></td></tr></tbody></table><br />现在，该是实际调用HelloWorld远程服务所提供方法的时候了。为此，客户程序调用了Call对象的invoke()方法，这个方法返回一个org.apache.soap.rpc.Response对象，如下所示： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>// 发出调用<br />Response resp = null;<br />try<br />{<br />resp = call.invoke(url, "");<br />}<br />catch( SOAPException e )<br />{<br />System.err.println("Caught SOAPException (" + e.getFaultCode() + "): " +<br />e.getMessage());<br />System.exit(-1);<br />}</p></td></tr></tbody></table><br />接下来，客户程序检查Response对象。如果方法调用过程中出现了错误，generateFault()方法返回一个true值，客户程序提取并显示实际的错误信息： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>Fault fault = resp.getFault();<br />System.err.println("Generated fault: ");<br />System.out.println (" Fault Code = " + fault.getFaultCode());<br />System.out.println (" Fault String = " + fault.getFaultString());</p></td></tr></tbody></table><br />如果方法调用成功，则客户程序提取并显示Hello信息： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>// 检查应答<br />if( !resp.generatedFault() )<br />{<br />Parameter ret = resp.getReturnValue();<br />Object value = ret.getValue();<br />System.out.println(value);<br />}</p></td></tr></tbody></table><br /><strong>三、带有JavaBean的HelloWorld实例</strong><br />如前所述，Apache SOAP提供了许多预先构造的串行化和反串行化方法，其中包括为利用Java Vector、Enumeration、数组、JavaBean作为参数和返回值而提供的串行化器和反串行化器。在这一部分，我将修改HelloWorld服务，通过一个JavaBean传入接收Hello信息的用户名。 <br /><br /><strong>3.1、HelloWorld服务 </strong><br />改写后的HelloWorld服务完整代码如下： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>package hello;<br />public class HelloServer<br />{<br />public String sayHelloTo(String name)<br />{<br />System.out.println("sayHelloTo(String name)");<br />return "Hello " + name + ", How are you doing?";<br />}</p><p>public <strong>String sayHelloTo(Name theName)</strong><br />{<br />System.out.println("sayHelloTo(Name theName)");<br />return "Hello " + theName.getName() + ", How are you doing?";<br />}<br />}</p></td></tr></tbody></table><br />服务的代码仍旧很简单，仍旧类似于不用JavaBean时的HelloWorld服务。不过，这意味着最复杂的工作都转移到了客户端。事实上，这个版本的服务与以前版本的唯一差别在于，现在出现了一个重载的sayHelloTo()方法。上面的代码中重载后的方法用粗体字显示。 <br /><br />重载的方法需要一个对Name JavaBean的引用。Name JavaBean的定义如下： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>package hello;</p><p>public class Name<br />{<br />private String name;<br />public String getName()<br />{<br />return name;<br />}<br />public void setName(String name)<br />{<br />this.name = name;<br />}<br />}</p></td></tr></tbody></table><br /><strong>3.2、部署服务</strong><br />部署一个使用了JavaBean的服务时，需要为Apache SOAP服务器提供一些额外的信息。因此，现在部署服务的过程稍微复杂一点。 <br /><br />■ 使用管理工具部署服务 <br /><br />要使用管理工具部署这个新版的HelloWorld服务，首先按照前面所介绍的步骤进行，但这一次不要点击Deploy按钮。现在，在Number of Mappings输入框输入1，它表示我们将给出一个映射（即Name JavaBean）的信息。紧接Mappings之下有一个表格，我们要用到这个表格的第一行。保留Encoding Style的值为SOAP，把NameSpace URI设置成对象的ID：在本例中，它是urn:Hello。接下来，把Local Part和Java Type输入框设置成Name JavaBean的完整名字，即hello.Name。最后，把Java to XML Serializer和XML to Java Deserializer输入框设置成org.apache.soap.encoding.soapenc.BeanSerializer，这是一个实现了Serializer和Deserializer接口的类，用来串行化和反串行化Name JavaBean。如果你用到了更多的JavaBean（比如还有一个Address Bean），则应该在这个表格中输入其他Bean的信息，同时还应该更新Number of Mappings输入框的值，使之反映出表格中实际被使用的行数。 <br /><br />■ 从命令行部署服务 <br /><br />要从命令行进行部署，我们只需修改作为命令行参数传入的XML部署描述器文件。修改后的XML文件如下所示： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>&lt;isd:service xmlns:isd="http://xml.apache.org/xml-soap/deployment" id="urn:Hello"&gt;<br />&lt;isd:provider type="java" scope="Application" methods="sayHelloTo"&gt;<br />&lt;isd:java class="hello.HelloServer" static="false"/&gt;<br />&lt;/isd:provider&gt;<br />&lt;isd:mappings&gt;<br />&lt;isd:map encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"<br />xmlns:x="urn:Hello" qname="x:hello.Name"<br />javaType="hello.Name"<br />java2XMLClassName="org.apache.soap.encoding.soapenc.BeanSerializer"<br />xml2JavaClassName="org.apache.soap.encoding.soapenc.BeanSerializer"/&gt;<br />&lt;/isd:mappings&gt;<br />&lt;/isd:service&gt;</p></td></tr></tbody></table><br />正如在前一个例子中，这些XML代码所包含的信息和通过Web界面的管理工具所提供的信息一样。 <br /><br /><strong>3.3、HelloWorld客户程序</strong><br />和第一个例子一样，客户程序更复杂，也更令人感兴趣。这里我不再仔细分析整个客户程序，而是介绍两个客户程序版本的不同之处。由于调用方法的一个参数（在本例中，它是唯一的参数）是一个JavaBean，所以必须手工设置一个类型映射注册项。这个任务通过如下步骤完成：先创建org.apache.soap.encoding.SOAPMappingRegistry类的一个实例，然后调用它的mapTypes()方法。正如mapTypes()方法名字所预示的，它用来注册一个以前未知的类型，比如定制的JavaBean。mapTypes()方法的参数包括要使用的编码方式、限定的JavaBean名字、类型的完整类名、串行化器和反串行化器。在本例中，执行串行化任务的是标准的Bean串行化器。限定的JavaBean名字包含一个元素的名字，包括它所属的名称空间。在本例中，Name JavaBean的限定名字由名称空间URI（urn:Hello）和本地名字（hello.Name）结合构成。请看下面的代码片断： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>// 创建类型映射注册器<br />SOAPMappingRegistry smr = new SOAPMappingRegistry();<br />BeanSerializer beanSer = new BeanSerializer();<br />// 映射类型<br />smr.mapTypes(Constants.NS_URI_SOAP_ENC,<br />new QName("urn:Hello", "hello.Name"),hello.Name.class, beanSer, beanSer);</p></td></tr></tbody></table><br />接下来，客户程序必须告诉Call对象使用新的注册器而不是默认的注册器。为此，我们要调用Call对象的setSOAPMappingRegistry()方法，如下所示： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6">call.setSOAPMappingRegistry(smr);</td></tr></tbody></table><br />手工设置好类型映射注册器之后，接下来还必须为Call对象设置参数。这一步骤可以按前面介绍的方法完成，不同之处在于，现在我们不再用字符串类型的名字作为参数，而是用JavaBean作为参数，如下所示： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>// 设置调用参数<br />Vector params = new Vector();<br />Name theName = new Name();<br />theName.setName(name);<br />params.addElement(new Parameter("name", hello.Name.class, theName, null));<br />call.setParams(params);</p></td></tr></tbody></table><br />客户程序剩下的部分和原来的版本一样。Listing 3显示了完整的客户程序代码： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>Listing 3: Client2.java</p><p>package hello;</p><p>import java.net.URL;<br />import java.util.Vector;<br />import org.apache.soap.SOAPException;<br />import org.apache.soap.Constants;<br />import org.apache.soap.Fault;<br />import org.apache.soap.rpc.Call;<br />import org.apache.soap.rpc.Parameter;<br />import org.apache.soap.rpc.Response;<br />import org.apache.soap.encoding.SOAPMappingRegistry;<br />import org.apache.soap.encoding.soapenc.BeanSerializer;<br />import org.apache.soap.util.xml.QName;<br /><br />public class Client2<br />{<br />public static void main(String[] args) throws Exception<br />{<br />if(args.length == 0)<br />{<br />System.err.println("Usage: java hello.Client [SOAP-router-URL] ");<br />System.exit (1);<br />}</p><p>try<br />{<br />URL url = null;<br />String name = null;<br />if(args.length == 2)<br />{<br />url = new URL(args[0]);<br />name = args[1];<br />}<br />else<br />{<br />url = new URL("http://localhost:8080/apache-soap/servlet/rpcrouter");<br />name = args[0];<br />}</p><p>// 构造调用对象<br />Call call = new Call();<br />call.setTargetObjectURI("urn:Hello");<br />call.setMethodName("sayHelloTo");<br />call.setEncodingStyleURI(Constants.NS_URI_SOAP_ENC);</p><p>// 创建类型映射注册器<br />SOAPMappingRegistry smr = new SOAPMappingRegistry();<br />BeanSerializer beanSer = new BeanSerializer();<br />// 映射类型<br />smr.mapTypes(Constants.NS_URI_SOAP_ENC,<br />new QName("urn:Hello", "hello.Name"),<br />hello.Name.class, beanSer, beanSer);<br />call.setSOAPMappingRegistry(smr);</p><p>// 设置参数<br />Vector params = new Vector();<br />Name theName = new Name();<br />theName.setName(name);<br />params.addElement(new Parameter("name", hello.Name.class,<br />theName, null));<br />call.setParams(params);</p><p>// 发出调用<br />Response resp = null;<br />try<br />{<br />resp = call.invoke(url, "");<br />}<br />catch( SOAPException e )<br />{<br />System.err.println("Caught SOAPException (" +<br />e.getFaultCode() + "): " + e.getMessage());<br />System.exit(-1);<br />}<br /><br />// 检查应答<br />if( !resp.generatedFault() )<br />{<br />Parameter ret = resp.getReturnValue();<br />Object value = ret.getValue();<br />System.out.println(value);<br />}<br />else<br />{<br />Fault fault = resp.getFault();<br />System.err.println("Generated fault: ");<br />System.out.println (" Fault Code = " + fault.getFaultCode());<br />System.out.println (" Fault String = " + fault.getFaultString());<br />}<br />}<br />catch(Exception e)<br />{<br />e.printStackTrace();<br />}<br />}<br />}</p></td></tr></tbody></table><br /><strong>四、编译和运行程序</strong><br />现在整个程序的开发工作已经完成，该是运行它的时候了。不过，我们首先要编译服务程序和客户程序。 <br /><br />创建一个hello目录，把Client1.java、Client2.java和HelloServer.java复制到这个目录。我把hello目录放到了Apache SOAP的示例目录（即E:\soap-2_0\samples）之下。编译程序时，classpath中只需包含hello目录的父目录（即E:\soap-2_0\samples）、soap.jar和xerces.jar。我用下面的批命令编译程序： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><p>set CLASSPATH=E:\soap-2_0\samples\;E:\soap-2_0\lib\soap.jar;E:\xerces-1_2_0\xerces.jar<br />javac -d .. HelloServer.java Client.java Client2.java</p></td></tr></tbody></table><br />注意：从hello目录执行这个批命令文件。 <br /><br />要使用这个服务，除了部署它之外，还需要修改Web服务器的classpath，确保Web服务能够找到hello.HelloServer类——对于本例，这是指把E:\soap-2_0\samples加入到Web服务器的classpath。对classpath进行必要的修改之后，重新启动Web服务器。接下来就可以运行客户程序了。下面是我运行hello.Client的批命令文件： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6">set CLASSPATH=E:\soap-2_0\samples\;E:\soap-2_0\lib\soap.jar;E:\xerces-1_2_0\xerces.jar<br />java hello.Client Tarak</td></tr></tbody></table><br />这里的classpath和编译程序时用的classpath相同。 <br /><br />最后，运行hello.Client2的批命令文件可以如下： <br /><br /><table cellspacing="0" bordercolordark="#ffffff" cellpadding="0" width="580" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6">set CLASSPATH=E:\soap-2_0\samples\;E:\soap-2_0\lib\soap.jar;E:\xerces-1_2_0\xerces.jar<br />java hello.Client2 Tarak</td></tr></tbody></table><br />观察Web服务器的控制台窗口，看看在运行两个不同的客户程序时，HelloWorld服务的哪些方法正在被调用。 <br /><br /><strong>■ 结束语</strong><br />在这篇文章中，我介绍了如何用Apache SOAP实现来创建简单的基于SOAP的服务。在SOAP实现方面，另一个重要的竞争者是Microsoft。遗憾的是，“纯”Java开发者在使用Microsoft实现的时候会有一段艰苦的时光，因为它的实现包含了COM对象。 <br /><br />在下一篇文章中，我将介绍Apache SOAP支持的另一种创建服务的方式：使用JavaScript之类的脚本语言，而不是Java。另外，我还要介绍一个很不错的JavaScript引擎，即Rhino。（<a href="http://www.ccidnet.com/tech/app/2001/09/21/58_3320.html" target="_blank">下一篇</a>） <br /><strong>■ 参考资源</strong><br /><ul><li>W3C的SOAP 1.1规范：<br /><a href="http://www.w3.org/TR/SOAP/" target="_blank">http://www.w3.org/TR/SOAP/</a></li><li>下载Apache SOAP：<br /><a href="http://xml.apache.org/dist/soap/" target="_blank">http://xml.apache.org/dist/soap/</a></li><li>有关IBM SOAP工程的更多信息：<br /><a href="http://www.alphaworks.ibm.com/tech/soap4j" target="_blank">http://www.alphaworks.ibm.com/tech/soap4j</a></li><li>Apache SOAP可用功能的一个清单：<br /><a href="http://xml.apache.org/soap/features.html" target="_blank">http://xml.apache.org/soap/features.html</a></li><li>Apache许可协议：<br /><a href="http://www.apache.org/LICENSE.txt" target="_blank">http://www.apache.org/LICENSE.txt</a></li><li>下载Tomcat 3.1<br /><a href="http://jakarta.apache.org/builds/jakarta-tomcat/release/v3.1.1/bin/" target="_blank">http://jakarta.apache.org/builds/jakarta-tomcat/release/v3.1.1/bin/</a></li><li>下载Apache Xerces 1.2版本：<br /><a href="http://xml.apache.org/dist/xerces-j/" target="_blank">http://xml.apache.org/dist/xerces-j/</a></li><li>"MS SOAP SDK vs IBM SOAP4J: Comparison &amp; Review," James Snell (O'Reilly): <br /><a href="http://windows.oreilly.com/news/soapreview_0600.html" target="_blank">http://windows.oreilly.com/news/soapreview_0600.html</a><br /></li></ul>（责任编辑 吴北 <a href="mailto:jiaoxq@staff.ccidnet.com">jiaoxq@staff.ccidnet.com</a>）<br /><!---文章内容主体部分结- --></li><img src ="http://www.blogjava.net/leitianguang/aggbug/96559.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2007-01-29 17:49 <a href="http://www.blogjava.net/leitianguang/articles/96559.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Dojo.Book 第一章（burnet翻译） </title><link>http://www.blogjava.net/leitianguang/articles/58216.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Fri, 14 Jul 2006 08:46:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/58216.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/58216.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/58216.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/58216.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/58216.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Dojo.Book 第一章（burnet翻译）																																																																																																																										英文版:http://manual.dojotoolkit.org/WikiH...&nbsp;&nbsp;<a href='http://www.blogjava.net/leitianguang/articles/58216.html'>阅读全文</a><img src ="http://www.blogjava.net/leitianguang/aggbug/58216.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2006-07-14 16:46 <a href="http://www.blogjava.net/leitianguang/articles/58216.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>dojo： jsLINB --- javascript工具包</title><link>http://www.blogjava.net/leitianguang/articles/58204.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Fri, 14 Jul 2006 07:43:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/58204.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/58204.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/58204.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/58204.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/58204.html</trackback:ping><description><![CDATA[
		<p>
				<a class="reference" href="http://dojotoolkit.org/">
						<span class="highlightedSearchTerm">
								<font style="BACKGROUND-COLOR: #feff82">dojo</font>
						</span>
				</a> 是采用BSD许可的开源javascript工具包，现在发展迅猛，得到广泛的支持，成立了 <a class="reference" href="http://dojotoolkit.org/foundation/"><font color="#436976"><span class="highlightedSearchTerm"><font style="BACKGROUND-COLOR: #feff82">dojo</font></span> 基金会</font></a> , IBM / AOL 这些大公司都是<span class="highlightedSearchTerm"><font style="BACKGROUND-COLOR: #feff82">dojo</font></span>基金会的成员。</p>
		<p>看看demo是最有说服力的了，按下面的操作进入demo(居然没有直达的链接！)：</p>
		<ol class="arabic">
				<li>
						<p class="first">点击下面的链接，进入主页：</p>
						<p>
								<a class="reference" href="http://dojotoolkit.org/">http://<span class="highlightedSearchTerm"><font style="BACKGROUND-COLOR: #feff82">dojo</font></span>toolkit.org/</a>
						</p>
				</li>
				<li>
						<p class="first">点击上面的 <tt class="docutils literal"><span class="pre">see</span><span class="pre">it</span><span class="pre">in</span><span class="pre">action</span></tt> 标签，这里分门别类罗列了各种例子</p>
				</li>
		</ol>
		<p>jsLINB--国人写的一个完整web2.0技术框架。jsLINB的在线demo：http://www.linb.net/linb/，里面包括变量类型检测、强制类型变量、javascript线程实现、完美OO模型、基于dom id的事件系统实现、dom元素的“随动”实现、高级托拽、sorted grid控件、tree grid控件等等。 http://www.linb.net/linb/#102002 jsLINB框架图 http://www.linb.net/linb/#102101001 变量类型检测 http://www.linb.net/linb/#102101002 强制类型变量 http://www.linb.net/linb/#102101003 javascript线程实现 http://www.linb.net/linb/#102101103 36位guid http://www.linb.net/linb/#102105001 基于dom id的事件系统实现 http://www.linb.net/linb/#102105002 dom元素的“随动”实现 http://www.linb.net/linb/#102106002001 基本拖拽 http://www.linb.net/linb/#102106002002 限制拖拽 http://www.linb.net/linb/#102106002003 拖拽任何domnode http://www.linb.net/linb/#102106002004 网格拖拽 http://www.linb.net/linb/#102106002005 停靠拖拽 http://www.linb.net/linb/#102106002006 多handle拖拽 http://www.linb.net/linb/#102106002007 图标代理拖拽 http://www.linb.net/linb/#102106002008 多目标drop http://www.linb.net/linb/#102109001 快速html生成 http://www.linb.net/linb/#102109002 DOM控制封装 http://www.linb.net/linb/#102109004 基于线程的特效 http://www.linb.net/linb/#102010 直接调用 http://www.linb.net/linb/#102011 完美OO实现 http://www.linb.net/linb/#203004003 Treebar控件 http://www.linb.net/linb/#203005003001 sorted grid控件 http://www.linb.net/linb/#203005003002 tree grid控件 http://www.linb.net/linb/#203007003 window控件</p>
<img src ="http://www.blogjava.net/leitianguang/aggbug/58204.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2006-07-14 15:43 <a href="http://www.blogjava.net/leitianguang/articles/58204.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DWR源码学习函数调用篇 [转]</title><link>http://www.blogjava.net/leitianguang/articles/51706.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Fri, 09 Jun 2006 07:49:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/51706.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/51706.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/51706.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/51706.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/51706.html</trackback:ping><description><![CDATA[
		<div class="postTitle"> </div>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>Dwr</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">通过用户配置文件</span>
				<span lang="EN-US">dwr.xml</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">将</span>
				<span lang="EN-US">java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类映射成一个</span>
				<span lang="EN-US">javascript</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">对象，从实现手法上看与</span>
				<span lang="EN-US">java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里的数据映射很相似。而</span>
				<span lang="EN-US">dwr</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">是将</span>
				<span lang="EN-US">JAVA</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">的对象映射到了</span>
				<span lang="EN-US">js</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">里，由客户端的</span>
				<span lang="EN-US">JS</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">提供给用户各类实现，而</span>
				<span lang="EN-US">java</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码完全在后台运行。</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>DWR</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数调用里涉及到的</span>
				<span lang="EN-US">JS</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">代码：</span>
				<span lang="EN-US">engine.js</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span lang="EN-US">
						<span style="mso-tab-count: 1">       </span>DWR</span>
				<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">函数调用里涉及到的类有：</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: 'Courier New'; mso-highlight: silver; mso-font-kerning: 0pt">AbstractDWRServlet</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">、</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: 'Courier New'; mso-highlight: silver; mso-font-kerning: 0pt">DefaultProcessor</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">
						<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">用户在提交</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">request</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">以后的操作步骤请参见我</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">blog</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">里的：《</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">dwr</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">源码学习（一）》，</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">JAVA</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">代码生成的映射</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">JS</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">代码其实只是一个</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">javascript</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">接口，它调用了</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">DWREngine._execute</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">这个函数，而这个函数大体只是执行了一些解析的工作，在它结尾处调用了</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">DWREngine.endBatch()</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">，然后又执行了</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">DWREngine._sendData(batch)</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">，这时我们会发现有这样一句：</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">
				</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">“</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">batch.req.open("GET", batch.path + "/exec/" + statsInfo + "?" + query, batch.async);</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">”很熟悉吧。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">
						<span style="mso-tab-count: 1">    </span>
				</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">下一步就到了真正的实现</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">js</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">调用</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">java</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">代码里方法的时候了，兴奋吧。其实实现也是很简单的。通过</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">servlet</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">这里实现了对各类型</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">request</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">参数的不同的匹配，还是看</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: 'Courier New'; mso-highlight: silver; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">AbstractDWRServlet</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-fareast-font-family: 宋体; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">.getPost()</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">这个方法：<br /></span>
		</p>
		<div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee">
				<span style="COLOR: #008080"> 1</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">protected</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> doPost(HttpServletRequest req, HttpServletResponse resp) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> IOException, ServletException<br /></span><span style="COLOR: #008080"> 2</span> <span style="COLOR: #000000">    {<br /></span><span style="COLOR: #008080"> 3</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">try</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 4</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080"> 5</span> <span style="COLOR: #000000">            builder.set(req, resp, getServletConfig(), getServletContext(), container);<br /></span><span style="COLOR: #008080"> 6</span> <span style="COLOR: #000000">            ServletLoggingOutput.setExecutionContext(</span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">);<br /></span><span style="COLOR: #008080"> 7</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080"> 8</span> <span style="COLOR: #000000">            processor.handle(req, resp);<br /></span><span style="COLOR: #008080"> 9</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">10</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">finally</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">11</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">12</span> <span style="COLOR: #000000">            builder.unset();<br /></span><span style="COLOR: #008080">13</span> <span style="COLOR: #000000">            ServletLoggingOutput.unsetExecutionContext();<br /></span><span style="COLOR: #008080">14</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">15</span> <span style="COLOR: #000000">}<br /></span><span style="COLOR: #008080">16</span> <span style="COLOR: #000000">注意processor.handle(req, resp);<br /></span><span style="COLOR: #008080">17</span> <span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> handle(HttpServletRequest req, HttpServletResponse resp) </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> IOException, ServletException<br /></span><span style="COLOR: #008080">18</span> <span style="COLOR: #000000">    {<br /></span><span style="COLOR: #008080">19</span> <span style="COLOR: #000000">        String pathInfo </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> req.getPathInfo();<br /></span><span style="COLOR: #008080">20</span> <span style="COLOR: #000000">        String servletPath </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> req.getServletPath();<br /></span><span style="COLOR: #008080">21</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">22</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (nullPathInfoWorkaround </span><span style="COLOR: #000000">&amp;&amp;</span><span style="COLOR: #000000"> pathInfo </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000">)<br /></span><span style="COLOR: #008080">23</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">24</span> <span style="COLOR: #000000">            pathInfo </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> req.getServletPath();<br /></span><span style="COLOR: #008080">25</span> <span style="COLOR: #000000">            servletPath </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> HtmlConstants.PATH_ROOT;<br /></span><span style="COLOR: #008080">26</span> <span style="COLOR: #000000">            log.debug(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Default servlet suspected. pathInfo=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> pathInfo </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">; contextPath=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> req.getContextPath() </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">; servletPath=</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> servletPath); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">$NON-NLS-1$ </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">$NON-NLS-2$ </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">$NON-NLS-3$</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #008080">27</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">28</span> <span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">29</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">null</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">30</span> <span style="COLOR: #000000">            pathInfo.length() </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">||</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">31</span> <span style="COLOR: #000000">            pathInfo.equals(HtmlConstants.PATH_ROOT))<br /></span><span style="COLOR: #008080">32</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">33</span> <span style="COLOR: #000000">            resp.sendRedirect(req.getContextPath() </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> servletPath </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> HtmlConstants.FILE_INDEX);<br /></span><span style="COLOR: #008080">34</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">35</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.startsWith(HtmlConstants.FILE_INDEX))<br /></span><span style="COLOR: #008080">36</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">37</span> <span style="COLOR: #000000">            index.handle(req, resp);<br /></span><span style="COLOR: #008080">38</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">39</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.startsWith(HtmlConstants.PATH_TEST))<br /></span><span style="COLOR: #008080">40</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">41</span> <span style="COLOR: #000000">            test.handle(req, resp);<br /></span><span style="COLOR: #008080">42</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">43</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.startsWith(HtmlConstants.PATH_INTERFACE))<br /></span><span style="COLOR: #008080">44</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">45</span> <span style="COLOR: #000000">            iface.handle(req, resp);<br /></span><span style="COLOR: #008080">46</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">47</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.startsWith(HtmlConstants.PATH_EXEC))<br /></span><span style="COLOR: #008080">48</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">49</span> <span style="COLOR: #000000">            exec.handle(req, resp);<br /></span><span style="COLOR: #008080">50</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">51</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.equalsIgnoreCase(HtmlConstants.FILE_ENGINE))<br /></span><span style="COLOR: #008080">52</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">53</span> <span style="COLOR: #000000">            file.doFile(req, resp, HtmlConstants.FILE_ENGINE, HtmlConstants.MIME_JS);<br /></span><span style="COLOR: #008080">54</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">55</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.equalsIgnoreCase(HtmlConstants.FILE_UTIL))<br /></span><span style="COLOR: #008080">56</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">57</span> <span style="COLOR: #000000">            file.doFile(req, resp, HtmlConstants.FILE_UTIL, HtmlConstants.MIME_JS);<br /></span><span style="COLOR: #008080">58</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">59</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (pathInfo.equalsIgnoreCase(HtmlConstants.FILE_DEPRECATED))<br /></span><span style="COLOR: #008080">60</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">61</span> <span style="COLOR: #000000">            file.doFile(req, resp, HtmlConstants.FILE_DEPRECATED, HtmlConstants.MIME_JS);<br /></span><span style="COLOR: #008080">62</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">63</span> <span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #008080">64</span> <span style="COLOR: #000000">        {<br /></span><span style="COLOR: #008080">65</span> <span style="COLOR: #000000">            log.warn(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">Page not found (</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> pathInfo </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">). In debug/test mode try viewing /[WEB-APP]/dwr/</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">$NON-NLS-1$ </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">$NON-NLS-2$</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #008080">66</span> <span style="COLOR: #008000"></span><span style="COLOR: #000000">            resp.sendError(HttpServletResponse.SC_NOT_FOUND);<br /></span><span style="COLOR: #008080">67</span> <span style="COLOR: #000000">        }<br /></span><span style="COLOR: #008080">68</span> <span style="COLOR: #000000">    }<br /></span><span style="COLOR: #008080">69</span> <span style="COLOR: #000000"></span></div>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">也就只有这几种类型的请求，还记得</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">DWREngine._sendData</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">吗？里面有这么一句：“</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">batch.req.open("GET", batch.path + "/exec/" + statsInfo + "?" + query, batch.async);</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">”看到他的请求路径是</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">exec</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">，对应在</span>
				<b style="mso-bidi-font-weight: normal">
						<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">processor.handle(req, resp);</span>
				</b>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">这个方法里就是</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">exec</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">，在刚才的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">JAVA</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">代码里我们已经看到过了是括号内的代码（</span>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: #7f0055; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">else</span>
				</b>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">
				</span>
				<b>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: #7f0055; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">if</span>
				</b>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">(pathInfo.startsWith(HtmlConstants.</span>
				<i>
						<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: #0000c0; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">PATH_EXEC</span>
				</i>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">))</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">），而</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">exec</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">早已在</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">servlet</span>
				<span style="FONT-SIZE: 10pt; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">初始化的时候就已经设置为</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; BACKGROUND: silver; COLOR: black; FONT-FAMILY: 'Courier New'; mso-highlight: silver; mso-font-kerning: 0pt">DefaultExecProcessor</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">，它的函数</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">hadle()</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">就是具体对</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">js</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">调用</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">java</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">类方法的实现了。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">
						<o:p>
						</o:p>
				</span>
		</p>
		<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt">
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">DWR</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">是一个小型的</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">AJAX</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">框架，它的实现思路简单，其实有很多人在开发中一定也有过类似的想法。它之所以现在才出现我想大概还是要归功于异步</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">javascript</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">消息发送这样的技术成为现实。所以我又想</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">AJAX</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">，从技术上说只能是</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">javascript</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">有了一个飞跃性的进步，而</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">AJAX</span>
				<span style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-font-kerning: 0pt; mso-bidi-font-family: 'Courier New'">的最终成功却要靠软件工程。</span>
				<span lang="EN-US" style="FONT-SIZE: 10pt; COLOR: black; FONT-FAMILY: 'Courier New'; mso-font-kerning: 0pt">
						<o:p>
						</o:p>
				</span>
		</p>
<img src ="http://www.blogjava.net/leitianguang/aggbug/51706.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2006-06-09 15:49 <a href="http://www.blogjava.net/leitianguang/articles/51706.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>DWR源码学习（一）[转]</title><link>http://www.blogjava.net/leitianguang/articles/51704.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Fri, 09 Jun 2006 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/51704.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/51704.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/51704.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/51704.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/51704.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: DWR一个外国人实现的很有前途的AJAX框架。多余的话就不说了，请看DWR的例子程序：web.xml 1&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt; 2&lt;!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java...&nbsp;&nbsp;<a href='http://www.blogjava.net/leitianguang/articles/51704.html'>阅读全文</a><img src ="http://www.blogjava.net/leitianguang/aggbug/51704.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2006-06-09 15:48 <a href="http://www.blogjava.net/leitianguang/articles/51704.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转换HTML内容为PDF格式(2) [转]</title><link>http://www.blogjava.net/leitianguang/articles/49935.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Fri, 02 Jun 2006 07:00:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/49935.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/49935.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/49935.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/49935.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/49935.html</trackback:ping><description><![CDATA[
		<div class="postbody">
				<p class="MsoNormal">
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt">Java </span>
						</b>
						<b>
								<span style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">程序</span>
						</b>
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt">
										<?XML:NAMESPACE PREFIX = O /?>
										<o:p>
										</o:p>
								</span>
						</b>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">通过使用上述步骤中用过的三个工具的</span>
						<span lang="EN-US">DOM API</span>
						<span style="FONT-FAMILY: 宋体">，我接下来会展示一个</span>
						<span lang="EN-US">JAVA</span>
						<span style="FONT-FAMILY: 宋体">程序。它在运行时需要提供两个命令行参数，会自动生成相应的</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">文档，并且不会产生任何临时文件。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">第一个程序新建一个</span>
						<span lang="EN-US">HTML</span>
						<span style="FONT-FAMILY: 宋体">文件的</span>
						<span lang="EN-US">InputStream</span>
						<span style="FONT-FAMILY: 宋体">对象，然后此对象被传给</span>
						<span lang="EN-US">JTidy</span>
						<span style="FONT-FAMILY: 宋体">。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">JTidy</span>
						<span style="FONT-FAMILY: 宋体">有个方法叫</span>
						<span lang="EN-US">parseDOM()</span>
						<span style="FONT-FAMILY: 宋体">，可以用来生成输出的</span>
						<span lang="EN-US">XHTML</span>
						<span style="FONT-FAMILY: 宋体">文档的</span>
						<span lang="EN-US">Document</span>
						<span style="FONT-FAMILY: 宋体">对象。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>public static void main(String[] args) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>// </span>
						<span style="FONT-FAMILY: 宋体">打开文件</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>if (args.length != 2) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>System.out.println("Usage: Html2Pdf htmlFile styleSheet");</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>      </span>
								<span>  </span>System.exit(1);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>FileInputStream input = null;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>String htmlFileName = args[0];</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>try {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>input = new FileInputStream(htmlFileName);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>catch (java.io.FileNotFoundException e) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>System.out.println("File not found: " + htmlFileName);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>Tidy tidy = new Tidy();</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>Document xmlDoc = tidy.parseDOM(input, null);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">JTidy</span>
						<span style="FONT-FAMILY: 宋体">的</span>
						<span lang="EN-US">DOM</span>
						<span style="FONT-FAMILY: 宋体">实现并不支持</span>
						<span lang="EN-US">XML</span>
						<span style="FONT-FAMILY: 宋体">命名空间。因此，我们必需修改</span>
						<span lang="EN-US">Antenna House</span>
						<span style="FONT-FAMILY: 宋体">的样式表，让它使用默认的命名空间。比如，原来是：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>&lt;xsl:template match="html:h2"&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>      </span>&lt;fo:block xsl:use-attribute-sets="h2"&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span> </span>
								<span>       </span>&lt;xsl:call-template name="process-common-attributes-and-children"/&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>      </span>&lt;/fo:block&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>&lt;/xsl:template&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">被修改后是：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>&lt;xsl:template match="h2"&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>      </span>&lt;fo:block xsl:use-attribute-sets="h2"&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>&lt;xsl:call-template name="process-common-attributes-and-children"/&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>      </span>&lt;/fo:block&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>&lt;/xsl:template&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">这个改动必需被应用到</span>
						<span lang="EN-US">xhtml<?XML:NAMESPACE PREFIX = ST1 /?><st1:chmetcnv tcsc="0" numbertype="1" negative="False" hasspace="False" sourcevalue="2" unitname="F" w:st="on">2f</st1:chmetcnv>0.xsl</span>
						<span style="FONT-FAMILY: 宋体">中的所有模板，因为</span>
						<span lang="EN-US">JTidy</span>
						<span style="FONT-FAMILY: 宋体">生成的</span>
						<span lang="EN-US">Document</span>
						<span style="FONT-FAMILY: 宋体">对象以</span>
						<span lang="EN-US">&lt;html&gt;</span>
						<span style="FONT-FAMILY: 宋体">标签作为根，如：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">&lt;html xmlns=quot;http://www.w3.org/1999/xhtml"&gt;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">修改后的</span>
						<span lang="EN-US">xhtml2fo.xsl</span>
						<span style="FONT-FAMILY: 宋体">包含在这篇文章附带的源代码中。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">接着，</span>
						<span lang="EN-US">xml2FO()</span>
						<span style="FONT-FAMILY: 宋体">方法调用</span>
						<span lang="EN-US">Xalan</span>
						<span style="FONT-FAMILY: 宋体">，使样式表应用于</span>
						<span lang="EN-US">JTidy</span>
						<span style="FONT-FAMILY: 宋体">生成的</span>
						<span lang="EN-US">DOM</span>
						<span style="FONT-FAMILY: 宋体">对象：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>Document foDoc = xml2FO(xmlDoc, args[1]);<span>  </span></span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">方法</span>
						<span lang="EN-US">xml2FO()</span>
						<span style="FONT-FAMILY: 宋体">首先调用</span>
						<span lang="EN-US">getTransformer()</span>
						<span style="FONT-FAMILY: 宋体">来获得一个指定的样式表的</span>
						<span lang="EN-US">Transformer</span>
						<span style="FONT-FAMILY: 宋体">对象。然后，代表着转换结果的那个</span>
						<span lang="EN-US">Document</span>
						<span style="FONT-FAMILY: 宋体">被返回：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>private static Document xml2FO(Document xml, String styleSheet) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>DOMSource xmlDomSource = new DOMSource(xml);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>          </span>DOMResult domResult = new DOMResult();</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>Transformer transformer = getTransformer(styleSheet);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>if (transformer == null) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>System.out.println("Error creating transformer for " + styleSheet);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>System.exit(1);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>try {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>transformer.transform(xmlDomSource, domResult);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>catch (javax.xml.transform.TransformerException e) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>return null;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>return (Document) domResult.getNode();</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">接着，</span>
						<span lang="EN-US">main</span>
						<span style="FONT-FAMILY: 宋体">方法用与</span>
						<span lang="EN-US">HTML</span>
						<span style="FONT-FAMILY: 宋体">输入文件相同的前缀来打开一个</span>
						<span lang="EN-US">FileOutputStream</span>
						<span style="FONT-FAMILY: 宋体">。然后调用</span>
						<span lang="EN-US">fo2PDF()</span>
						<span style="FONT-FAMILY: 宋体">方法所获得的结果被写入</span>
						<span lang="EN-US">OutputStream</span>
						<span style="FONT-FAMILY: 宋体">：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>String pdfFileName = htmlFileName.substring(0, htmlFileName.indexOf(".")) + ".pdf";</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>try {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>OutputStream pdf = new FileOutputStream(new File(pdfFileName));</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>pdf.write(fo2PDF(foDoc));</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>catch (java.io.FileNotFoundException e) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>System.out.println("Error creating PDF: " + pdfFileName);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>catch (java.io.IOException e) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>System.out.println("Error writing PDF: " + pdfFileName);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">方法</span>
						<span lang="EN-US">fo2PDF()</span>
						<span style="FONT-FAMILY: 宋体">会使用在转换中产生的</span>
						<span lang="EN-US">XSL-FO Document</span>
						<span style="FONT-FAMILY: 宋体">和一个</span>
						<span lang="EN-US">ByteArrayOutputStream</span>
						<span style="FONT-FAMILY: 宋体">来生成一个</span>
						<span lang="EN-US">FOP driver</span>
						<span style="FONT-FAMILY: 宋体">对象。通过调用</span>
						<span lang="EN-US">Driver.run</span>
						<span style="FONT-FAMILY: 宋体">可以生成</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">文件。结果被作为一个</span>
						<span lang="EN-US">byte array</span>
						<span style="FONT-FAMILY: 宋体">返回：</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>private static byte[] fo2PDF(Document foDocument) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>DocumentInputSource fopInputSource = new DocumentInputSource(</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>                                                         </span>foDocument);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>try {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>ByteArrayOutputStream out = new ByteArrayOutputStream();</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>Logger log = new ConsoleLogger(ConsoleLogger.LEVEL_WARN);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>Driver driver = new Driver(fopInputSource, out);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>driver.setLogger(log);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>     </span>
								<span>       </span>driver.setRenderer(Driver.RENDER_PDF);</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>driver.run();</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>return out.toByteArray();</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>} catch (Exception ex) {</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>            </span>return null;</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>        </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<span>    </span>}</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">Html2Pdf.java</span>
						<span style="FONT-FAMILY: 宋体">的源代码可以在这篇文章的附带代码中找到。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">使用</span>
						<span lang="EN-US">DOM API</span>
						<span style="FONT-FAMILY: 宋体">来完成这整个过程，速度要比使用命令行界面快得多，因为它不需要往磁盘中写入任何中间文件。这种方法可以集成到服务器里，来处理并发的</span>
						<span lang="EN-US">HTML-PDF</span>
						<span style="FONT-FAMILY: 宋体">转换请求。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">以前我曾以这里展示的这个程序为基础把生成</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">的功能集成到一个</span>
						<span lang="EN-US">WEB</span>
						<span style="FONT-FAMILY: 宋体">应用。而生成</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">的过程是动态的，因此不需要考虑</span>
						<span lang="EN-US">WEB</span>
						<span style="FONT-FAMILY: 宋体">页面和相应</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">同步的问题，因为生成的</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">文件并不是存放在服务器上。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<b>
								<span style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">结论</span>
						</b>
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt">
										<o:p>
										</o:p>
								</span>
						</b>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">综述，在本文里我描述了怎样利用开源组件来实现</span>
						<span lang="EN-US">HTML</span>
						<span style="FONT-FAMILY: 宋体">到</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">的转换。虽然这种实现方法在价格和源码方面很有吸引力，但同时也有一定的折衷。一些商业组件可以提供更完整的标准实现。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">比如说，</span>
						<span lang="EN-US">FOP</span>
						<span style="FONT-FAMILY: 宋体">目前的版本是</span>
						<span lang="EN-US">.91</span>
						<span style="FONT-FAMILY: 宋体">，不完全支持</span>
						<span lang="EN-US">XSL-FO</span>
						<span style="FONT-FAMILY: 宋体">标准。尽管如此，相对其它的格式而言，对</span>
						<span lang="EN-US">PDF</span>
						<span style="FONT-FAMILY: 宋体">提供了更多的支持。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span style="FONT-FAMILY: 宋体">在开始一个文档转换的项目之前，你必需考虑对文档格式的需求，并把它们与已有组件所实现的功能做个对比。这将有助于做出正确的决定。</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<b>
								<span style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">资源</span>
						</b>
						<b>
								<span lang="EN-US" style="FONT-SIZE: 14pt">
										<o:p>
										</o:p>
								</span>
						</b>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">
								<o:p> </o:p>
						</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># </span>
						<span style="FONT-FAMILY: 宋体">下载本文中的源码</span>
						<span lang="EN-US">:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.javaworld.com/javaworld/jw-04-2006/html/jw-0410-html.zip</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># Adobe's Document Server </span>
						<span style="FONT-FAMILY: 宋体">产品</span>
						<span lang="EN-US">:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.adobe.com/products/server/documentserver/main.html</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># Antenna House (</span>
						<span style="FONT-FAMILY: 宋体">出售商业的格式化程序</span>
						<span lang="EN-US">):</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.antennahouse.com</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># xhtml2fo.xsl </span>
						<span style="FONT-FAMILY: 宋体">把</span>
						<span lang="EN-US">XHTML </span>
						<span style="FONT-FAMILY: 宋体">转化为</span>
						<span lang="EN-US">XSL-FO </span>
						<span style="FONT-FAMILY: 宋体">的样式表</span>
						<span lang="EN-US">:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.antennahouse.com/XSLsample/XSLsample.htm</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># Apache FOP formatter </span>
						<span style="FONT-FAMILY: 宋体">把</span>
						<span lang="EN-US">XSL-FO </span>
						<span style="FONT-FAMILY: 宋体">翻译为</span>
						<span lang="EN-US">PDF:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://xmlgraphics.apache.org/fop</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># FOP </span>
						<span style="FONT-FAMILY: 宋体">对</span>
						<span lang="EN-US">XSL-FO </span>
						<span style="FONT-FAMILY: 宋体">标准的兼容性</span>
						<span lang="EN-US">:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://xmlgraphics.apache.org/fop/compliance.html</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># JTidy</span>
						<span style="FONT-FAMILY: 宋体">，把</span>
						<span lang="EN-US">HTML </span>
						<span style="FONT-FAMILY: 宋体">转化为</span>
						<span lang="EN-US">XHTML:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://sourceforge.net/projects/jtidy/</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># Xalan:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://xalan.apache.org/</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># XSL-FO, Dave Pawson (O'Reilly Media, 2002</span>
						<span style="FONT-FAMILY: 宋体">年</span>
						<span lang="EN-US">8</span>
						<span style="FONT-FAMILY: 宋体">月</span>
						<span lang="EN-US">; ISBN: 0596003552):</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.amazon.com/exec/obidos/ASIN/0596003552/javaworld</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># XSLT 2.0 Programmer's Reference, Michael Kay (Wrox, 2004</span>
						<span style="FONT-FAMILY: 宋体">年</span>
						<span lang="EN-US">8</span>
						<span style="FONT-FAMILY: 宋体">月</span>
						<span lang="EN-US">; ISBN: 0764569090):</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.amazon.com/exec/obidos/ASIN/0764569090/javaworld</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># </span>
						<span style="FONT-FAMILY: 宋体">浏览</span>
						<span lang="EN-US">JavaWorld</span>
						<span style="FONT-FAMILY: 宋体">的</span>
						<span lang="EN-US">Development Tools</span>
						<span style="FONT-FAMILY: 宋体">部分可以找到更多关于</span>
						<span lang="EN-US">Java</span>
						<span style="FONT-FAMILY: 宋体">开发工具的文章</span>
						<span lang="EN-US">:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.javaworld.com/channel_content/jw-tools-index.shtml</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US"># JavaWorld</span>
						<span style="FONT-FAMILY: 宋体">的</span>
						<span lang="EN-US">Java </span>
						<span style="FONT-FAMILY: 宋体">与</span>
						<span lang="EN-US">XML </span>
						<span style="FONT-FAMILY: 宋体">部分的文章索引</span>
						<span lang="EN-US">:</span>
				</p>
				<p class="MsoNormal">
						<span lang="EN-US">http://www.javaworld.com/channel_content/jw-xml-index.shtml </span>
				</p>
		</div>
<img src ="http://www.blogjava.net/leitianguang/aggbug/49935.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2006-06-02 15:00 <a href="http://www.blogjava.net/leitianguang/articles/49935.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转换HTML内容为PDF格式(1) [转]</title><link>http://www.blogjava.net/leitianguang/articles/49919.html</link><dc:creator>坚持学习，每天进步一些</dc:creator><author>坚持学习，每天进步一些</author><pubDate>Fri, 02 Jun 2006 05:02:00 GMT</pubDate><guid>http://www.blogjava.net/leitianguang/articles/49919.html</guid><wfw:comment>http://www.blogjava.net/leitianguang/comments/49919.html</wfw:comment><comments>http://www.blogjava.net/leitianguang/articles/49919.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leitianguang/comments/commentRss/49919.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leitianguang/services/trackbacks/49919.html</trackback:ping><description><![CDATA[
		<div class="postbody">作者：Nick Afshartous<br /><p class="MsoNormal"><span lang="EN-US"><?xml:namespace prefix = o /?><o:p>英文原文：<a href="http://www.javaworld.com/javaworld/jw-04-2006/jw-0410-html.html">http://www.javaworld.com/javaworld/jw-04-2006/jw-0410-html.html</a></o:p></span></p><p class="MsoNormal"><span lang="EN-US"><o:p>转自  <a href="http://shaofan.blogjava.net">http://shaofan.blogjava.net</a><br /></o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">把网页内容以</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">的格式呈献有利于内容的传播。在一些应用中，提供格式便于打印的文档是一个必需的功能，比如员工利益表等。事实上，法律规定</span><span lang="EN-US">Summmary Plan Descriptions(SPDs)</span><span style="FONT-FAMILY: 宋体">必须能够打印，即使它们是在线提供的也是如此。然而只打印网页本身是不够的，因为打印格式必包含表格内容和页码。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">为了提供这样的功能，开发人员可以把</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">内容转换为</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">格式。在此即做介绍。这里介绍的这种方法只使用开源组件。一些商业产品也支持动态的文档生成，比如说</span><span lang="EN-US">Adobe</span><span style="FONT-FAMILY: 宋体">，它有</span><span lang="EN-US">Document Server</span><span style="FONT-FAMILY: 宋体">产品线。但是，使用商业产品的开销是相当可观的。使用开源方案可以缓解开销的问题，并增加了组件源码的透明度。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">转换过程包含以下三步：</span></p><p class="MsoNormal"><span lang="EN-US">1.</span><span style="FONT-FAMILY: 宋体">把</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">转换为</span><span lang="EN-US">XHTML;</span></p><p class="MsoNormal"><span lang="EN-US">2.</span><span style="FONT-FAMILY: 宋体">把</span><span lang="EN-US">XHTML</span><span style="FONT-FAMILY: 宋体">转换为</span><span lang="EN-US">XSL-FO(Extensible Stylesheet Language Formatting Objects</span><span style="FONT-FAMILY: 宋体">扩展样式表语言格式化对象</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">。这里使用</span><span lang="EN-US">XSL</span><span style="FONT-FAMILY: 宋体">样式表和</span><span lang="EN-US">XSLT</span><span style="FONT-FAMILY: 宋体">转换器</span><span lang="EN-US">;</span></p><p class="MsoNormal"><span lang="EN-US">3.</span><span style="FONT-FAMILY: 宋体">把</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">文档传递给格式化程序来生成目标</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">文档。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">本文先介绍怎样用命令行界面来做这种转换，然后介绍怎样在</span><span lang="EN-US">JAVA</span><span style="FONT-FAMILY: 宋体">中使用</span><span lang="EN-US">DOM</span><span style="FONT-FAMILY: 宋体">接口来做同样的工作。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><b><span style="FONT-FAMILY: 宋体">组件版本：</span><span lang="EN-US"><o:p></o:p></span></b></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">本文中的代码在以下版本中进行了测试：</span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">组件</span><span lang="EN-US"><span>     </span></span><span style="FONT-FAMILY: 宋体">版本</span></p><p class="MsoNormal"><span lang="EN-US">JDK <span>    </span>1.5_06</span></p><p class="MsoNormal"><span lang="EN-US">JTidy <span>   </span>r7-dev</span></p><p class="MsoNormal"><span lang="EN-US">Xalan-J <span> </span>2.7</span></p><p class="MsoNormal"><span lang="EN-US">FOP <span>    </span><?xml:namespace prefix = st1 /?><st1:chsdate w:st="on" isrocdate="False" islunardate="False" day="30" month="12" year="1899">0.20.5</st1:chsdate></span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><b><span style="FONT-SIZE: 14pt; FONT-FAMILY: 宋体">使用命令行界面</span></b><b><span lang="EN-US" style="FONT-SIZE: 14pt"><o:p></o:p></span></b></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在转换过程中的每一步都包含了从一个输入文件生成输出文件的过程。这个过程可以用下图来表示：</span></p><span lang="EN-US"><o:p><p class="MsoNormal"><br /></p><p class="MsoNormal" align="center"><img src="http://img406.photo.163.com/rainy14f/46864571/1331680042.jpg" /></p><p class="MsoNormal"><br /> </p></o:p></span><p class="MsoNormal" style="TEXT-ALIGN: center" align="center"><span lang="EN-US"></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">使用这三个工具的命令行界面开始我们的工作是个好方法，尽管这种方法并不适合产品级的系统，因为它需要往磁盘中写入临时的中间文件。这种额外的</span><span lang="EN-US">I/O</span><span style="FONT-FAMILY: 宋体">会导致性能的降低。稍后，在我们用</span><span lang="EN-US">JAVA</span><span style="FONT-FAMILY: 宋体">来调用这三个工具时，这个问题就会得到解决。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><b><span style="FONT-FAMILY: 宋体">第一步：转换</span><span lang="EN-US">HTML</span></b><b><span style="FONT-FAMILY: 宋体">为</span><span lang="EN-US">XHTML<o:p></o:p></span></b></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">第一步就是把</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">转换为一个新的</span><span lang="EN-US">XHTML</span><span style="FONT-FAMILY: 宋体">文件。当然，如果文件本来已经就是</span><span lang="EN-US">XHTML</span><span style="FONT-FAMILY: 宋体">，那就不需要这一步了。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">我用</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">来完成这个转换。</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">是</span><span lang="EN-US">Tidy HTML</span><span style="FONT-FAMILY: 宋体">解析器的</span><span lang="EN-US">JAVA</span><span style="FONT-FAMILY: 宋体">版本。在转换的过程中，</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">会自动添加缺少的标签来创建格式良好</span><span lang="EN-US">(well-formed)</span><span style="FONT-FAMILY: 宋体">的</span><span lang="EN-US">XML</span><span style="FONT-FAMILY: 宋体">文档。我用的是在</span><span lang="EN-US">SourceForge</span><span style="FONT-FAMILY: 宋体">上的最新版本</span><span lang="EN-US">r7-dev</span><span style="FONT-FAMILY: 宋体">。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">可以用以下的脚本来运行</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">：</span></p><p class="MsoNormal"><span lang="EN-US">#/bin/sh</span></p><p class="MsoNormal"><span lang="EN-US">java -classpath lib/Tidy.jar org.w<st1:chmetcnv w:st="on" unitname="C" sourcevalue="3" hasspace="False" negative="False" numbertype="1" tcsc="0">3c</st1:chmetcnv>.tidy.Tidy -asxml $1 &gt;$2</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">此脚本设置了</span><span lang="EN-US">CLASSPATH</span><span style="FONT-FAMILY: 宋体">并调用了</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">。运行时，要输入的文件是以命令行参数的形式传给</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">。默认情况下，生成的</span><span lang="EN-US">XHTML</span><span style="FONT-FAMILY: 宋体">将被输出到标准输出设备。</span><span lang="EN-US">-modify</span><span style="FONT-FAMILY: 宋体">开关可以用来覆写输入文件。</span><span lang="EN-US">-asxml</span><span style="FONT-FAMILY: 宋体">开关把</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">的输出重定向到格式良好的</span><span lang="EN-US">XML</span><span style="FONT-FAMILY: 宋体">。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">调用时像这样：</span></p><p class="MsoNormal"><span lang="EN-US">tidy.sh hello.html hello.xml</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">hello.html(</span><span style="FONT-FAMILY: 宋体">输入</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US">hello.xml(</span><span style="FONT-FAMILY: 宋体">输出</span><span lang="EN-US">)</span><span style="FONT-FAMILY: 宋体">的内容如下：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">&lt;html&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;head&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>  </span>&lt;title&gt;Hello World</span></p><p class="MsoNormal"><span lang="EN-US">&lt;/head&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;body&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>   </span>&lt;p&gt; Hello World!</span></p><p class="MsoNormal"><span lang="EN-US">&lt;/body&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;/html&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">&lt;!DOCTYPE html PUBLIC quot;-//W<st1:chmetcnv w:st="on" unitname="C" sourcevalue="3" hasspace="False" negative="False" numbertype="1" tcsc="0">3C</st1:chmetcnv>//DTD XHTML 1.0 Strict//EN"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;html xmlns=quot;http://www.w3.org/1999/xhtml"&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;head&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;meta name=quot;generator" content="HTML Tidy, see www.w3.org" /&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;title&gt;Hello World&lt;/title&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;/head&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;body&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;p&gt;Hello World!&lt;/p&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;/body&gt;</span></p><p class="MsoNormal"><span lang="EN-US">&lt;/html&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">要注意的是，在</span><span lang="EN-US">XML</span><span style="FONT-FAMILY: 宋体">文件中的那个</span><span lang="EN-US">&lt;/p&gt;</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US">&lt;/title&gt;</span><span style="FONT-FAMILY: 宋体">是</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">自动添加的</span><span lang="EN-US">[</span><span style="FONT-FAMILY: 宋体">译注</span><span lang="EN-US">1]</span><span style="FONT-FAMILY: 宋体">。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><b><span style="FONT-FAMILY: 宋体">第二步：转换</span><span lang="EN-US">XHTML</span></b><b><span style="FONT-FAMILY: 宋体">为</span><span lang="EN-US">XSL-FO</span></b><span lang="EN-US">[</span><span style="FONT-FAMILY: 宋体">译注</span><span lang="EN-US">2]<b><o:p></o:p></b></span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">下面，</span><span lang="EN-US">XHTML</span><span style="FONT-FAMILY: 宋体">将被转换为</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">，一种用来为</span><span lang="EN-US">XML</span><span style="FONT-FAMILY: 宋体">文档指定打印格式的语言。我通过用</span><span lang="EN-US">XSLT</span><span style="FONT-FAMILY: 宋体">转换器</span><span lang="EN-US">(Apache Xalan)</span><span style="FONT-FAMILY: 宋体">处理</span><span lang="EN-US">XSL</span><span style="FONT-FAMILY: 宋体">样式表来完成这个转换。我使用的样式表是由</span><span lang="EN-US">Antenna House</span><span style="FONT-FAMILY: 宋体">提供的</span><span lang="EN-US">xhtml2fo.xsl</span><span style="FONT-FAMILY: 宋体">。</span><span lang="EN-US">Antenna House</span><span style="FONT-FAMILY: 宋体">是一个出售</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">上商用格式程序的公司。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">xhtml2fo.xsl</span><span style="FONT-FAMILY: 宋体">样式表指定了如何把每个</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">标签翻译成相应的</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">格式化命令序列。举例来说，</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">中的</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">标签在翻译中被定义为：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;xsl:template match="html:h2"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:block xsl:use-attribute-sets="h2"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:call-template name="process-common-attributes-and-children"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;/fo:block&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;/xsl:template&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在处理的过程中，每次遇到</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">标签，以上</span><span lang="EN-US">XSLT</span><span style="FONT-FAMILY: 宋体">模板都会被调用。</span><span lang="EN-US">html:</span><span style="FONT-FAMILY: 宋体">前缀表明</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">标签是</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">的命名空间</span><span lang="EN-US">(namespace)</span><span style="FONT-FAMILY: 宋体">。样式表的命名空间在顶层</span><span lang="EN-US">xsl:stylesheet</span><span style="FONT-FAMILY: 宋体">指示符的属性中被指定。在</span><span lang="EN-US">xhtml2fo.xsl</span><span style="FONT-FAMILY: 宋体">的最顶层，我们可以看到它指定了三个命名空间，分别对应于</span><span lang="EN-US">XSL,XSL-FO</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">语言。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;xsl:stylesheet version="1.0"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                    </span>xmlns:xsl="http://www.w3.org/1999/XSL/Transform"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span><span>                </span>xmlns:fo="http://www.w3.org/1999/XSL/Format"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                    </span>xmlns:html="http://www.w3.org/1999/xhtml"&gt;...</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">模板中的第二行</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:block xsl:use-attribute-sets="h2"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">致使</span><span lang="EN-US">fo:block</span><span style="FONT-FAMILY: 宋体">标签被输出，并且</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">的属性被生成为</span><span lang="EN-US">fo:block</span><span style="FONT-FAMILY: 宋体">标签的属性和值。每个</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">块</span><span lang="EN-US">(block)</span><span style="FONT-FAMILY: 宋体">都是一段文字，它们的格式基于块的属性的值。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">的属性在样式表中被定义为：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;xsl:attribute-set name="h2"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="start-indent"&gt;<st1:chmetcnv w:st="on" unitname="mm" sourcevalue="10" hasspace="False" negative="False" numbertype="1" tcsc="0">10mm</st1:chmetcnv></span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="end-indent"&gt;<st1:chmetcnv w:st="on" unitname="mm" sourcevalue="10" hasspace="False" negative="False" numbertype="1" tcsc="0">10mm</st1:chmetcnv></span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="space-before"&gt;1em</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="space-after"&gt;0.5em</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="font-size"&gt;x-large</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="font-weight"&gt;bold</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;xsl:attribute name="color"&gt;black</span></p><p class="MsoNormal"><span lang="EN-US"><span>   </span>&lt;/xsl:attribute-set&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">start-indent</span><span style="FONT-FAMILY: 宋体">及其后的属性用来指定</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">块的格式化后的外观。当你想改变</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">文档中用同样</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">标签的文字块的外观时，使用属性集可以使这种改变更加容易。只要改动属性的设置，那么输出的文件中所有使用这些属性的地方都会被改动。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">下一个指示符调用一个名为</span><span lang="EN-US">"process-common-attributes-and-children"</span><span style="FONT-FAMILY: 宋体">的模板：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;xsl:call-template name="process-common-attributes-and-children"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">这个模板在样式表中被指定。它的作用是检查一些普通的</span><span lang="EN-US">HTML</span><span style="FONT-FAMILY: 宋体">属性</span><span lang="EN-US">(</span><span style="FONT-FAMILY: 宋体">如</span><span lang="EN-US">lang,id,align,valign,style)</span><span style="FONT-FAMILY: 宋体">并生成相应的</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">指示符。要触发对嵌在顶层</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">标签中的任意标签的翻译，</span><span lang="EN-US">process-common-attributes-and-children</span><span style="FONT-FAMILY: 宋体">会调用：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;xsl:apply-templates/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">因此，如果输入是</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;h2&gt; Hello &lt;em&gt; there &lt;/em&gt; &lt;/h2&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">那么在</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">的模板中的</span><span lang="EN-US">&lt;xsl:apply-templates/&gt;</span><span style="FONT-FAMILY: 宋体">就会触发用来翻译</span><span lang="EN-US">&lt;em&gt;</span><span style="FONT-FAMILY: 宋体">标签的模板。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">翻译</span><span lang="EN-US">H2</span><span style="FONT-FAMILY: 宋体">标签的输出是：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:block start-indent="<st1:chmetcnv w:st="on" unitname="mm" sourcevalue="10" hasspace="False" negative="False" numbertype="1" tcsc="0">10mm</st1:chmetcnv>" ...</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>original H2 tag content</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;/fo:block&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">我们调用</span><span lang="EN-US">Xalan</span><span style="FONT-FAMILY: 宋体">来应用</span><span lang="EN-US">xhtml2fo.xsl</span><span style="FONT-FAMILY: 宋体">。在调用</span><span lang="EN-US">Xalan</span><span style="FONT-FAMILY: 宋体">之前，用</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体">脚本</span><span lang="EN-US">xalan.sh</span><span style="FONT-FAMILY: 宋体">来设置它需要用到的</span><span lang="EN-US">CLASSPATH</span><span style="FONT-FAMILY: 宋体">变量。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">#/bin/sh</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">export CLASSPATH='.;./lib/xalan.jar;./lib/xercesImpl.jar;./lib/xml-apis.jar;lib/serializer.jar'</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">java -classpath $CLASSPATH org.apache.xalan.xslt.Process -IN $1 -XSL xhtml2fo.xsl -OUT $2 -tt</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">因为</span><span lang="EN-US">Xalan</span><span style="FONT-FAMILY: 宋体">需要一个</span><span lang="EN-US">XML</span><span style="FONT-FAMILY: 宋体">解析器，所以这里还需要</span><span lang="EN-US">Apache Xerces</span><span style="FONT-FAMILY: 宋体">和</span><span lang="EN-US">xml-api JARs</span><span style="FONT-FAMILY: 宋体">。所有的</span><span lang="EN-US">jar</span><span style="FONT-FAMILY: 宋体">文件都可以在</span><span lang="EN-US">Xalan</span><span style="FONT-FAMILY: 宋体">的发布包中找到。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">要通过对</span><span lang="EN-US">XHTML</span><span style="FONT-FAMILY: 宋体">应用样式表来新建一个</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">文件，可以调用脚本：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>xalan.sh<span>  </span>hello.xml hello.fo</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">我喜欢用</span><span lang="EN-US">Xalan</span><span style="FONT-FAMILY: 宋体">的跟踪开关</span><span lang="EN-US">(-tt)</span><span style="FONT-FAMILY: 宋体">来显示应用的模板。</span><span lang="EN-US">hello.fo</span><span style="FONT-FAMILY: 宋体">文件如下：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">&lt;fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>xmlns:html="http://www.w3.org/1999/xhtml"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>writing-mode="lr-tb"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>hyphenate="false"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>text-align="start"</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>role="html:html"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>  </span>&lt;fo:layout-master-set&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:simple-page-master page-width="auto" page-height="auto"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                           </span>master-name="all-pages"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:region-body column-gap="<st1:chmetcnv w:st="on" unitname="pt" sourcevalue="12" hasspace="False" negative="False" numbertype="1" tcsc="0">12pt</st1:chmetcnv>" column-count="1" margin-left="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                      </span>margin-bottom="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>" margin-right="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>" margin-top="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:region-before display-align="before" extent="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                        </span>region-name="page-header"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:region-after display-align="after" extent="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                      </span>region-name="page-footer"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:region-start extent="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:region-end extent="<st1:chmetcnv w:st="on" unitname="in" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0">1in</st1:chmetcnv>"/&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;/fo:simple-page-master&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>  </span>&lt;/fo:layout-master-set&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>  </span>&lt;fo:page-sequence master-reference="all-pages"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:title&gt;Hello World</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:static-content flow-name="page-header"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:block font-size="small" text-align="center" space-before="<st1:chmetcnv w:st="on" unitname="in" sourcevalue=".5" hasspace="False" negative="False" numbertype="1" tcsc="0">0.5in</st1:chmetcnv>"</span></p><p class="MsoNormal"><span lang="EN-US"><span>                </span>space-before.conditionality=;"retain"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>Hello World</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;/fo:block&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;/fo:static-content&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:static-content flow-name="page-footer"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:block font-size="small" text-align="center" space-after="<st1:chmetcnv w:st="on" unitname="in" sourcevalue=".5" hasspace="False" negative="False" numbertype="1" tcsc="0">0.5in</st1:chmetcnv>"</span></p><p class="MsoNormal"><span lang="EN-US"><span> </span><span>               </span>space-after.conditionality=quot;retain"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>- &lt;fo:page-number/&gt; -</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;/fo:block&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;/fo:static-content&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;fo:flow flow-name="xsl-region-body"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;fo:block role="html:body"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;fo:block space-before="1em" space-after="1em" role="html:p"&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>          </span>Hello World!</span></p><p class="MsoNormal"><span lang="EN-US"><span>        </span>&lt;/fo:block&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>      </span>&lt;/fo:block&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>&lt;/fo:flow&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>  </span>&lt;/fo:page-sequence&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">&lt;/fo:root&gt;</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span></span></span> </p><p class="MsoNormal"><b><span style="FONT-FAMILY: 宋体">第三步：</span><span lang="EN-US">XSL-FO</span></b><b><span style="FONT-FAMILY: 宋体">到</span><span lang="EN-US">PDF<o:p></o:p></span></b></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">第三步，也就是最后一步，就是把</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">文档传递给格式化程序来生成</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">。我用的是</span><span lang="EN-US">Apache FOP(Formatting Objects Processor)</span><span style="FONT-FAMILY: 宋体">。</span><span lang="EN-US">FOP</span><span style="FONT-FAMILY: 宋体">部分实现了</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">标准，并对</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">的输出格式提供了最好的支持。而对</span><span lang="EN-US">Postscript</span><span style="FONT-FAMILY: 宋体">还处于初级阶段，对微软的</span><span lang="EN-US">RTF</span><span style="FONT-FAMILY: 宋体">的支持还在计划中。</span><span lang="EN-US">FOP</span><span style="FONT-FAMILY: 宋体">发布版包含</span><span lang="EN-US">shell</span><span style="FONT-FAMILY: 宋体">脚本</span><span lang="EN-US">fop.sh/fop.bat</span><span style="FONT-FAMILY: 宋体">，它们需要传入</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">文件作为输入参数来生成目标</span><span lang="EN-US">PDF</span><span style="FONT-FAMILY: 宋体">文件。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">在</span><span lang="EN-US">Unix</span><span style="FONT-FAMILY: 宋体">下可以这样运行：</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US"><span>    </span>fop.sh hello.fo hello.pdf</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">唯一所需的前提条件就是把设置为这个脚本使用到的</span><span lang="EN-US">FOP</span><span style="FONT-FAMILY: 宋体">目录设置环境变量。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">文件</span><span lang="EN-US">hello.pdf</span><span style="FONT-FAMILY: 宋体">即为</span><span lang="EN-US">FOP</span><span style="FONT-FAMILY: 宋体">的输出，你在本文的源代码中可以找到。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span style="FONT-FAMILY: 宋体">因为</span><span lang="EN-US">FOP</span><span style="FONT-FAMILY: 宋体">目前并未完全实现</span><span lang="EN-US">XSL-FO</span><span style="FONT-FAMILY: 宋体">标准，所以有一定的局限性。具体它实现了标准的哪些子集，可以在</span><span lang="EN-US">FOP</span><span style="FONT-FAMILY: 宋体">的网站上的</span><span lang="EN-US">Compliance</span><span style="FONT-FAMILY: 宋体">部分找到详细说明。</span></p><p class="MsoNormal">---------------------------------------------------------------------------<br /><br /><br /><span style="FONT-FAMILY: 宋体"></span></p><p class="MsoNormal"></p><p class="MsoNormal"><span lang="EN-US">[</span><span style="FONT-FAMILY: 宋体">译注</span><span lang="EN-US">1] </span><span style="FONT-FAMILY: 宋体">此处原文是“在</span><span lang="EN-US">XML</span><span style="FONT-FAMILY: 宋体">文件中的那个</span><span lang="EN-US">&lt;/p&gt;</span><span style="FONT-FAMILY: 宋体">是</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">自动添加的”。我使用</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">转换的结果是</span><span lang="EN-US">&lt;/title&gt;</span><span style="FONT-FAMILY: 宋体">也被添加，而且这符合</span><span lang="EN-US">JTidy</span><span style="FONT-FAMILY: 宋体">的逻辑，因此这里稍作了修改。</span></p><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal"><span lang="EN-US">[</span><span style="FONT-FAMILY: 宋体">译注</span><span lang="EN-US">2] </span><span style="FONT-FAMILY: 宋体">这一部分我在试着做的时候遇到很多问题。首先，有些地方作者描述的并不清楚，特别是对于模板的解释那一部分。其次，在用</span><span lang="EN-US">Xalan</span><span style="FONT-FAMILY: 宋体">做转换时遇到了</span><span lang="EN-US">Connection time out</span><span style="FONT-FAMILY: 宋体">的异常。这可能是由于</span><span lang="EN-US">xml</span><span style="FONT-FAMILY: 宋体">文件中的</span><span lang="EN-US">dtd(xhtml1-strict.dtd)</span><span style="FONT-FAMILY: 宋体">无法连接造成的。把该</span><span lang="EN-US">dtd</span><span style="FONT-FAMILY: 宋体">下载到本地后，该异常即可消除。然后是无法找</span><span lang="EN-US">ent</span><span style="FONT-FAMILY: 宋体">文件。所需要的这些</span><span lang="EN-US">ent</span><span style="FONT-FAMILY: 宋体">都可以在</span><span lang="EN-US">xmlbuddy</span><span style="FONT-FAMILY: 宋体">的安装包里找到，拷过来就可以了。我不知道作者是不是没有遇到过这些问题，也可能我这只是特例。</span></p></div>
<img src ="http://www.blogjava.net/leitianguang/aggbug/49919.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leitianguang/" target="_blank">坚持学习，每天进步一些</a> 2006-06-02 13:02 <a href="http://www.blogjava.net/leitianguang/articles/49919.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>