webwork 2.2 中如何给Collection赋值

原本javaeye有这么一篇帖子“在WebWork2 Action中如何自动设置Array、List、Map”,是moxie大哥写的。
http://forum.javaeye.com/viewtopic.php?t=8770

但是已经是2004年11月的文章了,在webwork 2.2 b4中,XWorkList和XWorkMap已经是deprecated状态了,当时我就一头雾水,也没找到什么好的线索。
去java.net下载了XWork的最新代码,看到了其中的注释,说这个工作已经可以自动完成了。
又几经周折,才算搞明白先在如何让List、Map等工作起来:

下面简单介绍一下:
1、如果要将值映射到pojo的collection,则需要使用conversion功能。
如我又一个Action,叫testAction:
public class testAction extends ActionSupport {
 private Collection smoeAttrs = null;(使用webwork自动负值,应有对应getter和setter)
 private IDeptJgzTjkEcoAttDAO ecoAttDAO = null;(改DAO使用Spring注入,应有相应setter)

     public String execute() throws Exception {
         if (log.isDebugEnabled()) {
   log.debug("performing execute() method!");
         }

  //持久化collection里面的pojo
  for (Iterator iterator = smoeAttrs.iterator(); iterator.hasNext();) {
              SomeAttr someAttr = (SomeAttr) iterator.next();
              ecoAttDAO.saveOrUpdate(someAttr, someAttr.getId());
         }

         return Action.SUCCESS;
     }
}

对应一个pojo:
package org.tin.test;

public class SomeAttr implements Serializable {

 /** The composite primary key value. */
 private java.lang.Long id;

 private java.lang.Float fild1;
 private java.lang.String fild2;
 private java.util.Date fild3;

 /*
  ….
  对应的getter和setter
 */
}

可以看到,上面的Action声明的时候没有任何涉及到XWorkList的地方(moxie介绍的那种风格),也就是说现在webwork并不知道Collection里面放的pojo的类型。这就是Webwork目前的高明之处,这样的代码非常干净。但是如果要自动设定Collection的值,访问到这些Pojo,则一定要知道Pojo的类型,Webwork如何做呢?
通过-conversion配置。
需要在对应该才那个testAction.java的相同目录写一个testAction-conversion.properties文件(格式就是Action名字+“-conversion.properties”)。
文件里面注明:
Element_someAttrs = org.tin.test.SomeAttr (以前版本曾经用过Collection、Map分开,但是现在不管什么类型,都用Element)
格式就是“Element_”+Action中Collection的名字+“=”+你的pojo的完整类名

如此配置后,自动设置值的时候就可以知道你的pojo的类型了,很干净。

下面一小段由于我接触Webwork不久,所以是个很初级的经验,如果需要则自取:
回忆moxie帖子中的重要的部分,在post到相应action的页面的form中,input要遵循这样的命名:
对应刚才所说的那个pojo:
<form>
 <input  name="someAttrs[0].fild1" value="45555.6" id="xxx11" />
 <input  name="someAttrs[0].fild2" value="test" id="xxx12" />
 <input  name="someAttrs[0].fild3" value="2006-01-05" id="xxx13" />
 <input  name="someAttrs[1].fild1" value="45555.6" id="xxx21" />
 <input  name="someAttrs[1].fild2" value="test" id="xxx22" />
 <input  name="someAttrs[1].fild3" value="2006-01-05" id="xxx23" />
 <input  name="someAttrs[2].fild1" value="45555.6" id="xxx31" />
 <input  name="someAttrs[2].fild2" value="test" id="xxx32" />
 <input  name="someAttrs[2].fild3" value="2006-01-05" id="xxx33" />
</form>

如何输出?很简单,在列表页中:
<ww:iterator value="someAttrs" status="someAttrsIter">
<tr>
 <td>
  <ww:hidden name="someAttrs[%{#someAttrsIter.index}].id" value="%{id}"/>
  <ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild1" value="%{fild1}"/></td>
 <td><ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild2 value="%{fild2}"/></td>
 <td><ww:textfield name="someAttrs[%{#someAttrsIter.index}].fild3" value="%{fild3}"/></td>
</tr>
</ww:iterator>

即可以,因为iteratror这个tag支持iteratroStatus这个东西,用它可以获取index、isOdd等信息,很方便。

配合
<action name="saveAction" class="testAction">
 <result name="success" type="redirect">/loadByInf.action?id=${someAttrOwner.id}</result>
</action>

则很容易的实现对Collection的CRUD。正好用到了ONGL的集中基本访问方式:#、%{}、${}

以上内容,错漏难免。因为今天终于可以偷闲,赶紧结绳记之。欢迎大家讨论更简便的方法。

Webwork 2.2 b5中datapicker的本地化使用方法

仅作为记录,尽量简明:
1、我使用Weblogic 8.1 SP5+Webwork 2.2 beta 5。2.2b5的Webwork已经完全转向使用jscalendar作为datapicker的js,而不是以前的tigracalendar,因为tigracalendar不支持国际化。Web项目使用FilterDispatcher,本应改可以将/webwork/*的请求拦截下来,但是它工做不正常。所以我把webwork.jar里面的\com\opensymphony\webwork\static目录拷贝到Web根目录,并将static目录重名名为webwork。
此时,你的Web根目录下面应有一个名为webwork的目录,里面有jscalendar、dojo、niftycorners这几个文件加,如果不需要其它的,可以只保留jscalendar一个目录。
2、在需要显示datapicker的地方使用如下标记<ww:datepicker name="ecoInf.turninDate" id="ecoInf.turninDate" template="datepicker.ftl" language="cn_utf8" format="%Y-%m-%d %H:%M:%S" showstime="true" />。
其中template完全可以不写。而name标明你的数据的来源。id是方便javascript访问所保留的,可以和name相同(如果有重复name,如经过iterator,则需要区别其id,保持id在html dom中唯一)。
showstime标明是否可以选择时间,可以是"true","false","24","12"。
language决定jscalendar使用的语言,参照下面说明。
3、language指定的语言其实就对应jscalendar/lang下面的语言文件,格式就是calendar-语言名.js,默认的中文使用的是zh。但是其实j2ee项目经常面对中文乱码问题,最佳解决方案就是统一使用UTF-8。但是calendar-zh.js正好不是UTF-8的,所以如果直接使用zh语言则datapicker没法正常工作。
我的解决方法是将webwork附带的jscalendar 1.0的lang里面的cn_utf8.js改名为calendar-cn_utf8.js,然后将language="cn_utf8"就工作正常了。
4、关于时间的显示格式。其实cn_utf8.js里面已经制定了时间的标准显示格式是%Y-%m-%d,符合我们的习惯。但是有时我们需要显示具体时间,参照他们网站的说明,使用format="%Y-%m-%d %H:%M:%S",这个也符合我们的习惯。
发个牢骚:
本来奇简单。但是很奇怪/webwork/*居然不能在Weblogic下自动映射,我一会而去试验下Tomcat,还有就是js解析utf-8出错造成整个js没法工作,浪费了半天时间,唉。

eXtremeComponent在中文环境下的使用

不知道大家是否使用过eXtremeComponent,我刚才在java eye没有搜索到。
最早知道eXtremeComponent是从www.open-open.com,去年就在用了,感觉明显比display-tag要好用多了。
它使用jstl,所以与webwork集成也很方便,不象display-tag那样需要把hibernate返回的collection复制一遍再访问。

具体的使用方法参考官方网站好了:
官方网站在这里:
http://www.extremecomponents.org/extremesite/welcome.jsp
最新的版本是1.0.1-M4-A14,可以到这里下载:
http://www.extremecomponents.org/extremesite/public/download/
或者直接下载:
http://www.extremecomponents.org/extremesite/public/download/extremecomponents-1.0.1-M4-A14.zip
但是这个snapshot版本没有依赖lib和资源文件等,推荐去这里下一个完整版本备用,目前最新的Production Release包是eXtremeComponents-1.0.1-M3-with-dependencies.zip:
https://sourceforge.net/project/showfiles.php?group_id=108168
最新版本的说明书在这里,说明书用的doc book格式,写的也很清楚:
http://www.extremecomponents.org/extremesite/public/download/eXtremeComponents.pdf
很多人都对他使用的doc book声称doc感兴趣,spring和hibernate都用doc book,可是一般看不到源文件。作者很慷慨将doc book的源文件也分享了,是学习是学习使用doc book的好东西:
http://www.extremecomponents.org/extremesite/public/download/generate-docs.zip

资源就贴到这里,这里要提及作者Jeff Johnston人非常热情,论坛上四处可见他的身影,给他发信他也是每信必会、有求必应,承蒙他多次帮助。而且论坛中大家多次提及中文问题,他也很重视。

转入正题:
我贴一下一个例子:
 <ec:table
 items="ecoAttrs"
 action="/jgz/tjk/eco/listTjkAttByInfId.action"
 imagePath="${pageContext.request.contextPath}/css/table/zh_CN/*.gif"
 cellpadding="1"
 title="农村经济运行情况列表"
 locale="zh_CN"
 rowsDisplayed="30">
  <ec:export view="xls" fileName="jgz_zyjjzbwcqk.xls" tooltip="输出Excel文件"/>
  <ec:exportPdf fileName="jgz_zyjjzbwcqk.pdf" tooltip="输出PDF文件" headerColor="blue" headerBackgroundColor="red" headerTitle="密云县农村经济月份经济主要指标完成情况表"/>
  <ec:exportCsv fileName="jgz_zyjjzbwcqk.txt" tooltip="输出CSV文件" delimiter="|"/>
  <ec:row>
   <ec:column property="ofTown.name" title="乡镇名称"/>
   <ec:column property="ncJihua" title="农村计划"/>
   <ec:column property="ncWancheng" title="农村完成"/>
   <ec:column property="ncQunian" title="农村去年"/>
   <ec:column property="zongShouRuWCJH" title="完成计划%"/>
   <ec:column property="zongShouRuTB" title="同比+/-%"/>
  </ec:row>
 </ec:table>

其中ecoAttrs是一个collection,放入pojo。action里面写你这个页面的访问方法(如我的页面是一个action,其他的如.do或者.jsp什么的都可以)。rowsDisplayed是默认显示条数,它可以自动实现分页。
下面的三个<ec:export>是导出三种格式用的,不用的话可以不写(写了需要在web.xml配置相应的filter)。
<ec:column>里面放属性,property指向pojo的相应属性,而title是表头显示的信息,这个标签需要用<ec:row>包起来(1.0.1 m4以后)(抱歉pojo比较丑,出自同事之手)。

这里放一套我做的中文图标:
http://tiny.51.net/extremecomponent/zh_CN.rar
还有我该写了一下css,更适合使用中文,将字体该为%大小,可以定义.eXtremeTable里面的font-size,即影响所有eXtremeTable里面的字体大小,也方便写js来动态修改大小:
http://tiny.51.net/extremecomponent/extremecomponents.css

贴一下我在web.xml里面的配置:
<filter>
 <filter-name>eXtremeExport</filter-name>
 <filter-class>
  org.extremecomponents.table.filter.ExportFilter
 </filter-class>
</filter>

<filter-mapping>
 <filter-name>eXtremeExport</filter-name>
 <url-pattern>/*</url-pattern>
</filter-mapping>

<taglib>
 <taglib-uri>/extremecomponents</taglib-uri>
 <taglib-location>/WEB-INF/tld/extremecomponents.tld</taglib-location><!– 别忘了把那个tld拷贝到相应目录去 –>
</taglib>

其实,那个filter只是在使用<ec:export>的时候才需要,不过这个功能还是很有用的。

export里面的excel和pdf默认不支持中文,需要手工修改源码,excel的比较简单:
修改org.extremecomponents.table.view.XlsView.java(我指的是1.0.1-M4-A14的相应代码)
102行:
HSSFCell hssfCell = hssfRow.createCell(cellnum);
hssfCell.setEncoding(HSSFCell.ENCODING_UTF_16);(就是添加这一行)
122行:
HSSFCell cell = row.createCell(cellnum);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);(就是添加这一行)
这个在使用UTF-8时工作正常。如果其他Unicode环境可以尝试HSSFCell.ENCODING_COMPRESSED_UNICODE。

编译后将对应.class放到WEB-INF/classes相应目录就可以了。

pdf view的比较麻烦,还没尝试,解决方法参照这个帖子:
http://extremecomponents.org/forum/viewtopic.php?t=139&highlight=chinese+filter
http://www-128.ibm.com/developerworks/cn/xml/x-ospdf/index.html

还有一小点:
升级到1.0.1-M4-A14以后两个图片改名了,如果用1.0.1-M3的对应gif则需要该如下两个文件名(我修改的那个ZH-CN已经重命名过了):
searchArrow.gif -> filterArrow.gif
search.gif -> filter.gif

说的比较罗嗦,主要是想让和我一样的非常初级水平的朋友能够比较容易上手。其实eXtremeComponent的文档很不错,用那个上手其实更好,我仅抛砖引玉,各位大虾多多包涵。

新年,2005总结再见,欢迎2006来临!

2005年是我的本命年,其间很多事情发生了改变,人生收获颇多。所以,这里几个流水账,自勉。

 1、年初和期末考试作斗争,并且成功全过。这门过后我的学分基本修够,减少了下个学期的专业课学习压力,是个成功。

 2、第四次冲击6级。靠,我个人非常清楚英语的重要性,所以一直注意实际阅读、听的能力,但是六级的应试能力不佳。幸好zz帮助我,给我找了些真题,而且教导我要向过6级就好好做真题。结果顺利通过,真是喜出望外。今年是老版6级最后一年了,算是赶上这个末班车了。谢谢zz。

3、陪zz准备北京公务员考试,本来说陪她考的,可是由于时效问题,没有真正陪她,也没有好好帮她复习。她没过。这是个失败,明年要陪她冲击。

4、学校第二学期开始,开始一段比较自由的学习。我开始认真地读《程序员杂志》,为自己从硬件兴趣型到软件专业型的转换做准备。经验是,不管如何要专业。

5、和小梁合作的jsp的电子商城项目被我们强行终结,幸好将我们将货款收回。这个项目我们从去年9月做到今年3月,成本亏了是肯定的,但是让我从一个asp程序员转型为jsp程序员,真正了解脚本是什么。呵呵,我的asp还是2年前在玩票,现在的jsp让我慢慢往后了解server可以如何运作。这里不多说了。但是这真的是个正式的算钱的项目,体会了软件工程,学习了如何分工协调,从我的搭档身上也学到了很多,我的学习能力在这个项目上迅速提升。

6、做了几个网站,包括给小叔公司代理telecobriges,还有大学同学的《厅长小武》,还有一个Moshiwig假发。基本上是设计型的,分别对PSD切片、xhtml+w3c等进行了更多的尝试。

7、五月和zz去青岛旅游,太高兴了,充满无数美好回忆!所以明年还要继续选择一个目的地去旅游。

8、进行二级实践课程,认识了几个好朋友,与他们的共事使我真正进入Java Web开发的阵营,并且用心的体验了什么是轻量J2EE开发,真正认识了Spring、Struts、Hibernate,几乎是一夜间我就成为了一个Javaer。

9、上了软件心理学,并认真思考了一下UI设计的问题。虽然没有上升到学术高度,但是确实认真思考了这方面的问题,感觉很有收获。

10、开始研究什么是架构,什么样的需求需要什么样的架构。多次和LBBZH讨论过这些问题,感觉收获巨大,他是个好朋友,以后还要多向他学习。

11、开始用业余时间在混乱的开源项目中体验不同的思路,从而可以在简历中说熟悉了一大堆的框架、工具等等。发现开源社区的意义,并尽量做些贡献(eXtremeComponents、参与翻译Pro Spring等)。这种感觉是快乐充实的。

12、协助一个朋友忙开网吧的事,并出差山东一次。虽然时间不长,但这种只身去陌生地方的经验是第一次,男人需要成长呀。

13、今年第一次自己找了个工作。得到了一个朋友的帮助。工作了不到两个月,平生第一次正式的领到工资。虽然在单位没有发挥自己的全部实力,但是还是认真地做事,可惜单位的职位还是不太适合我,我需要一个空间让我自由发挥。但是单位的同事都是朋友拉。谢谢丸子!

14、今年也第一次尝试了辞职。仅仅工作了两个月就被朋友召唤走了,心里没有一丝依恋。因为新的环境会很自由!辞职的流程还是比较长经验的,哈哈。

15、和朋友组成Team去密云做工程,我的职位是系统架构师。非常惭愧,其实不配这个称号。但是被人家吹捧的感觉还是不错的,谢谢你们的善意欺骗,我会努力成为真正的master的。

16、终于有足够的money陪zz逛街了,很爽。尤其是可以不假思索的说“拿下”,看zz惊讶的笑脸,满足啊。男人就应该这样,明年继续。

17、我和zz终于走到一个里程碑,我们已经计划好,她已经同意嫁给我了。具体的计划还在筹划,这是我人生中的重大决定呀。

18、今年花了很大的心思给zz准备生日礼物。她非常满意。男人应该尽到他的心意。zz,我喜欢给你画画。

19、今年在硬件上。我花eShop工程和小武等工程的钱买了个Dell 1704FPT LCD,并且通过我的努力将有坏点的显示器换成了一个完美的8ms板的。当然1704颜色一般,准备以后换个好的。后来入手了Logitech G5和MX510两个鼠标,键盘变成了Dell 8135。其余的新鲜东西没啥了。

20、年底送给zz一个iPod nano黑色。原先跟她说她并没有感兴趣,但是送她以后她却被它迷住了。她超级喜欢这个礼物,个人认为这礼物是我的杰作。同时送了iDog小狗一直,完全满足我家zz的爱好!

21、由LBBZH推荐加入了BJUG,参与了几次活动,受益匪浅。对各位大牛真地是佩服得五体投地,并且也迅速找到了自己的不足。更加认真地扎入到java这个阵营中了!学习了更多的框架,理解也比以前深刻了,明年还要继续跟进。

22、今年丢了一次钱包,卡没有使用强密码,损失了800元。还好先前花980买了个Meizu E5 512MB Mp3,它给我带来了很多的音乐享受,也让我少丢了另外800元钱。明年要涨记性,多注意防贼!

23、我的三星X108丢失在青岛的崂山风景区,具体丢失过程不明,但是以后还是要多家小心。 好了,23是我的幸运数字,不继续写了。

可以说2005年是我到现在的人生经历中收获最大的一年。学习平稳到了一个收获期,成功转型,成功潜入Java开发阵营并站稳脚,感情稳定并得到认可,经济状况明显好转,性格也成熟了很多,我真的从一个男孩成为一个准男人了。明年的目标就是更男人!要更男人就是为了要扛起我的父母和爱人。期待2006,一定要比2005更加充实。

Spring 2.0和给贫血模型充血

Spring 2.0 vs. the Anemic Domain Model
原来是因为老马骂了贫血模型为反模式,说冲血模型才是最好的,能够真正的OO。
不过Spring 2.0的概念被骂了个体无完肤。
本身,我的立场从来就没有站在OO这一边,我是真的无所谓的人,什么过程、OO、FP我都很认同,当然能优雅些是最好的。
看了以后就想到WQH前两天就已经推荐给我的ajoo写的充血模型的问题,我才意识到QH大师又走在我们前头了!
看了下javaeye上贫血/充血的讨论,才豁然开朗。
知道为什么冲突就对了。关键点还是在争吵OO,而OO在领域模型方面有时适合充血有时适合贫血,当然贫血居多,所以举起例子总是两边倒,没有定论。
还好,抽出重要部分,对于基本CRUD,那么绝对是贫血模型就好了。而对于有复杂计算的领域模型,我们要建立一个完备的OO的领域模型则需要充血。
这提醒了我们,充血的确是需要的。不过给Hibernate下的POJO(明显贫血到死)充血并不容易,所以才有了更多的文章讨论这个问题。
记录下来,大家有兴趣一起研究:
TSS:Spring 2.0 vs. the Anemic Domain Model
http://www.theserverside.com/news/thread.tss?thread_id=38047
Javaeye论坛:贫血就贫血,咂地?
http://www.hibernate.org.cn/viewtopic.php?p=100045&sid=df2163b2c94afbb6b214da6b3be42d73
ajoo在javaeye的conflunce上写的:怎样给马丁的充血域对象注射依赖
ajoo一文的后篇:http://www.javaeye.com/display/ajoo/Dependency+Injection+For+Rich+Domain+Model
对程序员透明的非aop方法解决rich domain object的依赖注射
http://www.javaeye.com/display/ajoo/Transparent+Dependency+Injection+For+Rich+Domain+Model
Codehaus上的一个解决方案:Dependency Injection For Rich Domain Objects
http://docs.codehaus.org/display/YAN/Dependency+Injection+For+Rich+Domain+Objects
老马写的批评贫血模型的檄文:AnemicDomainModel
http://www.martinfowler.com/bliki/AnemicDomainModel.html
Spring Blog上的原文:Spring 2.0 vs. the Anemic Domain Model
http://jroller.com/page/habuma?entry=spring_2_0_vs_the
我个人认为POJO还有DTO都是简单的VO,而VO就是VO,要区别于Real Object。我们的domain里面大都是VO而不是RO。Hibernate也是基于VO的,EJB3同样。所以RO应该说是理想OO下的东西,我们真正要用的时候,还是可以自己选择是否要实现这种复杂的东西的。但是不用RO则我们的程序就变得过程化。所以老马也认为这是头疼的事,但又不要解决,只能放到他的TODO list里面了,哈哈。
哈哈,但是看完Spring的那个Blog,感觉Spring 2.0做好了解决多向以来的模型的方法是很不错的,当然是由解决给贫血模型充血引发的,但是我认为它还能解决其它问题,所以感觉不错。但是Spring 2.0再次强调Aop的好处,也的确能看到,所以有时间还要学习一下AspectJ。
而这个问题ajoo说了IoC和Aop都可以解决,感觉各有道理。IoC方式感觉代码容易读懂,也合理。而Aop则代码有点牵强,当然使用起来感觉很爽,尤其和Lazy-init结合,对生存周期的控制有它读到的地方,而且想明白了用Aop+Annotation感觉也很清楚优雅。

非常完美的一天!

早晨,刚刚睁眼听到妈妈说7:05了。昨晚和ZZ说好了今天8:00去她家找她。所以麻利的起来穿好衣服,洗漱干净背上书包冲出家门。爱人的召唤吸引着我,脚步十分轻快。
和每个找她的周末的早晨一样,习惯性的期望13路正好经过,因为搭乘13是去她家的最佳车辆。作为完美一天开始的信号,我看到十三路从远方开来,并且面前是个绿灯,可以马上过马路到车站。快步冲过人行道,我与车一同停下,上车,心情很愉快!
我在锣鼓巷倒车,换乘115路。下车继续用我喜欢的节奏快步前行,到了115路总站发现刚好就要发车,小跑几步上了车,还坐在我最喜欢的皇帝位上。皇帝位就是最后一排最中间的那个坐,视野广阔,可以面对整个过道,拥有清晰的视野是让人心情轻快的事。
8:05分,我已经在ZZ家楼下。天太冷了,我走到ZZ家的楼道中,此时她已经收到了我到达的讯号,因为我听到她家的门被打开又被关上的声音,多么熟悉呀,说明我家宝贝已经就要下来了。
然后就是蹦蹦跳跳的下楼的声音,我迎上去,我家ZZ看来很高兴,她在看着我开心你的笑。我抱起她,一直到楼下。
按我们的计划上午有个健身的活动,我们搭车去了KFC,吃些早餐。要了咖啡和麦香猪柳蛋的组合。这个选择很英明,芝士ZZ很喜欢,而蛋的口感很顺华,猪柳则明显调和了清淡的口味,配合在一起就能给我们满足的感觉。然后就是期待中的一小段运动时间,现在健身已经是我们生活中的一个重要节目了,因为现在的生活节奏的确需要这种节目来缓解,边运动边聊天。
ZZ说昨晚吃的太少了,尽早就很饿,刚才的早餐其实大部分被我干掉了……ZZ说要计划一下中午吃什么,她想吃好的。
什么叫说曹操曹操就到?在完美的一天一定要有这样的巧合才对。就在我们计划吃什么的时候收到了姐姐发来的短信,问我们在哪里。嘿嘿,姐姐周末的短信就是说要有饭局了。
正好中午要去国展家乐福,就应了姐姐……中午去吃汉拿山,上次就说请姐姐吃的,正好也是ZZ的最爱之一。而我正好是无肉不欢的人,当然乐意的不得了!
饭局定在12:00。我和ZZ先去国展家乐福,这里的特点就是物种极大丰富,我们并不喜欢这里火车般的长队,但是喜欢到这里发现没见过的食物,这种感觉有点像在逛博物馆。
由于时间仓促,我们主要流连于西餐区,因为ZZ总想给我做pasta吃,前一天其实我们已经来过,不过还没有过瘾,我们继续寻找各种pasta的佐料(昨天已经买了通心粉和番茄肉酱),真的很好玩。很快接到电话,二姐的车到了。
我们两个迅速跑出去了,活像两个企鹅,哈哈,摇摇晃晃跑过过街天桥。
去吃汉拿山了。可爱的明明没来,哥哥点的菜。这里的牛扒还是那么好吃,让人感觉幸福呀。腐败的过程不赘述,吃完以后我们来到安贞华联。
ZZ想要兰寇的so magic香水,可惜这里没有兰寇。然后我们逛啊逛,终于逛到了海盗船,那天答应送她一个新耳环。其实她扎了耳朵眼没几天,现在还没好利落呢,前几天送她了一对耳钉,她还想要环。
到了店里,她在挑……我用眼扫了一下,发现一对比较闪亮的,好像在呼唤我。我推荐给ZZ,她一下就喊道:“太漂亮了!”然后她也环视了一下,马上肯定我选到的是最漂亮的,然后说我要买下它。
我非常干脆利落的让小姐开票并去付账了,这是我最近练出的本事,做男人给女朋友花钱一定要买单不眨眼不犹豫,说实话也没什么犹豫的,我喜欢她闪亮亮的。
回来的时候她已经把耳环换好了,看着她闪动着满意的眼神,我心里十分的满足,嘎嘎嘎!
然后继续逛,卖首饰的柜台真多,不过没怎么看到更好看的。所以说是完美的一天,因为想要的东西马上就可以找到!
我们继续逛,她给我指了很多毛衣,可能我很想给她买东西,并没有看到什么让我眼前一亮的毛衣。我现在也变挑剔了,因为要让她有面子我也要打扮得潇洒一些,前年这个时候我可不会逛商场买衣服,但是现在,逛商场感觉就像在自己家里一样。
下了楼,本来要回家了,看到国美电器了。她想起要买个卷发棒,其实去年她就要求过我,可是看到的都太低档了,所以还没出手。
进去以后,很快选定了德国伟嘉的3合1卷发棒,我坚持要送给她!她欣然接受,我很满足,嘻嘻。
然后过了马路,718很快到站,然后又很快有坐。到了家里,有香喷喷的牛肉面等我们爽呀!
爽呀!爽呀!爽呀!爽呀!
真的很满足,因为很完美,我们已经找到了应该收集到的所有快乐碎片,下一步就是步入婚姻殿堂了,她也欣然接受,我就要订婚了,当然日程还没有订!
所以,这是需要纪念的一天!
2005年12月11日!

关于事务的满脑袋酱子,解惑:本地、JTA、CMT

传统上J2EE有两种事务管理策略:全局或者本地事务
全局的由app server保证,如JTA。而本地则是针对某种资源的,如JDBC连接的事务。
其中,全局事务是为了保证多种事务资源的共同工作。但是如果是用本地的事务,则容器(app server)无法保证跨资源的事务。
JTA是一种全局的事务。但是JTA是笨重的,且JTA的事务一般需要通过JNDI获得,所以JNDI和JTA一般联用。而且JTA代码一般不能跨App server,会受限于某种特定的容器。
所以更好的方式是使用EJB CMT(Container Managed Transaction),它的特点是使用声明性事务,而不是编码事务管理。
所以,虽然EJB天然结合了JNDI,但是并不受限于容器(声明性)。
但是CMT又依赖于JTA和App server环境(或者说支持EJB的App server,Tomcat这些Servlet容器就不行啦)。所以这种事务如果依赖于EJB或者EJB的装饰封装则要花不少资本投资App server(不是钱也至少要人,如JBoss)。
但是,我们还有更好的选择,如Spring,或者很多Aop实现,EJB3等等。
而本地的事务策略虽然实现容易,但是缺点显著。它不能在多资源间实现事务支持,并且这种事务对变成模型的侵入也很大(传统JDBC事务使用起来就是这样)。而且如JDBC连接也不能与其他JTA事务协同被管理。如你的JDBC和某个其它事务绑定(如两个JDBC Connection)起来,如果遇到一个失败你如何将两个rollback?(这个是我自己演绎的)
下面是广告:
Spring解决了这个问题。它提供了一个持续的模型,可以应用在大多数环境。也就是说你可以灵活的更换它支持的各种事务策略(你也可以自己扩展)。而且Spring两种方式的事务都支持(声明/编码),当然Spring推荐使用声明的(侵入小,灵活)。

MB,本来写了不少体会,结果倒霉没有保存,如果有时间我再考虑一下是否重写吧,损失惨重!

我不再让你孤单

很少去KaraOK的,但是每次去的时候都回唱这首歌。
因为我实际唱得出的歌没有那么几首,这首很久之前我就非常喜欢,就好像是我自己要说的话。现在我很喜欢给她唱这首歌,因为看着她的脸唱这首深情的歌,就好像在念一首诗。
在她的朋友面前唱过这首歌,看着我唱歌时他们投降她的羡慕的目光,我心里也是暖暖的,因为这本就是应该献给你的——我最爱的宝贝!
她经常夸奖我大声唱时很感人,她说我唱的很好听。也许我不优雅的嗓子适合唱陈升这种Blackguard的歌吧。
甜蜜的时间是没有尽头的,当然这需要学会Free,虽然我不Free,但很大的时间我却可以体会到那种甜蜜,简单的满足。
所以,当今天我在一词听这首歌的时候,哼起它:
让我轻轻的吻着你的脸
擦干你伤心的眼泪
让你知道 在孤单的时候
还有一个我 陪着你
让我轻轻的对着你歌唱
像是吹在草原上的风
只想静静听你呼吸
紧紧拥抱你 到天明
路遥远 我们一起走
我要飞翔在你每个彩色的梦中
陪着你
我从遥远的地方来看你
要说许多的故事给你听
我最喜欢看你胡乱说话的模样 逗我笑
尽管有天我们会变老
老得可能都模糊了眼睛
但是我要写出人间最美丽的歌 送给你
路遥远 我们一起走
我要飞翔在你每个彩色的梦中
对你说 我爱你
WOO……
我不再让你孤单 我的风霜你的单纯
我不再让你孤单 一起走到地老天荒
我不再让你孤单 我的疯狂你的天真
我不再让你孤单 一起走到地老天荒
路遥远 路遥远
我不再让你孤单
所以,宝贝,我不再让你孤单!

实验Webwork2.2与Spring的Auto-wire (2)

太长了,这是下半部分。

我做了一下小实验,以Webwork2的样例程序为例:

原先只在xwork.xml总进行了配置,Spring配置中无该bean

<action

name="main" class="com.opensymphony.webwork.example.ajax.actions.ActiveCategory">

<result name="success">/category-main.jsp</result>

</action>

1、 使用byType方式:这个没什么可说,只要类一样自动就可以匹配,并使用。

添加了Spring中的配置:

<bean id="main_action"

class="com.opensymphony.webwork.example.ajax.actions.ActiveCategory"

singleton="false" />

2、 使用byName方式:在Spring中配置id=”xxx”,然后再xwork中配置name=”xxx”,可以自动匹配,可以使用。

修改了Spring配置如下:

<bean id="main"

class="com.opensymphony.webwork.example.ajax.actions.ActiveCategory"

singleton="false" />

3、 然后删除xwork.xml配置中的class=”com.xxx.xxx”class=””,依然可以工作。

修改了xwork.xml配置如下:

<action name="main" class="">

<result name="success">/category-main.jsp</result>

</action>

4、 然后再实验使用Springbeanname属性进行匹配,依然工作正常。

修改了Spring配置如下:

<bean id="main1" name="main"

class="com.opensymphony.webwork.example.ajax.actions.ActiveCategory"

singleton="false" />

所以,看起来nameid都可以用来auto-wire,所以id如果可以区分,用它来auto-wire就可以了,比较方便。

不过我个人有个疑问,在Spring中声明action是否要生明singleton=”false”?按理说应该false吧,可是我看例子中都没有声明。我记得Spring默认是singleton=”true”的,这是为什么?