实验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”的,这是为什么?

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

前几天看到BJUG的朋友说最近大家都不写技术Blog了,我实在是没看什么东西,今天正好要搞Webwork2+Spring,体验了一下新版本的集成,做了点翻译,还顺道作了点小实验。

基于Spring 1.2.5 + Webwork 2.2 Beta3

1、中文参考是飞云小侠的——《WebWork2.2中结合Spring:"新的方式"》:

http://www.jscud.com/srun/news/viewhtml/4_2005_9/134.htm

2、英文参考是WebworkConflunce上的文章(不好意思,基本上是翻译这篇文章):

Enabling Spring Integration

http://wiki.opensymphony.com/display/WW/Spring

3Other Spring Integration

http://wiki.opensymphony.com/display/WW/Other+Spring+Integration

其中:

webwork.properties中通过这条设置打开SpringObjectFactory

webwork.objectFactory = spring

而修改autoWire的工作方式则通过这个设置:

webwork.objectFactory.spring.autoWire = type

autoWire其实就是webwork寻找Spring已经创建的bean的方式,有如下四种方式可以设置:

name

通过对Spring中的beanname与你程序中的actionname属性进行匹配。系统默认使用这种方式(如果不写上面那句的话)。

type

通过在Spring中注册的bean中寻找与你程序中的actionname相同的属性来匹配。这需要保证Spring中一个类只能注册一次(即不允许部同名但同类的Spring配置)

auto

Spring试图自动检查最好的Auto-wire方式。

constructor

Spring会根据constructor的参数来匹配action。(webwork这里没有作更多说明,根据Spring的规则,这种方式应该与type类似,只不过这里不是匹配setter,而是匹配constuctor的参数。)

其实,看看Spring的相关书籍,其实这就是Spring的四种Auto-wire方式,分别对应:byNamebyTypeautodetectconstructor。可以参考Pro Spring的第4章的内容“Auto-Wireing Your Beans”。

然后说明了一下方式,配置了auto-wire以后每次都回试图通过Spring来匹配对象实例。如果Spring没有创建这个Bean,那么Webwork会自己创建它。同时,要在web.xml中注册SpringLisener来打开这个功能:

<listener>

<listener-class>

org.springframework.web.context.ContextLoaderListener

</listener-class>

</listener>

这里Webwork提出了一个提示:需要更多的ApplicationContext配置文件么?

如果使用了Spring的标准Listener来结合,那么可以除了aaplicationContext.xml还配置多个xml配置文件。可以通过下面的配置来实现,需要加到web.xml里面。

<!– Context Configuration locations for Spring XML files –>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>

/WEB-INF/applicationContext-*.xml

/WEB-INF/spring-daos.xml

/WEB-INF/spring-actions.xml

</param-value>

</context-param>

这个可以参考Spring文档。

Spring中的配置样例

这里,你可以添加标准的Spring配置文件,在WEB-INF/applicationContext.xml。下面是一个例子:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans default-autowire="autodetect">

<bean id="personManager" class="com.acme.PersonManager"/>

</beans>

从使用内建IoC转移到使用Spring

转移很容易。Spring的配置就如上所述。完成融合,你需要:

1、 将你的components的配置从components.xml适当转移到applicationContext.xml。然后就可以安全的删除components.xml了。

2、 xwork.xml的拦截器栈(interceptor stack)中移除Component Interceptor。虽然不移除也无伤大雅,但是留下它已经是个冗余了。

Session ScopeSpring

Spring目前不支持session scoped components。不过计划在Spring 1.3 release中整合该功能。现在,你必须使用Spring Session Componnets Workarounds

Spring中初始化Actions

一般,xwork.xml指明了每个Actions的具体类。当使用SpringObjectFacotry(如上面配置的过程),意味着将通过Spring来创建action,然后来组装(wire)他们之间的依赖,根据设定的auto-wire行为。SpringObjectFactory将会应用所有的预处理工作,例如代理你的action的事物(transactions)、安全(security)、等等。这样不需要明确配置,Spring会自动装配它们。大部分应用中,这就是你所要做的全部工作,使你的actions的服务和依赖关系被执行。

我们强烈建议使用声明的方式来让Spring知道你的actions之间的依赖。这包括自动的装配具有相同的name的属性和bean(就是指byNameAuto-wring),或者byTypeAutowire(这种情况下一个类型只能在Spring中注册一次)。或者还可以使用JDK5种的annotations来声明事物或者安全的配置,而不是通过applicationContext.xml,这样你就不需要在所有配置文件来维护它们了。

然而,有时你想让bean通过Spring自动管理。这很有用,例如,如果你想配置复杂的AOP或者Spring支持的技术到beans上,例如Acegi。这样,你需要将所有的配置写到applicationContext.xml里面,然后改变WebWork action中的class属性,使之与Spring中的bean name定义相同,代替原来使用的真实类名。

你的xwork.xml文件中的class属性会改变,就像下面这样:

<!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.0//EN" "http://www.opensymphony.com/xwork/xwork-1.1.dtd">

<xwork>

<include file="webwork-default.xml"/>

<package name="default" extends="webwork-default">

<action name="foo" class="com.acme.Foo">

<result>foo.ftl</result>

</action>

</package>

<package name="secure" namespace="/secure" extends="default">

<action name="bar" class="bar">

<result>bar.ftl</result>

</action>

</package>

</xwork>

这里,你的SpringapplicationContext.xml中有一个名为“bar”的bean。注意com.acme.Foo这个action不需要修改属性,它会自动autowire的。

记住:这不是必须的。这只在这种情况才必须,你希望覆盖掉已经在Webwork中创建的action,并且需要通过Spring支持但不能自动实决定的拦截器和IoC来装饰它的时候。记住,WebworkSpring继承只是标准的IoC,使用你指定的任何auto-wiring,甚至即使你没有显示的在Spring中映射action。所以一般来说你不需要这样做,但是如果需要的时候你最好知道这是如何实现的。

这段说的不太清楚,可能我翻译的不好。但是我理解它的意思是,可以不用修改class的名字,因为不修改它也会自动应用SpringAOP和其它IoC功能,当然是根据auto-wire的匹配。但是如果需要特别的确定要从Spring中装饰后再使用这个action,那么可以把class的属性修改掉。

全球最具影响力富豪名单公布 Google新贵上榜

北京时间10月9日,英国《金融时报》选出年度全球最具影响力富豪名单,除金钱外,这二十五名富豪的行为、思想及工作方式,都影响了人们的生活。微软主席盖茨蝉联冠军,长和系主席李嘉诚跻身第二十五位。

  1.盖茨(Bill Gates) 49岁

  微软主席 510亿美元

  2.乔布斯(Steve Jobs) 50岁

  苹果电脑行政总裁 30亿美元

  3.奥米耶(Pierre Omidyar) 38岁

  eBay创办人及主席 100亿美元

  4.布林(Sergey Brin)及佩奇(Larry Page) 32岁

  Google创办人 每人110亿美元

  5.默多克(Rupert Murdoch) 74岁

  新闻集团主席兼行政总裁 67亿美元

  6.米高彭博(Michael Bloomberg) 63岁

  彭博财经通讯创办人兼纽约市长 50亿美元

  7.贝鲁斯科尼(Silvio Berlusconi) 69岁

  Fininvest传媒集团创办人兼意大利总理 120亿美元

  8.索罗斯(George Soros) 75岁

  对冲基金经理 72亿美元

  9.Carlos Slim Helu 65岁

  墨西哥电讯界巨头 238亿美元

  10.Azim Premji 60岁

  印度软件公司Wipro主席 93亿美元

  11.米塔尔(Lakshmi Mittal) 55岁

  米塔尔钢铁公司主席 250亿美元

  12.巴菲特(Warren Buffett) 75岁

  Berkshire Hathaway主席、股神 440亿美元

  13.Richard Mellon Scaife 73岁

  美国出版人及右翼政治捐献者 12亿美元

  14.他信(Thaksin Shinawatra) 56岁

  泰国总理 13亿美元

  15.摩尔(Gordon Moore) 76岁

  英特尔荣誉主席 46亿美元

  16.阿布拉莫域(Roman Abramovich) 38岁

  俄罗斯石油大亨兼英超球队车路士班主 133亿美元

  17.特纳(Ted Turner) 66岁

  传媒巨子及慈善家 20亿美元

  18.Bernard Arnault 56岁

  LVMH集团主席及行政总裁 170亿美元

  19.德摩尔(John de Mol) 50岁

  荷兰电视制作人 20亿美元

  20.埃里森(Larry Ellison) 61岁

  甲骨文创办人及行政总裁 170亿美元

  21.戴尔 40岁

  戴尔电脑公司主席 180亿美元

  22.坎普拉德(Ingvar Kamprad) 79岁

  宜家家俬创办人 230亿美元

  23.李健熙 63岁

  三星集团主席 43亿美元

  24.普拉特纳(Hasso Plattner) 61岁

  SAP创办人 50亿美元

  25.李嘉诚 77岁

  长和系主席 130亿美元

来源:新浪

Java有些时候太Free了,也许这种左倾会成为麻烦,所以RoR之风又刮回来了,但是RoR其实也是个右派

恩,十一旅游回来,我们的单位在搬家,不得安宁。
今天抽空看了RoR中的表关系映射(many to one、one to many),使用has_one、belongs_to这样的限定,使用find_all等等那种RoR风格的自动反射的方法,真的很接近于自然语言,轻松舒适,非常优雅,而且节省时间。不过在改写我们的Level2项目的时候,发现需要改造的地方还是很多的,就是因为RoR的这个“约定优于配置”(Convention Over Configuration)的思想,很多地方我们都要手动制造遵从与约定的设计。比如Dish与Dishsort如果要映射,那么Dish里面就要有dishsort_id这样的字段,而不是dishtype……类似的情况很多。我的感想就是,如果系统是纯RoR实现,从头设计,那么用RoR会非常方便,而且可以得到震撼的结果。但是如果是遗留系统修改,或者是混合系统的开发,那么很多时候你就会感觉到约定带来的束缚是多么的不舒服。当初Java和.Net吵闹的时候就有很多JavaUser认为ASP.net里面的约定不爽……所以,我们只能说,Java有些时候太自由了,也许这种左倾会成为麻烦,所以RoR之风又刮回来了,但是RoR其实也是个右派。
真希望我们能走自己的路,自由欢快!

BTW:看看那个Free,中文的这个词还是个禁句,MSN真可怜,被GFW了。

我靠,太郁闷了,Struts这破玩意儿!

1、倒霉的Mysql-front,UTF-8支持太烂!!!!!!!
我这里凡是有中文的行,任何更新都回出错。以前是某些有中文的出错,看来中文支持肯定有问题。而且它的出错提示是德语的,真晕!!!
而且出错以后会奇怪的跳出新窗口,不停,必须用TaskManager关掉它。
我用phpMyAdmin就没有任何问题,很好用。
下午看看这个Mysql-front还有没有救药,如果不行就彻底抛弃。
2、我恨死Struts的ActionForm了!!!!!!!!
昨天我还只是觉得这个东西脱了裤子放屁,多此一举的利害。但是心想不过是浪费一些代码而已。
不过今天我继续发现,这个东西简直就是个隐藏的炸弹。
我本来没有在ActionForm里面写log做记录。心想如果里面发生了exception会抱错,因为我没有写try catch。但是后来我调试一个Action怎么都搞不定,明明在Action里面写了log,却怎么也不输出,我是异常郁闷!
大约浪费了两个小时后,我才明白,我这个Action调用了这个ActionForm,而ActionForm如果property匹配发生错误不会抱错的,也就是说如果那个request里面没有那个property它就会默认为null,而不报错。检查只发生在validate()方法,而这个方法非常恶心,如果发生了错误它会返回input的page,而不会报任何错误!(当然它存了ActionError在session)但是我却在log系统看不到,而且没有exception。就造成了程序中的一个黑洞,我什么都看不到。
而且ActionForm和input Page里面的html:text….那些标记的名称匹配非常费时,根本就不自动化,全部售动写非常容易出错,而且出错还有隐蔽性(没有的peroperty会null,前面说了),而又不能把所有null都到validate()检测,因为有些属性允许null,所以……
我快被ActionForm搞疯了!
所以,我越来越觉得Webwork2中那种Action和Model在一起的方式非常优秀,而且它使用了ongl,model的属性和前端页面通过命名规则自动绑定,省事多了。
所以,可以这么说,费了九牛二虎之力,ActionForm只能浪费时间和精力(Struts本意是使验证变得方便,容易测试),并且实际上测试起来非常困难,绝对是糟粕。记得有人说,既然Struts所有东西里都传了request、session这些东西,那么完全可以舍弃ActionForm,而把数据初始化写到Action里,如xxx=request.getParameter("xxx"),就和JSP里的Scriptlet一个样子,哈哈,不过这样Struts就不再是Struts了,只有形式了。如果伪需求要求必须用Struts,我们可以绕过(不用ActionForm,用request),或者小心点用。所以反过来说就是,我不想用这样的残废了。

关于MVC框架的一个好讨论

http://forum.hibernate.org.cn/viewtopic.php?t=6947&postdays=0&postorder=asc&start=0&sid=19cfb9f49ed6092478ad38654751f38c
叫做struts和webwork双体验。
这里讨论的非常好。
虽然很长,但是值得认真看,里面讨论了很多MVC的核心问题,让框架一下子便得扁平了,那些复杂的东西其实不过是非常简单的概念。你也就理解了Struts的思想,还有Webwork的思想,以及他们的优缺点。不过本贴似乎都比较偏向于Webwork2。

不过说句公道话,ActionForm的确烂,写得恶心。Webwork那种Model-Driven真是看其来简单,而且Xwork有是IoC,还支持AOP(Inteceptor),所以我也希望摆脱Webwork。而转观Tapestry,虽然我以前评价过这个东西的view层非常有特点,但是Tapestry后面的东西还是非常丑陋的(Tape3后面很复杂,而Tape4用了HiveMind以后更复杂),而且Tapestry这个东西有严重的Apache通病,自己家东西杂烩,还特别乱七八糟的,代码一塌糊涂……

所以,看完这篇评论,你会非常清楚Struts应该怎么用可以避开它的弱点。
还有,坚定了由时间一定要学习Webwork2的信念。很多人说懂了Struts,学会Webwork2只需要一个下午

关于Hibernate,小发现

写login的时候记录login time。
结果遇到一大堆麻烦,搞了半天找不到问题所在。
然后把log4j里面的debug打开,发现还是捕捉不到exception然而tx却rollback了。
仔细看代码,发现在UserLoginAction里面catch(Exception e)然后做了log就结束了,忘记e.printStrackTrace()了,加上。然后发现了两个很严重的问题!

1、我跟踪了Hibernate的SQL,它里面的SQL的临时命名后面都加了“_”,这个东西造成我们的Domain的所有id在update时不管用,也就是说涉及存储和修改时,只有insert可以,因为这个时候的id是自动生成的,否则只要set Domain里面的id就会出错。
后来仔细察看,发现Mysql的字段名里面最好不要有“ _ ”,字符,否则Hibernate就会出问题。报告“could not execute query; bad SQL grammar”。解决方法就是把字段里面的“ _ ”去掉,比如我把user表里面的user_id改成了userid。
问题就解决了。2、解决了上面的问题还是有问题。我们的Manager的update方法不能用。会报告session里面不能有两个相同id的domain对象。
我写了个UnitTest却可以update。所以感觉很奇怪。
后来看到这里的解释:http://www.matrix.org.cn/thread.shtml?topicId=25286&forumId=23
搞明白了问题。因为我们有UserAuthenticationManager,它里面会检查登陆用户的个人信息。而我在LoginAction的生命周期中UserAuthenticationManager一直处于激活状态,所以Hibernate的session也一直打开,而LoginAction里面再调用UserManager的update方法保存时就会出现session中调出两个同id的Domain对象的情况,Hibernate就会报错,然后rollback……
正好那里有解决方法,用merge方法就不会在SaveorUpdate的时候检查冲突对象了,问题就解决了。

所以希望大家注意:
1、把目前数据库中的_id这样的命名修改为xxxid这样的命名。
2、大家写的DAO中涉及到update操作的地方请使用getHibernateTemplate().merge()方法。

Web2.0,说馒头是面包

前几天听说……
我不跟风的,喜欢视那些xx作为浮云……
今天本意再讨论Ajax和方法论,看到了个介绍,从技术上:
WikiPedia的Web 2.0条目下列出了这些条件:

* CSS 和语义相关的 XHTML 标记

* AJAX 技术

* Syndication of data in RSS/ATOM

* Aggregation of RSS/ATOM data

* 简洁而有意义的 URLs

* 支持发布为 weblog

* RESTian (preferred) 或者 XML Webservice APIs

* 一些社会性网络元素

嘿嘿,其实大家都注意到了,这些技术我们也在上手和使用中了,所以,看来没有那么可怕啦

有幸再次见到Michael Chen

昨天有幸再次见到Michael Chen,他这个人真的很平实。
他说,我这个东西不是想做个框架,就是想提供一个客户端的异步通讯的工具。
看了这篇文章,更加加深了我对他的认同,他也认为应用决定使用什么技术,Ajax再火,在目前的xmlhttp+javascript的不完全可靠实现下也只能用在一写改善用户体验的小地方,全局的应用只不过是被技术冲昏了头脑。
我昨天和郑浩也在讨论同样的问题,我们都同意两个重要的标准:
1、技术要改变用户体验。如更好、更快捷、更清晰。这是一种功能指标。
2、技术要带来性能的提升,或者硬件的节省。因为性能我们觉得是技术的重要评价指标。当然首先要保证稳定。
而现在更多看到戴着幽雅帽子的编程技术,总是充斥着复用的话题,但是说实话,感觉真正的复用太少了,更多的是一种技术狂热,或者Open狂热。
所以我想用一个名词形容他们,“OpenMania”,开源综合症,中间还是有不少可怕的狂热症状的,不过郑浩说的很好,患了此症的人都是好人,而且是大好人。

这是闲话。
上午花了些时间把buffalo的js给精简了一下,成果不算很明显:
buffalo.js(12,007Byte) ->> buffalo_shrink.js(8,725byte)
xmlcallback.js(3,732Byte) ->> xmlcallback_shrink.js(2,785byte)

等测试完毕发给Michael Chen。
要这么想,接近缩小了1/3,也就是说带宽可以……我已经OpenMania了

JavaServer Faces对决Tapestry

JavaServer Faces对决Tapestry
面对面的对比
作者:Phil Zoio 发布于The Server Side
原链接:
http://www.theserverside.com/articles/article.tss?l=JSFTapestry
本人翻译了其中一小部分,如果侵犯版权请通知我,谢谢。
很有趣,里面提出是一种实现(Hibernate、Spring)更能推动产业呢?还是一个标准(JSR)呢?很难回答。
Tapestry的分离方式非常优雅,后来被很多其它实现所参照,但Tapestry是做的最好的。你甚至可以用Dreamweaver来写模版,这对于那种美工不懂JSP、JAVA的团队非常有效,静态的预览也很容易。
而JSF对于组件化的推动是非常有效的,派生了很多好的页面组件,这是非常好的重用思想。比如IBM就把JSF和SDO结合,产生的东西绝对令人印象深刻(在加上Ajax实现)。
本文开头说明Struts作为一个MVC实现已经有点越发老迈了,日落西山是早晚的事。而新一代的MVC,象Web Work那些都是更佳的实践。不过JSF和Tapestry提出的上面两个优雅的解决对表现层更加友好,所以要对比一下。
文中对比了Tepestry 3.0.3和JSF 1.1。大家注意Tapestry 4已经进入beta阶段,而且变化是翻天覆地的,里面也提及了一些。
文章很长,看起来还是有点累的。不过比起学习两个技术,看看这种文章对你学习之前是个很好的指导。
标准1:页面开发
Tapestry的可融入标准HTML的能力区别于其它框架,是最有价值的功能。
标准2:Java编程模型
JSF为创建程序类提供了直观且具有弹性的编程模型,相对于Tapestry中一些奇怪的设置要自由得多。
标准3:请求(Request)处理生命周期
JSF更容易访问,而Tapestry的方式更适合于复杂的需求,它允许人们为需求中的单独操作定制生命周期。
标准4:导航
两个框架都有怪癖;作者偏向于Tapestry的基于编码的方式来导航。
标准5:事件处理
JSF受益于值变化事件监听器。对于Tapestry,当事件处理逻辑是逐个页面设定的,这个生命周期事件处理模型会更适合。而JSF更适合于对整个系统整体设定的生命周期事件处理。
标准6:组件状态管理
Tapestry有效的组件状态管理机制,使人们对它的能力和适用范围有足够的信心。对于不需要高性能的程序,重绕(rewind,Tepestry的一个毛病)问题是你愿意摆脱的。
标准7:标准组件
Tapestry提供了领先的标准组件集,而JSF得益于大量的第三方组件。
标准8:组件开发
在Tepestry中进行自定义组件开发相对容易于JSF。
标准9:验证和转换
JSF在概念上占有优势。但是Tapestry在客户端验证支持上挽回了弱势,它具有更加的错误管理机制,和更多的系统外验证的实现。
标准10:国际化
Tepestry的优势在于紧凑的格式,而且它的国际化页面可以进行预览。
标准11:可测试性
相对少的框架依赖使在JSF中进行受控bean单元测试比Tepestry页面类单元测试更加容易。
标准12:开发者获得的效率提升
由于工具的愈发面面俱到和易于使用,JSF的开发效率可以得到提升。对于那些喜欢以代码为中心的开发者,Tapestry可能会更有效率。
标准13:易于学习
JSF框架对于一般开发者更容易上手,虽然Tapestry中的模版创建很容易上手(但是它的学习曲线更难,资料也不全,且正在从3升级到4,有翻天覆地的变化)。
标准14:业界支持
JSF是个工业标准,所以受到广泛的业界支持,他更容易吸引IT经理人和开发者。(里面说JSF会慢慢好找工作,当然Struts还是最大需求。而Tapestry估计不会作为招聘要求的技能。)
标准15:可扩展性
JSF提供了比Tapestry 3更加优雅的扩展机制。Tapestry 4会很大程度上改进框架的这种能力。