﻿<?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-Tin's Blog-随笔分类-Other Project</title><link>http://www.blogjava.net/iamtin/category/7428.html</link><description>You are coming a long way, baby~Thinking, feeling, memory...</description><language>zh-cn</language><lastBuildDate>Wed, 17 Oct 2007 04:18:23 GMT</lastBuildDate><pubDate>Wed, 17 Oct 2007 04:18:23 GMT</pubDate><ttl>60</ttl><item><title>两台Vista，共享ADSL的做法</title><link>http://www.blogjava.net/iamtin/archive/2007/01/26/vista_pppoe_internet_share_how_to.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Fri, 26 Jan 2007 06:37:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2007/01/26/vista_pppoe_internet_share_how_to.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/96150.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2007/01/26/vista_pppoe_internet_share_how_to.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/96150.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/96150.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.blogjava.net/iamtin/archive/2007/01/26/vista_pppoe_internet_share_how_to.html'>阅读全文</a><img src ="http://www.blogjava.net/iamtin/aggbug/96150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2007-01-26 14:37 <a href="http://www.blogjava.net/iamtin/archive/2007/01/26/vista_pppoe_internet_share_how_to.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>《OSGi实战》读后感</title><link>http://www.blogjava.net/iamtin/archive/2006/09/06/67982.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Wed, 06 Sep 2006 03:27:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/09/06/67982.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/67982.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/09/06/67982.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/67982.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/67982.html</trackback:ping><description><![CDATA[
		<p>看了下BlueDavy的OSGi实战这篇OpenDoc，很感谢BlueDavy同学！<br />例子举的是一个User Login的Case，例子很简单，让我们从中领略了OSGi的风情。这个Doc中的例子都是围绕Equinox展开的，它是Eclipse 3.1以后的核心实现，也就是说现在的Eclipse是个OSGi架构。<br />从架构上来说OSGi和SOA如出一辙，都强调面向服务，而OSGi似乎对热切换和契约管理比较着重，也就是说OSGi更现实，它强调的是一种实际的合约标准。产生的结果是差不多的，就是系统模块之间的高度解藕。<br />可以看OSGi的Core Framework，最内层是L0：运行环境（就是语言平台或者解释平台一类的环境），然后是OSGI的L1：模块，L2：生命周期管理，L3：服务注册。<br />我认为这种架构也基本上是一个SOA需要关注的几个问题。<br />L1是实现OSGi的基础，在Java下提供了类加载机制，使系统能够模块化。个人感觉类似原来Eclipse中的微内核。<br />L2是解决模块之间依赖关系的最基本工作单位，负责初始化、停止、更新等操作，这样模块能够活起来，同时在这些过程中可以手动维护依赖关系，也是模块协作的基础。<br />L3则是协作的合同签署场所，应该是L2的扩展，使模块之间能够按照契约工作。我觉得更形象地说就是路由器，模块间的动态依赖可以很好地通过它来解决，让OSGi可以动起来。<br />拥有了这几层，我想我们完全可以理解为一个SOA的实现，当然更细化。应该是一种新的组合应用的方式。<br />白嘴说肯定没有BlueDavy的文章好，大家还是去看看那篇文档。</p>
		<p>说说遗憾：<br />1、OSGi在B/S架构中还不好应用。虽然例子是B/S的，可是居然是Servlet模型，里面解释了目前Equinox项目也在扩展应用服务器支持和JSP支持等，可是起码目前还不成熟。<br />2、模块的粒度很成问题。目前OSGi的契约机制与java interface机制对比一下。OSGi不可能完全取代本地的interface式的解藕，当然人家也没这么说。只使我担心过渡设计后，过细的Bundle肯定会得不偿失，所以需要有人设计/计划这个粒度。这个可能与基于Web services的SOA架构面临类似的问题，需要好的架构师。<br />3、文档不友好么？说实话，很感谢BlueDavy和OSGi观察者那些大牛的贡献。但是感觉production的样例工程还是很难搞到（其实Eclipse plugins的例子满多哈，可惜没啥文档，需要硬着头皮看），对应的指导文档还没出现。BlueDavy提供的servlet实现我们不可能跟上，毕竟简单也是一种需求。（那谁说过度设计比设计不足更可怕，那个我不是唱反调，我希望我们都能找到那个sweet point，有个好的参照那最好不过了）。<br />4、由于思想先进，在某些人看来是阳春白雪。估计不少人还是埋头下里巴人。观望态度。</p>
		<p>结束，又是流水账，大家拍砖。</p>
<img src ="http://www.blogjava.net/iamtin/aggbug/67982.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-09-06 11:27 <a href="http://www.blogjava.net/iamtin/archive/2006/09/06/67982.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>看看Springside的DAO和Manager</title><link>http://www.blogjava.net/iamtin/archive/2006/09/05/67899.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Tue, 05 Sep 2006 13:52:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/09/05/67899.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/67899.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/09/05/67899.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/67899.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/67899.html</trackback:ping><description><![CDATA[
		<strong>内容太乱，如果懒得看请只看粗体部分就可以了</strong>
		<img height="19" src="http://www.blogjava.net/Emoticons/74_74.gif" width="19" border="0" />
		<br />springside的一个特点就是manager继承自DAO，其实这是个名字上的问题。<br />Java EE一直强调分层架构，在Web部分比较典型的就是前端MVC、中间Business、后面持久化。而Manager对应business，持久化由于实现替换的需求一般使用DAO模式。<br />先分析一下在轻量化的Java EE下面他们存在的意义：<br />1、有的人说过在Web项目中Manager和DAO是同意的，尤其是在透明ORM存在下，DAO由于往往是CRUD的实现场所，而Manager却往往是薄薄的一层门面，很多人就在质疑两者的合并问题。<strong>可是robbin曾经进行过一个精辟的分析，虽然两者做的看起来差不多，可是两者的事务属性却不一样，Manager应该有清晰的事务界限，而DAO不应关心于此。</strong>也就是说Manager可能会将几个DAO方法组合调用，然后封装在一个事物中。这样说明确了两者的一个重要区别，我们也能体会在使用声明事务的时候有一个分明的事务界限是很有意义的，否则就有可能把Manager中的一个事物拆分，这样实际上就错误了。<br />2、有些人质疑透明ORM存在的情况下DAO存在的意义，因为透明ORM基本已经隔离了不同数据库的方言区别。这个也很简单，Rod大叔分析过。<strong>透明ORM存在的情况下DAO起到了隔离透明ORM与EJB或者JDBC实现的作用</strong>，这几种实现实际上是应该考虑到的。<br />3、还有一个问题，就是DAO是否应该隐藏透明ORM的API。因为前面说到了DAO起到隔离实现的作用，似乎应该隐藏特定API。可是某大叔也说过，完全隔离不可能，修改底层实现而不修改上层API也不划算（应该说往往费力不讨好），其实就是Rod大叔的思想，我们宁可提供各种support或者template，但是不强求抽象出各种实现。所以<strong>DAO的实现即使依赖于部分Hibernate API也不是错</strong>。<br />上面纯属贫嘴，知道的朋友们不要嫌弃。<br />说说Springside的实现。<br />其实，<strong>实际上Springside使用的就是经典的GenericHibernateDAO+无Manager的实现</strong>。这么说在否定前面所说，不过其实这都是文字游戏：D<br />首先，对于Hibernate为主的实现下，DAO使用Generic是很方便的。Spring的hibernate template受累于向JDK1.4兼容，所以没有用generic，但是实际上DAO是generic的经典应用。在Hibernate网站上有过讨论。现在Springside使用的GenericHibernateDAO已经进化的非常先进了。<br /><strong>Springside实际上有Manager，我说没有其实是指它的Manager继承自DAO。</strong>看似乱伦，但实际上非常合理。<strong>前面说了Manager与DAO的很大区别在于事物范畴，使用继承后，两者之间就可以分离，可以通过Spring的AOP将事物属性配置在Manager上，也就解决了问题。这应该说也是template模式的标准应用。本来Manager就有很多方法可以通过模板实现，而DAO和Generic就很好地解决了他们之间的模板关系。<br /></strong>我们先看看具体的设计：<br />以CustomerManager为例，我们看看类签名：<br /><font color="#ff0000">CustomerManager extends BaseHibernateDao&lt;Customer&gt;<br />BaseHibernateDao&lt;T&gt; extends AbstractHibernateDao&lt;T&gt;<br />AbstractHibernateDao&lt;T&gt; extends HibernateDaoSupport</font><br /><strong>三层结构：<br /><font color="#0000ff">第一层</font>AbstractHibernateDao继承自大家都熟悉的Spring的HibernateDaoSupport，这一层的主要作用是扩展Generic，这样一方面减少了强行类型转换的啰嗦，一方面使DoaminClass的信息通过Generic继承透明声明。这一层还有一个作用，就是说不管你是否使用Generic，你的应用程序最好也在这里增加一层继承，作用是在需要的时候你可以在这里扩展DAO模版：D<br /><font color="#0000ff">第二层</font>是BaseHibernateDao。这个其实是springside很自豪的一个地方，可以理解，因为这里真的花了很多的代码，而且相当精妙。</strong>不卖官子，其实<strong>这里主要给DAO扩展了分页支持</strong>，这显然是异常重要的，大家google一下就知道分页在Web应用中的重要性了，<strong>基本上你看一个Java Web Framework都会看到它对自己分页特性的支持方式介绍，或者说分页的实现风格已经是Java Web Framework实现优劣的一个标准了。</strong>应该说，<strong>springsdie的分页实现来自javaeye上的一个经典的讨论</strong>，robbin等牛在里面仔细讨论了用DetachedCriteria实现分页查询，后面引出bug，然后解决，希望没看过的朋友都看看。（应用Hibernate3的DetachedCriteria实现分页查询|http://forum.javaeye.com/viewtopic.php?t=14657&amp;postdays=0&amp;postorder=asc&amp;start=0）<br /><strong>springside的实现是集大成者，考虑到了Criteria（不仅是DetachedCriteria）、HQL、collection.size()几种不同实现，也考虑到了使用Criteria的时候Order造成的问题</strong>（这个在我的Blog中给DetachedCriteria擦屁股那个里面讨论过）。<br /><strong><font color="#0000ff">第三层</font>就是具体的Manager，它是用Generic继承传递了DoaminModel的类信息。由于大部分CRUD已经在DAO里面实现了，所以Manager只需要实现一些需要特殊实现的method的就可以了，简单的应用中Manager里面经常是空空如也。<br /></strong><br /><strong>其中，BaseHibernateDao的实现相对复杂，主要因为里面包装了分页实现。大家可以具体看看CriteriaPage和HqlPage两个类，这是精妙所在。</strong>但是在这一层还有个<strong>CriteriaSetup是个比较奇怪的东西</strong>，一开始没太看明白是做什么用的。后来问了百衣，他说这是为了解决search问题提供的，从jsp传递过来的东西在Controller层可以通过util（<strong>这里springside很CoC，它把search_开头的东西自动作为“=”的查询条件传给Manager，但目前的缺陷在于只能默认处理“=”，其它方式需要扩展</strong>）处理查询条件传给Manager，但是这个东西设计得有点怪，白衣也对它不满意，说在Springside 2.0里面要重构掉，但还没有什么好的想法，大家又建议可以提给他。<br />我认为传递查询信息大概需要这样的设计：<br />1、在Controller里面不暴露hibernate API，但是能够顺利将参数传递到Manager。<br />2、Manager直接传递，或者将这些参数转换为Hibernate API后再传递，因为这正是manager需要负责的商业逻辑之一。<br />3、DAO里面最好不要做那么多转换，毕竟它是持久层。 <br />当然，目前符合这个要求，只是限定于Map是二元容器，不能存3元的查询条件（key、value、type）。所以可能下一步会补足。<br />分析到这里，springside的DAO的结构大概就是这样的。<br />感觉这和我们Team上个项目的结构很象（不好意思，没说有springside那么好），有一点区别。<br />由于Manager继承自DAO，我们让DAO多了很多方法，主要就是想提供方便。尤其是<br /><strong><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"><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> T loadById(Class</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> persistenceClass, Serializable id);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> T loadByProperty(Class</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> persistenceClass, String propertyName, Object value);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">listAll(Class</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> persistenceClass);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">listByProperty(Class</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> persistenceClass, String propertyName, Object value);<br /><img src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align="top" /></span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> List</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">listAllOrderBy(Class</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> persistenceClas, </span><span style="COLOR: #0000ff">boolean</span><span style="COLOR: #000000"> isAsc, String orderByPropertyName);</span></div>可是springside并没有提供这样的东西，有点遗憾。<br />这些东西经常用到，如果使用了会减少了很多时候遇到的Manager里面注入其他Domain的DAO，却只是为了load或者listAll的问题（同时用generic）：D</strong><br />今天有点别的事，先说到这里，好好想想，看有什么问题过两天在说说。<strong>这Blog太流水账，太空洞，大家见谅。</strong><img src ="http://www.blogjava.net/iamtin/aggbug/67899.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-09-05 21:52 <a href="http://www.blogjava.net/iamtin/archive/2006/09/05/67899.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Eclipse里面运行Springside的Test</title><link>http://www.blogjava.net/iamtin/archive/2006/08/31/66841.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Thu, 31 Aug 2006 05:02:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/08/31/66841.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/66841.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/08/31/66841.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/66841.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/66841.html</trackback:ping><description><![CDATA[Springside里面的Test现在已经比较丰富，而且徐x贡献了基于selenium rc的functional test，这些东西是很好的学习资料。尤其是functional test，让QA的任务可以在Java里面实现了，而且是基于浏览器的测试。<br />推荐看看rainmundox的<a id="viewpost1_TitleUrl" href="/raimundox/archive/2006/08/04/61860.html"><font color="#808080">Selenium Better Pratice</font></a><br /><br />但是首先却遇到了问题：<br />在Eclipse里面运行functional-test这个target的时候发现报错（test target叶出错的）：<br />Could not create task or type of type: junit.<br />我就想当然的把junit-3.8.1.jar拷贝到我的%ANT_HOME%/lib下面了，结果问题依旧。<br />然后google了下，发现是这样的：<br />“该信息表明 Ant 没有找到任务或任务所依靠的类。 Ant 试图加载 Junit JAR 文件。当在 IDE 外部使用 Ant 时，应该把 junit.jar 放在 %ANT_HOME%/lib 文件夹。使用 Eclipse 时该任务无法工作，因为它使用自身版本的 Ant 。所以 junit.jar 必须放在 Eclipse 的 Ant 文件夹中，即 %ECLIPSE_HOME%/plugins/org.apache.ant_1.6.2/lib （很显然，不同版本的 Eclipse 会有不同版本的 Ant ）。”<br />在Eclipse 3.2里面已经是ant_1.6.5了，拷贝过去问题还是没有解决。<br />然后走了不少弯路。<br />最后，发现其实是这样的。上面提示了Eclipse用的自己的ant，这个时候你拷贝junit-3.8.1.jar过去并不起作用，因为ant设置不会自动扫描那个目录的/lib。<br />解决方法目前看最好的就是在Eclipse的Window-&gt;Preferences-&gt;Ant-&gt;Runtime-&gt;Classpath里面Ant_Home你指定一下就可以了，可以是你自己的Ant或者Eclipse/plugins里面的ant，这没关系，然后它就会自动扫描相应/lib目录了（之前你应该已经把junit-3.8.1.jar拷贝过去了）。<br />然后就搞定了。注意，只有在Eclipse运行Ant才有可能遇上这个问题:D<br /><br />呵呵，问题搞定了，先review一下Test，看看有什么能解决的。然后我想先分析一下SpringSide的DAO、Manager这种结构，明后天。<img src ="http://www.blogjava.net/iamtin/aggbug/66841.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-08-31 13:02 <a href="http://www.blogjava.net/iamtin/archive/2006/08/31/66841.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从Domain开始看Springside</title><link>http://www.blogjava.net/iamtin/archive/2006/08/30/66637.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Wed, 30 Aug 2006 04:30:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/08/30/66637.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/66637.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/08/30/66637.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/66637.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/66637.html</trackback:ping><description><![CDATA[
		<p>SpringSide是一个fantasy的好项目，可惜驽钝，没能加入其中，有时会看看它的代码，吸取一些养分。<br /><a href="http://www.springside.org.cn/">http://www.springside.org.cn/</a><br /><br />今天先看看Springside的bookstore的domain设计，这不是springside的重点，先看看。<br />从hbm看起，在springside-bookstore/src/org.springside.bookstore.commons.domain.hbm下面放着这些hbm。<br />在Order.hbm.xml里面可以看到一个list映射。list映射可以按照顺序持久化one-to-many关系。使用了&lt;composite-element&gt;映射后OrderItem就没有单独的class声明了，完全以一种组件的形式被映射到Order里面。<br />有序的List映射是很方便的，这样就可以通过List的set(int, Object)来改变OrderItem的顺序，这个需求是经常被提起的。<br />Order.java里面可以看到在价格计算上使用了Rule，Rule是用String纪录的rule id，我记得springside团队试验性的使用了Drools，具体在进步研究后分析。<br />Order实现了AclDomainAware接口，可见是用ACL进行了访问控制。没有继承自统一的DomainObject基类，这个不知从何考虑，感觉Domain继承自统一基类在框架很多地方都可以得到便利。实现接口在这里应该作为一种签名标示，作为某些环节或者拦截器使用。SpringSide这里应该是用的是Acegi，可以看到这个是差沙同学实现的。<br />Order这部分就没有什么其它特别之处了，是比较典型的pojo，贫血模型:D。在这里没有看到全功能DomainModel的影子。此时修改Order里面的orderItems就需要手动替换，addProduct的功能都不在这里，的确有点不爽。<br />BTW：在Order.hbm.xml的配置里面可以看到上面有一行&lt;import class="org.springside.bookstore.commons.domain.OrderItem"/&gt;，不知道起什么作用，希望了解的朋友指点。<br />在Product.hbm.xml里面有一个继承映射：“每个类分层结构一张表（Table per class hierarchy）”的形式。<br />再进到Product.java里面，它实现了HistorizableEntity接口，而前者又继承自AuditableEntity。<br />从里面的注释上看HistorizableEntity作为Hibernate Event Listener的记号，对此接口的领域对象自动保存修改纪录，这个我找到代码在org.springside.core.commons.support.audit.HistoryEventListener里面。这个东西被配置到session上。从代码上看，这个东西用来记录这个商品的LifeCycle，不过代码还没有完成，不知道calvin同学会用什么方法得到user等信息（Hibernate Listener是单例，不能有状态信息）。这种方法在RoR里面有个_at和_on的后缀，可以自动完成修改时间等信息的持久化，不知道此处是否是要实现类似的功能。<br />Product里面有个@SearchableId、@SearchableProperty、@SearchableComponent的注释，这是compass的注释，这种暴露属性提供搜索的配置方式非常舒服，是对pojo进行搜索的好例子。compass对Lucene的包装是不错的，这里好像是hellboys同学写的，有时间深入看一下。<br />限制描述字段的功能放到了pojo里面，这个方法很不错，大家也都在用。<br />Product的toString方法使用的是ToStringBuilder.reflectionToString，这个不知大家是否常用，不过这个东西大家要主要。比如在Domain公用基类中就不要用，否则它会对所有lazy load的属性有毁灭性打击:D。Springside没有使用这种结构，当然没关系。<br />Book是Product的子类，继承是OO特性，这里显然考虑周到，Springside也就不是仅能卖书的应用了:D。equals、hashCode方法都出现了重复。不过，重构强调任何形式的重复都是邪恶的，RoR的Hansson坚信之，所以有了CoC概念。<br />不过这里产生一个问题，我实现的一些应用中发现对于Hibernate的继承，类型转换是个令人头疼的问题，相当不舒服，因为descrimitor对于你是不可见的，你很难在保留id的情况下强行转换一个子类到另一个子类。这点很不灵活，不知大家有什么好办法？<br />Custemer、Category是单纯的Pojo。Category没有实现层次，这点比较失望，感觉应该做一个树形结构的显示管理的demo。</p>
		<p>下面的部分，我会继续分析:D</p>
<img src ="http://www.blogjava.net/iamtin/aggbug/66637.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-08-30 12:30 <a href="http://www.blogjava.net/iamtin/archive/2006/08/30/66637.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>TSS关于企业级Java座谈的总结</title><link>http://www.blogjava.net/iamtin/archive/2006/07/10/57479.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Mon, 10 Jul 2006 06:09:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/07/10/57479.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/57479.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/07/10/57479.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/57479.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/57479.html</trackback:ping><description><![CDATA[
		<p>TSS座谈会上Cameron Purdy, Rod Johnson, Bruce Snyder, Bruce Tate, Floyd Marinescu和Ari Zilka作了一个“企业级Java的未来如何？”的座谈。<br />下面是infoQ上关于这个座谈的一个总结，不是原文，是摘要。<br />首先大家谈一谈关于企业级Java的未来的想法：<br />Bruce Tate：企业级Java状态良好，缺乏的是Java对低端应用开发的支持（在Web应用领域看，明显是在暗指Ruby on Rails）。<br />Ari Zilka：可伸缩性问题突显出来，将会倾向于让更多的机器分布式工作来代替花很多钱在一台巨强的机器。“我认为AOP将会改变应用程序服务器市场的面貌。”<br />Floyd Marinescu：Java本身正在变化，它不再是单纯的语言，它是JDK+JVM=bytecode=任何语言。Java将成为DSL和脚本语言的平台。Web开发框架将会是创新的领域。Rails就是证据。但是我们需要这种形式与Java的更优整合。Web2.0正在使web从一个发布平台向一个应用程序平台转变，它会改变我们所做的应用程序开发。<br />Bruce Snyder：同意Web2.0的观点。开发必须要更简单，API必须简化。说说这个东西到底有多酷，如果我们对元模型编码，将他们从开发中抽象出来，就像EJB vs. JAX-WS，而且你可以在编译时生成它们（听起来像MDD，模型驱动开发）。这种方式可能与SOA和Web2.0的想法相关联。<br />Cameron Purdy：同意关于Web2.0的观点，但实际上是我们不应该假设Java会是Web2.0应用的基础。<br />Rod Johnson：很兴奋的看到面向对象开发的复兴。EJB持久化API润许我们构造真正的领域模型，而不是贫血的。我们将会看到AspectJ在未来的几年中应用越发广泛。最难理解的是JVM而不是Java。最难预测的是Web曾将会发生什么，有大量相互竞争的实现。<br />Ted问了一个很难回答的问题：你认为EJB的机会的窗口已经关闭了么？将会永远的关闭，或者还有机会？<br />Bruce Tate：“我偷偷的告诉你，我认为EJB3已经死了，是Rod扼杀了它。”<br />Rod Johnson：持久化部分令人敬畏，并且将会被广泛拥抱。其它部分比起现在的方案要差，例如监听能力。[编辑解释：Spring+JPA将好于EJB3]。<br />Floyd Marinescu：这个问题实际上是“标准在新的开源世界中将扮演什么角色”？在开源世界中，最好的解决方案会成为标准，并且这样的方案不会变成厂商依赖而所定于某种商业项目，所以真正的问题是人们在已经有了Spring+Hibernate的时候是否会接受EJB。标准将会带来大面积的合作，这里稳定性问题要比创新更重要，但是我不认为小的项目会转入EJB3中。<br />Bruce Tate：“我不那样认为，EJB与那些都无关。它主要是包装和消灭POJO周围的服务，比如Spring……比如JBoss，它们给我们的很多东西和周围的API都是第二位的。”<br />Ari Zilka：一定要分辨出巨大变化的催化剂。对持久化部分有催化剂/需求，并且它是独立的。目前EJB2的项目没有足够的理由转移到EJB3，因为在功能角度没有足够多的变化。<br />而后是一些关于开源、Linux等方面的问题，具体参照原文。<br /><a href="http://www.infoq.com/news/Future-of-Enterprise-Java-Panel">http://www.infoq.com/news/Future-of-Enterprise-Java-Panel</a></p>
		<p>抽出一下：<br /><font color="#0000ff">1、Java从语言转向平台。如同.Net，JVM本身提供了平台的抽象。将会扩展动态语言与脚本语言的支持。<br />2、企业应用的开发过程将简化，如MDD一类，但目的是集中精力开发商业逻辑，而不是纯简化代码或者什么什么。小型应用可能会转向动态语言或脚本语言所营造的舒适开发框架，如RoR，或其它Rails。<br />3、富领域模型替代贫血模型，基于JPA。<br />4、目前的AOP、IoC工具依然会流行，而不一定会限定于EJB3模型中。事实说了算，Spring这种事实性标准影响力还是很大的。<br />5、分布式的考虑，可伸缩型问题凸显。如何透明实现分布式是个关键性问题，AOP是技术契机。<br />6、Web2.0会产生巨大影响力，但Java绝不是唯一选择。Java要找好自己的位置，同时在平台上最好能够更多的融合，如让JVM支持PHP/Ruby/Python。<br />7、Web部分竞争激烈，并会持续。EJB3的JSF命运难测。看Web2.0的浪潮了。</font></p>
<img src ="http://www.blogjava.net/iamtin/aggbug/57479.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-07-10 14:09 <a href="http://www.blogjava.net/iamtin/archive/2006/07/10/57479.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>范型擦拭法即范型类无法获取范型参数信息的原因</title><link>http://www.blogjava.net/iamtin/archive/2006/05/08/45091.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Mon, 08 May 2006 13:37:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/05/08/45091.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/45091.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/05/08/45091.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/45091.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/45091.html</trackback:ping><description><![CDATA[
		<p>江南白衣的Blog上一篇：<br /><a id="viewpost1_TitleUrl" href="/calvin/archive/2006/04/28/43830.html">Java5泛型的用法，T.class的获取和为擦拭法站台</a><br />他参考的这里：<br /><a href="http://www.hibernate.org/328.html"><font color="#366900">Generic Data Access Objects</font></a><br /><br />我们的项目中也用的GenericHibernateDAO，里面使用了一个：</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: #0000ff">public</span>
				<span style="COLOR: #000000"> GenericHibernateDAO(</span>
				<span style="COLOR: #0000ff">final</span>
				<span style="COLOR: #000000"> Class</span>
				<span style="COLOR: #000000">&lt;</span>
				<span style="COLOR: #000000">E</span>
				<span style="COLOR: #000000">&gt;</span>
				<span style="COLOR: #000000"> clazz) {<br />        </span>
				<span style="COLOR: #0000ff">this</span>
				<span style="COLOR: #000000">.clazz </span>
				<span style="COLOR: #000000">=</span>
				<span style="COLOR: #000000"> clazz;<br />    }</span>
		</div>
		<br />的构造函数。<br />但是看了江南白衣的介绍，的确方便的可以写成：<br /><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: #0000ff">public</span><span style="COLOR: #000000"> GenericHibernateDAO() {<br />        </span><span style="COLOR: #0000ff">this</span><span style="COLOR: #000000">.clazz </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (Class</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">E</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">) ((ParameterizedType) getClass()<br />                                                         .getGenericSuperclass()).getActualTypeArguments()[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">];<br />    }</span></div>这样，继承的子DAO就可以不用写Super(xxx.class)进行构造了。<br /><br />其中的：<br />(Class<span style="COLOR: #000000">&lt;E</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]; <br />非常神奇，看了faint的一个回复（请参照白衣的Blog）：<br /><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: #0000ff">package</span><span style="COLOR: #000000"> test; <br /><br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.ParameterizedType; <br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> java.lang.reflect.Type; <br /><br /></span><span style="COLOR: #0000ff">import</span><span style="COLOR: #000000"> junit.framework.TestCase; <br /><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> TClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> { <br />} <br /><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> GoodClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> TClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> { <br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> ParameterizedType getClassT() { <br /></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (ParameterizedType) getClass().getGenericSuperclass(); <br />} <br />} <br /><br /></span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> BadClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> TClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> { <br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> ParameterizedType getClassT() { <br /></span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (ParameterizedType) getClass().getGenericSuperclass(); <br />} <br />} <br /><br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> GenericsTest </span><span style="COLOR: #0000ff">extends</span><span style="COLOR: #000000"> TestCase { <br /><br /></span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> print(Type[] targs) { <br />System.out.print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">actual type arguments are:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br /></span><span style="COLOR: #0000ff">for</span><span style="COLOR: #000000"> (</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> j </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">; j </span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000"> targs.length; j</span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">) { <br />System.out.print(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> instance of </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> targs[j].getClass().getName() </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">:</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br />System.out.println(</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> (</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> targs[j] </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">); <br />} <br />} <br /><br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testGoodClass() </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception { <br />ParameterizedType type </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> GoodClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">().getClassT(); <br />Type[] types </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> type.getActualTypeArguments(); <br />print(types); <br /><br />assertEquals(TClass.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, type.getRawType()); <br />assertEquals(String.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, types[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]); <br />} <br /><br /></span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> testBadClass() </span><span style="COLOR: #0000ff">throws</span><span style="COLOR: #000000"> Exception { <br />ParameterizedType type </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> BadClass</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">String</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">().getClassT(); <br />Type[] types </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> type.getActualTypeArguments(); <br />print(types); <br /><br />assertEquals(TClass.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, type.getRawType()); <br />assertEquals(String.</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000">, types[</span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">]); <br />} <br />}<br /></span></div></span>例子中的 BadClass 非常有意思，无法获取T的实际类型，我试验了半天也得不到。<br />看到也有朋友问这个问题：<br /><a href="http://forum.java.sun.com/thread.jspa?threadID=684429&amp;messageID=3985573">http://forum.java.sun.com/thread.jspa?threadID=684429&amp;messageID=3985573</a><br /><br />纳闷，怎么就不行呢。<br />翻了翻候捷的这篇文章：<a href="http://www.jjhou.com/javatwo-2004-GP-in-jdk15.pdf">http://www.jjhou.com/javatwo-2004-GP-in-jdk15.pdf</a><br />才恍然大悟，原来对于BadClass这种情况就是获取不了它的Class。 
<div style="COLOR: red"><br />这是擦拭法的本意。<br />实际上BadClass&lt;String&gt;()实例化以后Class里面就不包括T的信息了，对于Class而言T已经被擦拭为Object。而真正的T参数被转到使用T的方法（或者变量声明或者其它使用T的地方）里面（如果没有那就没有存根，这里指ParameterizedTyp），所以无法反射到T的具体类别，也就无法得到T.class。<br />而getGenericSuperclass()是Generic继承的特例，对于这种情况子类会保存父类的Generic参数类型，返回一个ParameterizedType，这时可以获取到父类的T.class了，这也正是子类确定应该继承什么T的方法。<br />我们应该利用这种特性，这对实现模版方法非常有用。</div><img src ="http://www.blogjava.net/iamtin/aggbug/45091.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-05-08 21:37 <a href="http://www.blogjava.net/iamtin/archive/2006/05/08/45091.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>分页的轻量实现</title><link>http://www.blogjava.net/iamtin/archive/2006/03/31/38438.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Fri, 31 Mar 2006 04:30:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/03/31/38438.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/38438.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/03/31/38438.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/38438.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/38438.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 为我们的项目写的一个轻量的分页API。目的在于将分页与数据查询的逻辑完全剥离。我以前看过robbin发的通过detachedCriteria实现的分页那片贴子，里面把分页和数据查询结合在一起了。而我觉得分开更轻量，而且替换也比较容易。但是这个实现中有一个反模式，在逻辑中生成了代码，无奈之选，为了简便。其中字符生成可以自己扩展i18n实现，应该非常容易。分页实现的接口：package com.gol...&nbsp;&nbsp;<a href='http://www.blogjava.net/iamtin/archive/2006/03/31/38438.html'>阅读全文</a><img src ="http://www.blogjava.net/iamtin/aggbug/38438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-03-31 12:30 <a href="http://www.blogjava.net/iamtin/archive/2006/03/31/38438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java Web 框架的“甜点”</title><link>http://www.blogjava.net/iamtin/archive/2006/03/30/WebFrameworkSweetSpots.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Thu, 30 Mar 2006 08:28:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/03/30/WebFrameworkSweetSpots.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/38276.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/03/30/WebFrameworkSweetSpots.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/38276.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/38276.html</trackback:ping><description><![CDATA[
		<p>
				<font size="6">
						<strong>Jave Web Framework Sweet Spots</strong>
				</font>
				<br />
				<font size="5">
						<strong>Java Web 框架的“甜点”</strong>
				</font>
		</p>
		<p>这是一篇很有趣的文档，所以摘要一下，其实类似阅读笔记，好像是3/25发布的：</p>
		<p>不知怎么翻译Sweet Spots，难道翻译为甜处、甜头、蜜点、蜜穴？</p>
		<p>这时基于对以下人的采访：<br />JSF  Jacob Hookom<br />RIFE  Geert Bevin<br />Seam  Gavin King<br />Spring MVC Rob Harrop<br />Spring Web Flow Rob Harrop and Keith Donald<br />Stripes  Tim Fennell<br />Struts Action 1 Don Brown<br />Tapestry Howard Lewis Ship<br />Trails  Chris Nelson<br />WebWork  Patrick Lightbody<br />Wicket  Eelco Hillenius</p>
		<p>原文在此：<a href="http://www.virtuas.com/articles/webframework-sweetspots.html">http://www.virtuas.com/articles/webframework-sweetspots.html</a></p>
		<p>
				<font size="6">
						<strong>
								<font size="5">JSF(Jacob Hookom)</font>
								<br />
						</strong>
				</font>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？<br />当你希望浏览器程序像桌面程序一样工作的时候，你可以遵循标准并获得大量第三方支持。它致力于降低复杂度。它允许你不与view和特定的action、参数传递、状态传递、渲染打交道就可以进行高质量的开发，不管是否使用工具。<br />2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？<br />它不适合大规模的、只读（其实指读为主）的网站。在这种情况推荐Struts，因为知识库丰富（应该指文档和用户群）。<br />3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？<br />Seam：<br />优点：非常简单直接<br />缺点：对于大项目过于简单；没有模块化开发的好例子<br />Struts：<br />优点：巨大的文档和用户群；跟着它没错<br />缺点：状态/行为的分离过于教条化<br />WebWork：<br />优点：比Struts易于使用<br />缺点：复杂的UI难于维护，UI代码过于复杂（JSF作者对action Framework都攻击这一点）<br />Tapestry：<br />优点：概念新颖；可以应付复杂的UI<br />缺点：对于一个组件化（JSF主要竞争对手），它依然依附于page/action的概念<br />4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？<br />他认为JSF这个标准下这些应该有第三方提供。JSF(2.0)会提供“Partial Faces Request”，它是Ajax实现。JSF也会增强annotation组建编程。<br />5、有对你们的framework的传言需要澄清么？如果有，是哪个？<br />很多JSF书都拿Struts作为对比。他认为这不能体现JSF的特点。他认为Struts和WebWork能做到的JSF也能做到。<br />6、你对Ruby on Rails的看法如何？<br />它与WebWork一样好用，它的CoC（Convention over Configration）和脚手架非常好用。他认为CoC可以被应用在任何framework，他认为这是RoR最大的优点。他还认为RoR会走上其它framework的路（复杂性等），因为人们需要自己的扩展。</p>
		<p>
				<font size="5">
						<strong>RIFE(Geert Bevin)</strong>
						<br />
				</font>
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />你可以付出10%的工作量，得到其它framework的90%的……，它是一个full-stack framework（如RoR）。它吸收了成熟的分层框架的架构，并将共同的优点汇集在一起。提供了web continuation，POJO驱动的CRUD生成，可扩展的基于组建的架构，无session的状态控制，关注REST作为API，双向无逻辑模版引擎，集成了内容控制框架（CMS？）。每个层次的组建提供了可复用性（AOP，site，sub-site，page，widget，portlet等）。适合于团队快速开发公共Web项目，适合喜欢开发可复用组件的人。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />团队中的每个人都有其它framework的知识，难于培训他们。开发状态相关的服务器端Web组件，而不是用RIA或Ajax去实现。第三方支持很重要的情况下（可怜RIFE用户群还不大）。他推荐这种情况下使用JSF。或者在XML为主要发布形式的情况下，推荐Cocoon。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />他试验过WebWork，JSF，Wicket。他喜欢WebWork的简单，但是不喜欢它的模版方式（tag的template，应该），它也不提供组件封装。他认为JSF的工具支持非常吸引人。Wicket的纯Java实现很不错，可惜XML配置很不爽。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />关于Ajax，RIFE刚刚集成了DWR，而且选定以后也使用这个。集成Dojo，Scriptaculous，Prototype都很容易集成进来。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />这些错误理念：1、RIFE的XML配置繁琐 2、RIFE是continuations server 3、RIFE重新造轮子没有提供新鲜东西 4、RIFE的模版语法很蹩脚过于简单和业余 5、RIFE是基于request的framework 6、RIFE的功能太多，学习曲线陡峭<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />RoR对Java社区的冲击非常棒，元编成也得到了信任。RoR没什么特殊之处，也没有从Ruby语言获益很多。<br />我讨厌：它的模版。Partials（RoR中的组件）。URL的分散处理。Active Record提供了从数据库schema而来的DSL，但是却不是从domain model而来。没有l10n和i18n支持。手动状态转换。不能在JVM运行（……）。实际上脚手架生成了实际代码。Ruby缺少工具和IDE。</p>
		<p>
				<strong>
						<font size="6">
								<font size="5">Seam(Gavin King)</font>
								<br />
						</font>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />拥有丰富用户交互体验的应用。方便实现多窗口的操作，回退的支持，单窗口多工作区，无状态浏览。对商务流程（BPM）的集成是独一无二的。Seam方便使用数据驱动的ORM。遵循JSF和EJB3，多任务支持（多窗口/多工作区），BPM的领先解决方案。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />不适合只是将数据从数据库显示到网页的应用，这时应该使用PHP或RoR。不适合需要设计特别的HTML组件的情况，此时应该选用Tapestry或Wicket。还在使用JDK1.4的人们。还有那些喜欢Struts的人（嘿嘿，够狠）。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />JSF：喜欢他的事件/交互模型。喜欢他的EL和模型绑定。不喜欢那么多XML（为什么没有annotation）。创建自己的controls太难了。<br />Tapestry：非常好。form验证是它的杀手锏！模版方式很有创意。不过非基于POJO的组件模型则让我对它失去兴趣。<br />RIFE：这个东西很怪，但是有创业也有趣。我想进一步学习。如果学习先要自费武功:D<br />Struts：这个东西的模型view绑定太复杂了。东西已经过时了。<br />WebWork：比Struts好一点，不过也过时了。XWork曾经是个很好的实现，不过现在也过时了。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />Portal支持。远程框架Seam Remoting Framework（Ajax）。模版消息的工具支持。以后还要集成ESB，计划引擎和异步支持。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />这些都不是真的：JSF不能处理GET requests。JSF post后无法redirect。JSF不能与REST共存。<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />它是PHP的很好替代品。如果它有一个正经一点的持久化层它就可以和Java竞争了。</p>
		<p>
				<font size="6">
						<strong>
								<font size="5">Spring MVC(Rob Harrop)和Spring Web Flow(Rob Harrop and Keith Donald)</font>
						</strong>
				</font>
				<br />
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />Spring MVC：<br />稳定可扩展，支持了i18n、文件上传、异常处理，这些稳定的支持给开发者坚实的工作基础。是最佳实践，告诉你怎么做是最好的。与Spring集成，领先的IoC远生支持。支持，Spring社区活跃和庞大。Struts开发者可以平滑过渡。适合多种项目，可选的多种result类型。<br />Spring Web Flow：<br />内置任务处理引擎，支持线性处理过程中的持续状态。抽象，减少开发的关注点。适合多种项目类型，插件支持Spring MVC、Struts、JSF等。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />Spring MVC：不适合需要组件化开发的场景。它是一个request驱动的MVC。那些场景推荐JSF或Tapestry。<br />Spring Web Flow：处理线性页面流，不适合一般的“自由浏览”。当然Spring Web Flow可以与request驱动或者组件驱动共存。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />Spring框架支持Struts和JSF集成。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />Spring MVC：简化JSP标签。更多的MVC配置schema。CoC风格的默认控制器、URL影射、view，学习Rails和Stripes的优点。增强数据绑定和验证（支持范型绑定）。Portlet支持。Spring也要接受Ajax，使用DWR库。<br />Spring Web Flow：一大堆，关心的可以自己看……<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />Spring MVC难于配置。在Spring 2.0，将会改善，可以使用自己定义的基于schema的配置。<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />Spring MVC：RoR非常有趣。不过现在就拿出来用还有点幼稚。这里举了个例子，关于变量的复数形式的处理，RoR会使用这样的CoC风格来处理变量list，而Spring MVC也实验了种种风格，但是受到的结果却很差。人们认为英语的复数很古怪，没有一定的规则，所以会带来混乱，如（person -&gt; people）。所以Spring MVC设计了变量+List的命名，personList更加明确，虽然这样不酷，但更好用。就是说Spring MVC要取其精华去其糟粕。</p>
		<p>
				<font size="6">
						<strong>
								<font size="5">Stripes(Tim Fennell)</font>
						</strong>
				</font>
				<br />
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />与Spring MVC、WebWork等相同。它提供高质量action驱动的框架的同时，尽量简化配置，增进开发效率。Stripes适合复杂的数据交互的场合。这种情况下绑定验证的强项就完全体现出来了，能够很好的处理form和map转换等。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />所有的action驱动的framework都适合用户在非Ajax驱动的情况下在一个页面进行松关联（loosely related）和无状态交互的情况。适合每次都刷新的页面。管理多窗口间持续状态的应用会比较麻烦，此时应该选择JSF。不过我认为90%以上的Web程序都是前者，JSF只适合剩下的那9%，AJAX对于管理无状态UI更加适合。客户端不需要AJAX，则可以看看Wicket，它更加简单。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />用过Struts、WebWork、Spring MVC。其中Struts做过商业项目，不过这个东西带来的麻烦远比带来的效率提升要多。它认为这些MVC都有三个缺点：暴露了过多的复杂性给可发者。没有提供足够的开发便利性，没有提供足够多的错误和提示信息，也没有date格式化等小的便利（其实有）。稳当太差。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />1.3要加入Inteceptor，实现AOP功能。验证系统要加强。支持Ajax。我还在寻找一个好的Ajax/javascript库。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />这些观点：1、Stripes使用了annotation代替XML，只是换汤不换药：由于元数据更接近代码，所以修改默认的配置非常方便，不像XML那样复杂，这是实质的变化。2、Annotation意味着你只能有一套配置：我认为90%的action都有自己的一套配置！Stripes会根据继承关系寻找Annotations，子类的annotation会覆盖父类的，因为像validation都是可以继承的，如果特别需要还可以覆盖。这样很合理。在1.3中允许validations基于UI事件进行。它向后兼容，不需要可以不用。<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />我认为Java社区有很多可以从RoR学习的地方。Stripes学习了RoR的前端部分，开发者可以减少配置量。但是RoR的RHTML让我想到了以前的JSP中混乱的scriptlet。而后面的ActiveRecord是一个很好的理念，实现的也很好。ActiveRecord比Hibernate等复杂的ORM工具要容易理解，因为这样的特点RoR才引起了这么大的波澜。</p>
		<p>
				<font size="5">
						<strong>Struts Action 1(Don Brown)</strong>
						<br />
				</font>
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />文档和用户基础，书籍和背后的支持。容易雇到人（也容易找工作）。虽然其他项目的理念比这个要先进，但是这些不算什么。实际上，Web层是很容易也很直接的。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />如果你需要portlets或者复杂的页面（显示很多东西），那么Struts要么无法工作要么太枯燥。这种情况你需要一个基于组件的framework，如JSF、Tapestry/Wicket。<br />3<strong>、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />这些我基本都试验过，他们每个都工作的很不错。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />Struts Action 2基于WebWork2，很快会开始。现在已经支持Ajax了，我们在寻找更加容易的开发方式，JSF支持（Struts Shale），continuation支持，还有支持更多的脚本语言（BSF扩展脚本撰写Action）。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />Struts太过时了，而且也不酷，难于使用。但是你可以自己修改或者扩展它。我认为团队对于你的限制远大于framework对你的限制。<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />不需要D&amp;D工具，旨在帮助开发人员提高开发效率的好例子。我们在Action 2中将学习它的先进理念。</p>
		<p>
				<font size="6">
						<strong>
								<font size="5">Tapestry(Howard Lewis Ship)</font>
						</strong>
				</font>
				<br />
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />我想Tapestry对于中等规模或者大规模的应用会带来很多好处（甚至你可以在单页面的应用程序中获得好处）。这里有允许你创建新的组件的良好工具。Tapestry不关心数据从哪里来，很多“项目类型”都基于切面（aspect）（如CRUD vs. RSS feed vs. etc.）。我认为Tapestry非常容易与IoC集成（HiveMind或与Spring），方便进行测试。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />我在其它Java framework中没有找到到强于Tapestry的优点。但是对于RoR，我自己没有使用过使用，很难说RoR中的项目应该是什么样子。我没有仔细对比过RIFE，它看起来受了RoR影响，尤其是类似ActiveRecord的数据访问层。但是如果你的应用需要特定的URL格式，那么在Tapestry中奋战胜算不大。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />在这两年来我没怎么尝试过Tapestry以外的东西。我没怎么学习RoR，因为时间太有限了。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />Tapestry 4.0有很好的Ajax支持，通过Tacos库。而Tapestry 4.1还要进一步强化这方面的支持。<br />Tapestry 5.0提供了明显的改进：没有abstract类（Tapestry的怪癖:）。没有强迫的继承关系。对属性进行annotation而不是方法。没有XML，只有模版和annotaions。只能类装载，自动寻找类的变化。最小化API，超越annotaion。面向方面（Aspect-oriented）模块构造，使用mix-ins。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />Tapestry 3.0还不容易测试，4.0改善了一些。Tapestry只是个人秀；实际上我们有很多活跃的贡献者。Tapestry的学习曲线非场陡峭。它只有漂亮的模版实现；实际上Tapestry的特点在于状态管理（允许对象存储状态，而不是多线程的单例来管理requests之间的游离和持久状态）<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />很有影响力。但是模版的实现非常丑陋。我听到了很多意见，关于RoR的优缺点。基于我的基本理解，这些观念对Tapestry 4产生了影响（它对Tapestry 5影响更深）。<br />RoR意味着限制了你的选择：如果你选择RoR那么就要尊旬它的实践（CoC..），看起来你的钱会花的恨值。这些类似Microsoft的哲学。而Java更崇尚给你更宽松的选择，不限定你使用的工具，但是暧昧的说这需要你对你的工具理解更深。不仅对Tapestry，还对于JEE、Spring这写entire stack的框架，需要从RoR学习，不仅提供工具，还需要提供整套的解决方案。</p>
		<p>
				<font size="6">
						<strong>
								<font size="5">Trails(Chris Nelson)</font>
						</strong>
				</font>
				<br />
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />Trails的应用程序只需要Web界面和持久化的domain model就可以了。Trails给你的domain model快速的提供一个界面，除了POJO自己不需要附加的代码。Trails允许你修改界面的外观和行为，包括验证、i18n、安全。这些都不需要java代码生成，不喜欢代码生成的人应该感觉很舒适。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />Trails讲究够用就好。它允许你快速交付，问问你的客户：“这样够好么？”。这会改变你的工作流程，当然这不是可以覆盖所有需求的解决方案。当UI需求很高，Trails没有优势。我认为Trails适合于混合的应用，对于管理员他们只需要够用就好，那么就可以使用Trails。其它的部分我们可以订制开发，我们在使用Tapestry、Hibernate、Spring来实现这些部分，Trails正是基于它们。对于非交互的应用，Trails也不适合，如报表应用，可以考虑Eclipse BIRT。<br />3<strong>、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />我用Struts很多。它曾经是伟大的framework。主要的缺陷是它不能自动帮定数据到domain model。我也研究过JSF，它比Struts强，但是自定义组建非常难。Tapestry非常便于自定义组建，尤其对于建立高阶组件（有其它组件组成的）非常方便，Trails正在使用它。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />对于Trails来说我们站在巨人的肩膀上。Tapestry在ajax功能作了很多努力，所以Trails也不难与其共舞。但是我们需要创建更多的例子来演示这些。我们也致力于让Trails容易介入到已经进行的项目中。以后Trails还要加入基于实例的安全（instance-based security）（目前正在使用基于角色的role-based），还有method invocation。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />Trails是对RoR的移植。Trails的名字来自Rails。它是基于Rails的理念，但不是对它的移植。<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />我认为我们有很多需要从RoR学习的地方，那将帮助我们享受开发Web程序的惬意。</p>
		<p>
				<font size="6">
						<strong>
								<font size="5">WebWork(Patrick Lightbody)</font>
						</strong>
				</font>
				<br />
				<strong>1、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong>
				<br />一般来说，WebWork一般适合小的团队，它们愿意保持一双脏手，学习开元工具如何使用。WebWork不面向“轮椅程序员”，那些人只喜欢拖拽式的开发。WebWork给花时间学习它的人回报。例如，直到输入和输出的人（阅读了参考文档，那样很好）能够容易的创建ActionMapper和Configuration实现来提供“惯例”代替配置（CoC）的方便。我最近的例子中，URL是这样“/project/123/suite/456/test/create”影射到“com.autoriginate.actions.project.suite.test.CreateAction”，然后自动的传递参数：projectId=123、suiteId=456。而Result是“[action].jsp”或者“[action]-[result].jsp”，也可以通过annotation来配置。<br />也就是说，WebWork是你的应用程序framework中的最佳基础工具。在这种情况以外也很好，但是目前不算最佳的“甜点”。<br />除去这些一般的，WebWork对于正在创建需要插件和扩展的产品的人是必备的。例如JIRA、Confluence、Jive Forums。因为WebWork支持广泛的模版语言（Velociy和FreeMarker），完整的tag支持，模块写好后非常容易插入。一个jar包就可以包括所有的action和view（得益于ftl的classpath支持）。最终的效果很好：在Confluence中你可以通过管理界面上传一个jar，这个plug-in就会自动部署。这是因为Atlassian（Confluence、Jira的小组）非常了解这个framework，并且作了很多的贡献。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？</strong><br />与其它action framework相同，WebWork在控制状态和wizards上比较弱。如果你写了很多长的wizards，JSF可能是比较好的解决方案。我还想说，文档还需要改善（参考文档还不错，但是教程、cookbooks和FAQ还比较差），如果没有一个WebWork高手作为项目领队，新手可能会敬而远之。<br />对于非常简单的程序，我推荐使用简单的JSP或者Spring MVC，如果用户接受Spring的话。但是总的来说，我认为在action framework中WebWork是最好的。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？<br /></strong>我试验过RIFE、Spring MVC、Struts、Spring Web Flow，还有一点点Tapestry。我发现RIFE的概念很优秀，但是它的实现不怎么样。不难想象Geert还是使用“m_”作为字段的前缀。它看起来不像Java。模版难住了我，所以就没有继续看。<br />Spring MVC还可以，但是它是一个非常简单的framework实现。WebWork的数据绑定（WebWork世界中称为类型转换）要强多了，而且是自动的（而Spring需要自己写property editors）。在Spring中的view替换支持泰有限了，而WebWork中的UI tags在Spring中压根没有提供。Spring中你可以使用JSP 2.0轻松的写自己的tag，但是不支持其它的语言。<br />Spring Web Flow：XML让我抓狂。太过火了，不管Keith的主张，它“不支持任何的Web framework”。这个web framwork回避掉了WebWork、Spring MVC、Struts或者其它framework中的99%。我倒不是说这是个坏主意，但是我应该诚实的说它是一个完整的框架。<br />Tapestry很优雅，但是HTML属性（jwcid）惹人厌。我接受这种理念，且实践中这会带来一些好处（Shale也有相似的地方）。但是实际上，我发现“HTML/CSS开发者”和“app开发者”一般是同一个人，Tapestry就架设如此。实际上，由于Ajax的推动，我想越来越多的“程序逻辑”会被嵌入到UI；这样的话，Tapestry的模型就不那么适宜了。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />在Struts Action 2.0我们希望：更好的文档。支持标准（如果可以，我们希望用JSTL代替OGNL，但是首先要保证不会有功能损失）。增强AJAX支持，提供更多的widgets：如自动完成。解除配置地狱；提供更多的选择，如我们开始所说的CoC。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />他需要很多的配置：我已经演示过，通过CoC风格，它可以做的比Rails更好（Rails的管理部允许内嵌controllers）。<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />非常重要的一点是，我要说RoR不能与大多数的framework对比，除了RIFE和Seam。对比RoR和WebWork就相当于对比Hibernate和JDBC。一个是full stack，另一个只是stack中的一部分。<br />另一个重要的问题：DHH是个怪胎，但是聪明的怪胎。它的高效率无可争辩，它被称为Rails。<br />好的，我们不说这个，随便说说别的：<br />我使用Rails创建了一个小的app。我把它扔掉并很快用Java重写了。我认为Rails可以让你的app中的80%快速完成；而剩下的20%比前面80%需要花的时间还多。当然程序开发就是这样。脚手架非常酷，尤其是ActiveRecord在运行时改变类。但是后来你需要写UI、自定义的验证规则，自定义安全影射等等。一个基于CRUD的app能够在30分钟内运行并不意味着你能以这个速度完成它。<br />Rails的web framework部分相比于WebWork很可怕。实际上根本无法比较。它的实现更接近于Spring MVC的简单功能。<br />完整的stack非常棒。他们在这方面做得很好，这里Java还有差距需要追赶。WebWork是web stack，但是持久化解决方案并不确定。所以最大的问题在于即使WebWork和SiteMesh提供了如配置动态读取和动态类reloading，Spring、iBatis和Hibernate并不提供。它们至少需要提供配置重读取后才可以发展出类似Rails那样的功能。类似的，Hibernate和iBatis对WebWork等的请求提供的支持不够。对于一个类，我可以不需要再xwork.xml中进行配置，但是持久化引擎并不允许我们这样做。当这些功能能够同时具备，没准一个complete stack的框架就会推出。<br />要求快5倍10倍是愚蠢的。可靠的工程师都知道开发产品的时候最大的警力都花费在构思代码上，而不是书写代码。定义需求，获取反馈，市场定位，定义数据库结构，映射用户接口。不管使用什么语言，你需要思考很长时间。没有语言或者框架能够提升思考的速度。<br />最后，Rails提供了：用脚本语言良好实现的stack。Python、Perl尤其是PHP中的其它框架还没有成熟。我认为“PHP猴子”们还有很多事情要做，他们通常不是很有才干的工程师。（可能我翻译错误了，希望纠正）。在脚本语言中提供良好的框架，人们能够实现设计精良的app并的到回报（因为脚本语言的特点）。不只是“管理代替配置CoC”甚至是集成stack，Java需要的是立刻反射出变化的能力。很多Java开源领袖认为“修改web.xml”的重新载入是一种方法。这种智力游戏应该结束了。我们不仅仅需要配置文件和类的重新载入，我们需要社区给Sun足够的压力，使其能够在下一代的JVM中提供热插拔（HotSwap）的能力。或者，更加复杂的程序模型，如OSGi，需要进一布被社区所接受。当然我并不希望走那条路线。</p>
		<p>
				<font size="5">
						<strong>Wicket(Eelco Hillenius)</strong>
						<br />
				</font>1<strong>、你认为你的framework的“甜点”在哪里？他最适合哪种类型的项目？</strong><br />我认为有5点：Wicket是以代码为中心的：可以在view层进行OO编程。组件是完全自管理的：容易创建和重用。概念的分离是清晰的也是强迫的。干净的模版。开发伸缩性大-就像OO一样。<br /><strong>2、它不适合于什么样的场景？在这些场景你推荐什么fremework？它是哪个？<br /></strong>Wicket不适合UI很简单且只读的场合。这时页面脚本更加适合，比如JSP，或者JSF。如果你需要无限的可伸缩性，你可能需要状态无关的实现。从1.2版开始，Wicket也有无状态页面的概念，这样可伸缩性与其它framework差不多了。<br /><strong>3、在下面提到的framework中，你试验过他们么？如果试验过，你比较喜欢哪个？你不喜欢哪个？</strong><br />JSF：<br />优点：基于组件。工业背景。工具支持。一些扩展让他更容易使用。它允许你从传统JSP升级到JSF。<br />缺点：它缺少其它API的优雅。以JSP为中心。配置很多而且代码很难看。有很多种实现。它让我回忆起EJB1/2，以厂商为中心等等。<br />RIFE：没用过，说了一大堆。<br />Seam：不是一个真正的Web framework。类似JSF扩展。如果使用EJB/JSF/JBoss组合，这个选择很好。但是不遵循JSR 227/235。<br />Tapestry：很好，4.0版本好了很多。我把它推荐给我所工作的公司。Wicket更加以编程为中心。而Tapestry更加pragmatic。<br />Trails：从来没用过。<br />Spring Web Flow：framework本身很好，但是我不喜欢它的stacking。如果用工作流，我希望选择一个如jBMP的方案。我也不喜欢以流为中心的解决方案，认为这样很过程化。<br />WebWork、Spring MVC、Struts：Model 2的framework糟透了。我用过几年，也对Maverick贡献过代码，但是我彻底失去兴趣了。Model 2 framework太过程化了，这些程序员不知道怎么用OO编程。我宁可雇佣一个Swing编程的人也不会去选择一个使用Model 2 framework编程的人，因为Swing编程的人写的程序一般更漂亮。……如果让我从这些Model 2 framework中挑一个出来，我选择Stripes，它抛弃了model 2中的一些不好的方面。<br /><strong>4、你的framework的未来会怎样？对于用户开发会有什么方便使用的变化？你会原生支持Ajax么？你们计划支持它了么？</strong><br />我们将会支持Java5。我们会增强Spring支持，复杂的权限认证支持，和基于角色的参考实现，还会提供原生AJAX支持，URL加载（nice URLs），无状态页等。<br />我们的市场占有率不高，但是用户群在提高。我正在写“Wicket In Action”（Manning出版）正在筹划中，今年夏天会出版。<br /><strong>5、有对你们的framework的传言需要澄清么？如果有，是哪个？</strong><br />关于伸缩性的问题是第一位的。程序的可伸缩型一般是由数据库性能差或者缓存策略查询优化并发等问题。服务器端可伸缩性并不一定不可扩展，可以通过集群来继绝。……<br /><strong>6、你对Ruby on Rails的看法如何？</strong><br />我喜欢我看到的Ruby，如果我有时间我还会仔细把玩它。如果不是Wicket的问题，我希望更多的实践RoR。……</p>
<img src ="http://www.blogjava.net/iamtin/aggbug/38276.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-03-30 16:28 <a href="http://www.blogjava.net/iamtin/archive/2006/03/30/WebFrameworkSweetSpots.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Web MVC Framework - Stripes观后感</title><link>http://www.blogjava.net/iamtin/archive/2006/03/22/36922.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Wed, 22 Mar 2006 13:36:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/03/22/36922.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/36922.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/03/22/36922.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/36922.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/36922.html</trackback:ping><description><![CDATA[BJUG的Cleverpig说起Stripes，正好前两天在TSS上看到Simon Brown的Blog，对它有点感性认识，所以今天就看了一下，说些粗陋的感受：<br />皮毛上的观感：<br />1、使用Annotation配置。将Action影射、返回View、默认Command注册、是否验证这些东西都通过Annotations搞，挺有意思。<br />2、它也包装了自己的Tag，Tag从感官上感觉很像WebWork的风格（估计Stripes也是过这个来实现bind，和Spring MVC相同吧，不过没仔细看Stripes的bind方式）。但是它好像很方便与JSTL共用，所以我觉得它可能和Spring MVC类似，把变量拷贝到request里面，而不是WebWork那样的VlueStack。<br />3、它的Validation很Cool，用Annotation设定Validation相当舒适。<br />4、它里面的event似乎挺有意思，也就是说一个Action可以对应多个method，它管它叫Event。现在WebWokr和Spring MVC对这都有支持，但是Annotation带来些快感。<br />5、看到Simong Brown说Stripes有个userActionBean标签，能够直接调用ActionBean并邦定所有参数过来。这个和WebWork的ww:action很相似吧，起码理念上都应该是Page级别的Controler，方便复用Action的。这个东西挺好。<br />6、可惜，从Quick Start Guide里面看到jsp里面的jsp:useBean有些不理解。难道View又不纯洁了？而且如果把manager放到jsp里面那要MVC干什么？这个有点不知什么意思。<br />7、感觉Stripes更像Spring MVC，从形状上看像Annotation+Spring MVC，好像没提供更多的东西。它宣称的快速很多我不知道是否可信。<br />8、感觉好玩的是Stripes说自己的目标是做程序届的Apple硬件、SONY电器、德国汽车，这个……<br /><br />请参考这里：<br />Comparing webapp frameworks : Stripes<br /><a href="http://weblogs.java.net/blog/simongbrown/">http://weblogs.java.net/blog/simongbrown/</a><br />Stripes Best Practice<br /><a href="http://stripes.mc4j.org/confluence/display/stripes/Best+Practices">http://stripes.mc4j.org/confluence/display/stripes/Best+Practices</a><br />Stripes Home<br /><a href="http://stripes.mc4j.org/confluence/display/stripes/Home">http://stripes.mc4j.org/confluence/display/stripes/Home</a><img src ="http://www.blogjava.net/iamtin/aggbug/36922.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-03-22 21:36 <a href="http://www.blogjava.net/iamtin/archive/2006/03/22/36922.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>根据生日计算年龄</title><link>http://www.blogjava.net/iamtin/archive/2006/03/10/34608.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Fri, 10 Mar 2006 02:00:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/03/10/34608.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/34608.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/03/10/34608.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/34608.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/34608.html</trackback:ping><description><![CDATA[根据生日计算年龄可以通过Calendar实现。最简单可以考虑get(Calendar.DAY_OF_YEAR)来简单修正年龄，但是遇到生日在闰年的2月29之后，或者今年是闰年的2月29之后可能出现计算不准，误差一天。所以还是老实判断年月日好了。<BR>
<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: #0000ff">public</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;getAge(Date&nbsp;birthDay)&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throws</SPAN><SPAN style="COLOR: #000000">&nbsp;Exception&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Calendar&nbsp;cal&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Calendar.getInstance();<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(cal.before(birthDay))&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">throw</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;IllegalArgumentException(<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">The&nbsp;birthDay&nbsp;is&nbsp;before&nbsp;Now.It's&nbsp;unbelievable!</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;yearNow&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;cal.get(Calendar.YEAR);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;monthNow&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;cal.get(Calendar.MONTH);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;dayOfMonthNow&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;cal.get(Calendar.DAY_OF_MONTH);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cal.setTime(birthDay);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;yearBirth&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;cal.get(Calendar.YEAR);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;monthBirth&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;cal.get(Calendar.MONTH);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;dayOfMonthBirth&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;cal.get(Calendar.DAY_OF_MONTH);<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;age&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;yearNow&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">&nbsp;yearBirth;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(monthNow&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;=</SPAN><SPAN style="COLOR: #000000">&nbsp;monthBirth)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(monthNow&nbsp;</SPAN><SPAN style="COLOR: #000000">==</SPAN><SPAN style="COLOR: #000000">&nbsp;monthBirth)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">monthNow==monthBirth</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">if</SPAN><SPAN style="COLOR: #000000">&nbsp;(dayOfMonthNow&nbsp;</SPAN><SPAN style="COLOR: #000000">&lt;</SPAN><SPAN style="COLOR: #000000">&nbsp;dayOfMonthBirth)&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;age</SPAN><SPAN style="COLOR: #000000">--</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">do&nbsp;nothing</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">monthNow&gt;monthBirth</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;age</SPAN><SPAN style="COLOR: #000000">--</SPAN><SPAN style="COLOR: #000000">;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;</SPAN><SPAN style="COLOR: #0000ff">else</SPAN><SPAN style="COLOR: #000000">&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">monthNow&lt;monthBirth<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">donothing</SPAN><SPAN style="COLOR: #008000"><BR></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">return</SPAN><SPAN style="COLOR: #000000">&nbsp;age;<BR>&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></DIV><img src ="http://www.blogjava.net/iamtin/aggbug/34608.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-03-10 10:00 <a href="http://www.blogjava.net/iamtin/archive/2006/03/10/34608.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>eXtremeComponent在中文环境下的使用</title><link>http://www.blogjava.net/iamtin/archive/2006/02/16/31097.html</link><dc:creator>Tin</dc:creator><author>Tin</author><pubDate>Thu, 16 Feb 2006 13:10:00 GMT</pubDate><guid>http://www.blogjava.net/iamtin/archive/2006/02/16/31097.html</guid><wfw:comment>http://www.blogjava.net/iamtin/comments/31097.html</wfw:comment><comments>http://www.blogjava.net/iamtin/archive/2006/02/16/31097.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/iamtin/comments/commentRss/31097.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/iamtin/services/trackbacks/31097.html</trackback:ping><description><![CDATA[<SPAN class=postbody>不知道大家是否使用过eXtremeComponent，最早知道eXtremeComponent是从<A href="http://www.open-open.com/">www.open-open.com</A>，去年就在用了，感觉明显比display-tag要好用多了。 <BR>它使用jstl，所以与webwork集成也很方便，不象display-tag那样需要把hibernate返回的collection复制一遍再访问。 <BR><BR>具体的使用方法参考官方网站好了： <BR>官方网站在这里： <BR><A href="http://www.extremecomponents.org/extremesite/welcome.jsp" target=_blank>http://www.extremecomponents.org/extremesite/welcome.jsp</A> <BR>最新的版本是1.0.1-M4-A14，可以到这里下载： <BR><A href="http://www.extremecomponents.org/extremesite/public/download/" target=_blank>http://www.extremecomponents.org/extremesite/public/download/</A> <BR>或者直接下载： <BR><A href="http://www.extremecomponents.org/extremesite/public/download/extremecomponents-1.0.1-M4-A14.zip" target=_blank>http://www.extremecomponents.org/extremesite/public/download/extremecomponents-1.0.1-M4-A14.zip</A> <BR>但是这个snapshot版本没有依赖lib和资源文件等，推荐去这里下一个完整版本备用，目前最新的Production Release包是eXtremeComponents-1.0.1-M3-with-dependencies.zip： <BR><A href="https://sourceforge.net/project/showfiles.php?group_id=108168" target=_blank>https://sourceforge.net/project/showfiles.php?group_id=108168</A> <BR>最新版本的说明书在这里，说明书用的doc book格式，写的也很清楚： <BR><A href="http://www.extremecomponents.org/extremesite/public/download/eXtremeComponents.pdf" target=_blank>http://www.extremecomponents.org/extremesite/public/download/eXtremeComponents.pdf</A> <BR>很多人都对他使用的doc book声称doc感兴趣，spring和hibernate都用doc book，可是一般看不到源文件。作者很慷慨将doc book的源文件也分享了，是学习是学习使用doc book的好东西： <BR><A href="http://www.extremecomponents.org/extremesite/public/download/generate-docs.zip" target=_blank>http://www.extremecomponents.org/extremesite/public/download/generate-docs.zip</A> <BR><BR>资源就贴到这里，这里要提及作者Jeff Johnston人非常热情，论坛上四处可见他的身影，给他发信他也是每信必会、有求必应，承蒙他多次帮助。而且论坛中大家多次提及中文问题，他也很重视。 <BR><BR>转入正题： <BR>我贴一下一个例子： <BR>
<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"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:table&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #ff0000">items</SPAN><SPAN style="COLOR: #0000ff">="ecoAttrs"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>action</SPAN><SPAN style="COLOR: #0000ff">="/jgz/tjk/eco/listTjkAttByInfId.action"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>imagePath</SPAN><SPAN style="COLOR: #0000ff">="${pageContext.request.contextPath}/css/table/zh_CN/*.gif"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>cellpadding</SPAN><SPAN style="COLOR: #0000ff">="1"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>title</SPAN><SPAN style="COLOR: #0000ff">="农村经济运行情况列表"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>locale</SPAN><SPAN style="COLOR: #0000ff">="zh_CN"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>rowsDisplayed</SPAN><SPAN style="COLOR: #0000ff">="30"</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:export&nbsp;</SPAN><SPAN style="COLOR: #ff0000">view</SPAN><SPAN style="COLOR: #0000ff">="xls"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;fileName</SPAN><SPAN style="COLOR: #0000ff">="jgz_zyjjzbwcqk.xls"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;tooltip</SPAN><SPAN style="COLOR: #0000ff">="输出Excel文件"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:exportPdf&nbsp;</SPAN><SPAN style="COLOR: #ff0000">fileName</SPAN><SPAN style="COLOR: #0000ff">="jgz_zyjjzbwcqk.pdf"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;tooltip</SPAN><SPAN style="COLOR: #0000ff">="输出PDF文件"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;headerColor</SPAN><SPAN style="COLOR: #0000ff">="blue"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;headerBackgroundColor</SPAN><SPAN style="COLOR: #0000ff">="red"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;headerTitle</SPAN><SPAN style="COLOR: #0000ff">="密云县农村经济月份经济主要指标完成情况表"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:exportCsv&nbsp;</SPAN><SPAN style="COLOR: #ff0000">fileName</SPAN><SPAN style="COLOR: #0000ff">="jgz_zyjjzbwcqk.txt"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;tooltip</SPAN><SPAN style="COLOR: #0000ff">="输出CSV文件"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;delimiter</SPAN><SPAN style="COLOR: #0000ff">="|"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:row</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:column&nbsp;</SPAN><SPAN style="COLOR: #ff0000">property</SPAN><SPAN style="COLOR: #0000ff">="ofTown.name"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;title</SPAN><SPAN style="COLOR: #0000ff">="乡镇名称"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:column&nbsp;</SPAN><SPAN style="COLOR: #ff0000">property</SPAN><SPAN style="COLOR: #0000ff">="ncJihua"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;title</SPAN><SPAN style="COLOR: #0000ff">="农村计划"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:column&nbsp;</SPAN><SPAN style="COLOR: #ff0000">property</SPAN><SPAN style="COLOR: #0000ff">="ncWancheng"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;title</SPAN><SPAN style="COLOR: #0000ff">="农村完成"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:column&nbsp;</SPAN><SPAN style="COLOR: #ff0000">property</SPAN><SPAN style="COLOR: #0000ff">="ncQunian"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;title</SPAN><SPAN style="COLOR: #0000ff">="农村去年"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:column&nbsp;</SPAN><SPAN style="COLOR: #ff0000">property</SPAN><SPAN style="COLOR: #0000ff">="zongShouRuWCJH"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;title</SPAN><SPAN style="COLOR: #0000ff">="完成计划%"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">ec:column&nbsp;</SPAN><SPAN style="COLOR: #ff0000">property</SPAN><SPAN style="COLOR: #0000ff">="zongShouRuTB"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;title</SPAN><SPAN style="COLOR: #0000ff">="同比+/-%"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">ec:row</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">ec:table</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN></DIV><BR>其中ecoAttrs是一个collection，放入pojo。action里面写你这个页面的访问方法（如我的页面是一个action，其他的如.do或者.jsp什么的都可以）。rowsDisplayed是默认显示条数，它可以自动实现分页。 <BR>下面的三个&lt;ec:export&gt;是导出三种格式用的，不用的话可以不写（写了需要在web.xml配置相应的filter）。 <BR>&lt;ec:column&gt;里面放属性，property指向pojo的相应属性，而title是表头显示的信息，这个标签需要用&lt;ec:row&gt;包起来（1.0.1 m4以后）（抱歉pojo比较丑，出自同事之手）。 <BR><BR>这里放一套我做的中文图标： <BR><A href="http://tiny.51.net/extremecomponent/zh_CN.rar" target=_blank>http://tiny.51.net/extremecomponent/zh_CN.rar</A> <BR>还有我该写了一下css，更适合使用中文，将字体该为%大小，可以定义.eXtremeTable里面的font-size，即影响所有eXtremeTable里面的字体大小，也方便写js来动态修改大小： <BR><A href="http://tiny.51.net/extremecomponent/extremecomponents.css" target=_blank>http://tiny.51.net/extremecomponent/extremecomponents.css</A> <BR><BR>贴一下我在web.xml里面的配置： <BR>
<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"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter-name</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">eXtremeExport</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">filter-name</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter-class</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>org.extremecomponents.table.filter.ExportFilter&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">filter-class</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">filter</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter-mapping</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">filter-name</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">eXtremeExport</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">filter-name</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">url-pattern</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">/*</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">url-pattern</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">filter-mapping</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">taglib</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">taglib-uri</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">/extremecomponents</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">taglib-uri</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">taglib-location</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">/WEB-INF/tld/extremecomponents.tld</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">taglib-location</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #008000">&lt;!--</SPAN><SPAN style="COLOR: #008000">&nbsp;别忘了把那个tld拷贝到相应目录去&nbsp;</SPAN><SPAN style="COLOR: #008000">--&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">taglib</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN></DIV><BR>其实，那个filter只是在使用&lt;ec:export&gt;的时候才需要，不过这个功能还是很有用的。 <BR><BR>export里面的excel和pdf默认不支持中文，需要手工修改源码，excel的比较简单： <BR>修改org.extremecomponents.table.view.XlsView.java（我指的是1.0.1-M4-A14的相应代码） <BR>102行： <BR>
<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"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">HSSFCell&nbsp;hssfCell&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;hssfRow.createCell(cellnum);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>hssfCell.setEncoding(HSSFCell.ENCODING_UTF_16);（就是添加这一行）&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>122行：&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>HSSFCell&nbsp;cell&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;row.createCell(cellnum);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>cell.setEncoding(HSSFCell.ENCODING_UTF_16);（就是添加这一行）&nbsp;</SPAN></DIV><BR>这个在使用UTF-8时工作正常。如果其他Unicode环境可以尝试HSSFCell.ENCODING_COMPRESSED_UNICODE。 <BR><BR>编译后将对应.class放到WEB-INF/classes相应目录就可以了。 <BR><BR>pdf view的比较麻烦，还没尝试，解决方法参照这个帖子： <BR><A href="http://extremecomponents.org/forum/viewtopic.php?t=139&amp;highlight=chinese+filter" target=_blank>http://extremecomponents.org/forum/viewtopic.php?t=139&amp;highlight=chinese+filter</A> <BR><A href="http://www-128.ibm.com/developerworks/cn/xml/x-ospdf/index.html" target=_blank>http://www-128.ibm.com/developerworks/cn/xml/x-ospdf/index.html</A> <BR><BR>还有一小点： <BR>升级到1.0.1-M4-A14以后两个图片改名了，如果用1.0.1-M3的对应gif则需要该如下两个文件名（我修改的那个ZH-CN已经重命名过了）： <BR>searchArrow.gif -&gt; filterArrow.gif <BR>search.gif -&gt; filter.gif <BR><BR>说的比较罗嗦，主要是想让和我一样的非常初级水平的朋友能够比较容易上手。其实eXtremeComponent的文档很不错，用那个上手其实更好，我仅抛砖引玉，各位大牛多多包涵。<BR><BR>下面是补充上的如何让PDF View支持中文，这个需要点耐心。<BR><SPAN class=postbody>我是在WindowsXP里面（这个涉及到文件夹和所带的字体）。 <BR><BR>1、解开fop-0.20.5.jar，启用cmd，并到它的目录中，执行： <BR>
<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"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #000000">java&nbsp;org.apache.fop.fonts.apps.TTFReader&nbsp;-ttcname&nbsp;"SimSun"&nbsp;C:\WINDOWS\Fonts\simsun.ttc&nbsp;simsun.xml&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>java&nbsp;org.apache.fop.fonts.apps.TTFReader&nbsp;-ttcname&nbsp;SimHei&nbsp;C:\WINDOWS\Fonts\simhei.ttf&nbsp;simhei.xml&nbsp;</SPAN></DIV><BR>2、然后就会生成需要的两个字体描述文件：simsun.xml、simhei.xml <BR>我们将我们生成的两个xml文件和它们对应的字体simsun.ttc和simhei.ttf存储到我们的Web项目的WEB-INF/fonts下面。 <BR>3、然后在我们的src目录（目的是要被部署到WEB-INF/classes目录，也有可能是/src/conf，看你的工程的设定）创建一个名为fop-pdf-userconfig.xml的文件，内容如下：</SPAN> <BR>
<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"><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top><SPAN style="COLOR: #0000ff">&lt;?</SPAN><SPAN style="COLOR: #ff00ff">xml&nbsp;version="1.0"&nbsp;encoding="UTF-8"</SPAN><SPAN style="COLOR: #0000ff">?&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">configuration</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">fonts</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font&nbsp;</SPAN><SPAN style="COLOR: #ff0000">metrics-file</SPAN><SPAN style="COLOR: #0000ff">="@@@@@@@@@@fonts/simsun.xml"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;embed-file</SPAN><SPAN style="COLOR: #0000ff">="@@@@@@@@@@fonts/simsun.ttc"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;kerning</SPAN><SPAN style="COLOR: #0000ff">="yes"</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimSun"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimSun"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="bold"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimSun"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="italic"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimSun"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="italic"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="bold"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">font</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font&nbsp;</SPAN><SPAN style="COLOR: #ff0000">metrics-file</SPAN><SPAN style="COLOR: #0000ff">="@@@@@@@@@@fonts/simhei.xml"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;embed-file</SPAN><SPAN style="COLOR: #0000ff">="@@@@@@@@@@fonts/simhei.ttf"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;kerning</SPAN><SPAN style="COLOR: #0000ff">="yes"</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimHei"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimHei"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="bold"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimHei"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="italic"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="normal"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;</SPAN><SPAN style="COLOR: #800000">font-triplet&nbsp;</SPAN><SPAN style="COLOR: #ff0000">name</SPAN><SPAN style="COLOR: #0000ff">="SimHei"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;style</SPAN><SPAN style="COLOR: #0000ff">="italic"</SPAN><SPAN style="COLOR: #ff0000">&nbsp;weight</SPAN><SPAN style="COLOR: #0000ff">="bold"</SPAN><SPAN style="COLOR: #0000ff">/&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top>&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">font</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">fonts</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/None.gif" align=top></SPAN><SPAN style="COLOR: #0000ff">&lt;/</SPAN><SPAN style="COLOR: #800000">configuration</SPAN><SPAN style="COLOR: #0000ff">&gt;</SPAN></DIV><BR><SPAN class=postbody>注意，其中有“@@@@@@@@@@”，因为我的实现方法很丑陋，我后面的代码中将“@@@@@@@@@@”替换为你部署后运行的路径，目的是字体文件等能够跟工程一同部署，减少固定字体等文件的麻烦。 <BR>4、对extremeComponent的代码，我又修改了两处： <BR>其一，对于org.extremecomponents.table.view.PdfView修改： <BR>将其中出现&lt;fo:block的地方全部添加font-family=\"SimSun,SimHei\"。 <BR>然后double colwidth = 10 / columnCount;中的10修改为20，此处修改使中文字符不会堆积在一起。 <BR>我还将上面的sb.append(" page-width=\"11in\" ");修改为sb.append(" page-width=\"22in\" ");，这样对于中文比较宽大的报表可以显示完全，不过这个要自己把握。 <BR><BR>其二，修改org.extremecomponents.table.filter.PdfViewResolver： <BR>我在driver.run();前面增加如下一段代码： <BR>
<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"><IMG id=Codehighlighter1_4_1360_Open_Image onclick="this.style.display='none'; Codehighlighter1_4_1360_Open_Text.style.display='none'; Codehighlighter1_4_1360_Closed_Image.style.display='inline'; Codehighlighter1_4_1360_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_4_1360_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_4_1360_Closed_Text.style.display='none'; Codehighlighter1_4_1360_Open_Image.style.display='inline'; Codehighlighter1_4_1360_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top><SPAN style="COLOR: #0000ff">try</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN id=Codehighlighter1_4_1360_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_4_1360_Open_Text><SPAN style="COLOR: #000000">{&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ClassLoader&nbsp;loader&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;Thread.currentThread().getContextClassLoader();&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;URL&nbsp;url&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;loader.getResource(&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">/org/extremecomponents/table/filter/PdfViewResolver.class</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">get&nbsp;the&nbsp;class's&nbsp;working&nbsp;folder&nbsp;</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;classPathUrl&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;url.toExternalForm();&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;fileRoot&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;classPathUrl.substring(</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;classPathUrl.lastIndexOf(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">WEB-INF</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">));&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileRoot&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(fileRoot.substring(</SPAN><SPAN style="COLOR: #000000">6</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN style="COLOR: #000000">+</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">WEB-INF/</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);&nbsp;</SPAN><SPAN style="COLOR: #008000">//</SPAN><SPAN style="COLOR: #008000">cut&nbsp;the&nbsp;"file:/"&nbsp;prefix&nbsp;</SPAN><SPAN style="COLOR: #008000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top></SPAN><SPAN style="COLOR: #000000"><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InputStream&nbsp;opis&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;loader.getResourceAsStream(&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">fop-pdf-userconfig.xml</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;StringBuffer&nbsp;tempConfigurationStrBuf&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;StringBuffer();&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[]&nbsp;buffer&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">byte</SPAN><SPAN style="COLOR: #000000">[</SPAN><SPAN style="COLOR: #000000">4096</SPAN><SPAN style="COLOR: #000000">];&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">int</SPAN><SPAN style="COLOR: #000000">&nbsp;len;&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG id=Codehighlighter1_811_934_Open_Image onclick="this.style.display='none'; Codehighlighter1_811_934_Open_Text.style.display='none'; Codehighlighter1_811_934_Closed_Image.style.display='inline'; Codehighlighter1_811_934_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><IMG id=Codehighlighter1_811_934_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_811_934_Closed_Text.style.display='none'; Codehighlighter1_811_934_Open_Image.style.display='inline'; Codehighlighter1_811_934_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000">&nbsp;((len&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;opis.read(buffer))&nbsp;</SPAN><SPAN style="COLOR: #000000">!=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">-</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)&nbsp;</SPAN><SPAN id=Codehighlighter1_811_934_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_811_934_Open_Text><SPAN style="COLOR: #000000">{&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;s&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;String(buffer,&nbsp;</SPAN><SPAN style="COLOR: #000000">0</SPAN><SPAN style="COLOR: #000000">,&nbsp;len);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;tempConfigurationStrBuf.append(s);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000">&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;configurationStr&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;tempConfigurationStrBuf.toString();&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;configurationStr&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;configurationStr.replaceAll(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">@@@@@@@@@@</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fileRoot);&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top><BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ByteArrayInputStream&nbsp;bais&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ByteArrayInputStream(configurationStr.getBytes());&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;org.apache.fop.apps.Options&nbsp;options&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;org.apache.fop.apps.Options();&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options.loadUserconfiguration(bais);&nbsp;<BR><IMG id=Codehighlighter1_1386_1432_Open_Image onclick="this.style.display='none'; Codehighlighter1_1386_1432_Open_Text.style.display='none'; Codehighlighter1_1386_1432_Closed_Image.style.display='inline'; Codehighlighter1_1386_1432_Closed_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align=top><IMG id=Codehighlighter1_1386_1432_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_1386_1432_Closed_Text.style.display='none'; Codehighlighter1_1386_1432_Open_Image.style.display='inline'; Codehighlighter1_1386_1432_Open_Text.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">catch</SPAN><SPAN style="COLOR: #000000">&nbsp;(FOPException&nbsp;fe)&nbsp;</SPAN><SPAN id=Codehighlighter1_1386_1432_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"><IMG src="http://www.blogjava.net/images/dot.gif"></SPAN><SPAN id=Codehighlighter1_1386_1432_Open_Text><SPAN style="COLOR: #000000">{&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fe.printStackTrace();&nbsp;<BR><IMG src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></SPAN></DIV><BR></SPAN><SPAN class=postbody>大家可以抨击代码的丑陋，呵呵，不过还好it works。代码很丑陋，本来想咨询raimundo的，他正好忙，所以畸形了，如果朋友们有其它好方法可以一同改进。 <BR>不过要注意，我替换的/org/extremecomponents/table/filter/PdfViewResolver.class是放到WEB-INF/classes文件夹的，如果您将它替换到jar包里面，则上面内容还需要修改一下，我没有测试，但是估计也不麻烦的。 <BR><BR>至此，最基本的解决Pdf export的方法就写好了。可是正好看到差沙已经早些放出了他的修改，明显比我这个优雅，但是他的修改无法将fonts里面的内容自动部署并检查目录，大家可以合并一下代码，相信会更好一点。回去好好学习差沙分享的代码，大家一同学习。 <BR><BR>相关代码打包在这里：<BR><A href="http://tiny.51.net/extremecomponent/ec_pdf_chfix.rar">http://tiny.51.net/extremecomponent/ec_pdf_chfix.rar</A><BR><BR>本解决方案参考了本贴： <BR><A href="http://extremecomponents.org/forum/viewtopic.php?t=139&amp;highlight=chinese+filter" target=_blank>http://extremecomponents.org/forum/viewtopic.php?t=139&amp;highlight=chinese+filter</A></SPAN> <BR><BR>这是我在JavaEye的一篇帖子，转到我的Blog上来。</SPAN><img src ="http://www.blogjava.net/iamtin/aggbug/31097.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/iamtin/" target="_blank">Tin</a> 2006-02-16 21:10 <a href="http://www.blogjava.net/iamtin/archive/2006/02/16/31097.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>