关于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会很大程度上改进框架的这种能力。

CSS中的一些有用技术

1、滑动门技术
我这次也用到这个技术了,其实是一种互相折叠的技术,我已经使用过很多了。
这篇文章中介绍了如何在标签中使用滑动门技术,这个很有用,而且效果不错。
2、对于需要把传统html4.0转到css+xhtml的人,这篇文章很好。
一种简单的对照关系,可以让你把表格布局放到标准的css布局上面来,其实并不费力的。
不过要记住不要滥用float,否则会死的很惨。position:absolute有时也是不错的选择。
捷足先登学用CSS:HTML结构化
3、关于圆角容器
div标签很多时候类似个矩形容器,大家很爱用它。用它实现圆角容器可以让你的网页变得美观生动。
不过问题在于圆角容器会带来大量的嵌套div,不优雅。
为了优雅,可以使用javascript+dom来解决,哈哈,很不错的。
我的简历就使用了自己制作的圆角容器,自己修改javascript很好玩的,使用的东西不难看懂。后面那个网站很不错,456 Berea Street很多人都推荐。
Rounded Corners with CSS and JavaScript
Transparent custom corners and borders | 456 Berea Street
4、IE欺骗技术中的一个简单应用
圆角容器的css使用的一个解决IE对png支持不好的办法,记下来,很有用的。不过目前不知道怎么在css文件里面使用这个hack。里面的代码只对IE其作用,可以弥补IE对Web Standards支持不好的一些问题。
<!–[if lt IE 7]>
<style type="text/css">
/* Serve gif images to IE/Win pre version 7 */
.i1,
.i2 { background-image:url(css/borders.gif); }
.bt,
.bt div,
.bb,
.bb div { background-image:url(css/box.gif); }
/* Set a height to fix up some rendering issues. */
.i1,
.i3 { height:1px; }
</style>
<![endif]–>
5、关于控制框架宽度的方法
本来觉得Chinaren校友录论坛里面可以自动收缩的框架不错。可是后来发现在Firefox不能用。找了很多地方不能解决。结果闲逛的时候发现了解决方法。
框架页如下:
<FRAMESET id="_bodyframeset" rows="38,*" frameSpacing="0" frameBorder="NO">
 <FRAME id="top" src="top.htm" scrolling="no" target="body">
 <FRAMESET id="main" name="main" cols="200,9,*" frameSpacing="0" frameBorder="NO">
  <FRAME name="left" src="left.htm" scrolling="auto" target="body">
  <FRAME name="control" src="control.htm" scrolling="no">
  <FRAME name="body" id="body" src="userlist.htm" scrolling="yes">
 </FRAMESET>
</FRAMESET>
在control中的加入如下javascript函数,调用它可以自动收缩:
function shift_status()
{
 flag = !flag;
 if(flag)
 {
  if(screen.width>1024)
   window.top.document.getElementById("main").cols="200,9,*";
  else if(screen.width>800) 
   window.top.document.getElementById("main").cols="200,9,*";
  else
   window.top.document.getElementById("main").cols="160,9,*";
  GEId("menuSwitch1").src=’images/ej1_30.gif’;
  GEId("menuSwitch1").title=’隐藏’;
 }
 else
 {
  window.top.document.getElementById("main").cols="0,9,*";
  GEId("menuSwitch1").src=’images/ej1_32a.gif’;
  GEId("menuSwitch1").title=’显示’;
 }
}
原来框架页可以动过window访问到,然后就可以通过id访问它的子页面了,哈哈。不过这种Dom解析的说明网上也找不到很好的,查起来非常不方便。谁有好的资源可以告诉我。
6、一个在IE和Firefox都可以工作的灰度隐藏的Js
我了解到Firefox支持了Opcity,可以实现IE私有的filter里面的透明度的设置,所以修改了一下以前的一段js,让两个浏览器都可以实现类似的效果。不过目前在ff上没有渐变的效果,还需要改进。
<script language="javascript">
function high(which){
theobject=which
which.style.opacity=1
highlighting=setInterval("highlightit(theobject)",50)
}
function low(which){
which.style.opacity=0.25
clearInterval(highlighting)
which.filters.alpha.opacity=25
}
function highlightit(that){
if (that.filters.alpha.opacity<100){
that.filters.alpha.opacity+=10
}
else if (window.highlighting)
clearInterval(highlighting)
}
</script>
本文如果需要转载,请和我本人联系,未经同意不得专用,谢谢。

说说Displaytag


继续在Open-open.com逛,看到排名很靠前的一个java taglib项目。因为一直觉得taglib没产生什么有意义的东西,只不过是规范化了很多,看到排名靠前的taglib挺奇怪,就仔细看了看。
发现原来是个表格组件。前一段时间看讲座对Dorado那个界面比较感兴趣,使用了Ajax和组件化的表格技术,数据对象通过Javascript+dom解析,类似IBM的SDO概念。觉得如果能够真正的弄好,这种可服用的表格组件非常有前途。
当然SDO已经在IBM的JSF组件里面应用了,帮定起来真的很方便,而且客户端的体验也非常的好。可是JSF的最大缺陷就是手动开发太麻烦了,培植非常繁琐,所以就依赖于IDE来自动实现JSF组件的配置,所以JSF的IDE都是由背景的,代表某一方利益的东西。比如SUN的NetBeans、IBM的那个什么5.1,而我喜欢用的Eclipse下面还没有很好的辅助IDE,Nitrox新版支持JSF了,可是没有破解,正版又老贵,Myeclipse 4.0支持了JSF,但看了看很初级。
撤了老远,其实我想说我对这种实现的很Fine的组建太感兴趣了。
马上去它的网站看:
http://displaytag.sourceforge.net/
首页的几张截图非常吸引人,它产生的表格看起来非常的棒!
听Open-open介绍,这个东西和Struts结合很顺畅,我们的项目用的Struts+Hibernate+Spring,马上加进来试验。
遇上问题,session里面的变量访问不到,很奇怪,这个东西难住我了,找不到问题。看了它们的PDF,本以为会比网站讲得详细,后来发现不过就是网站的内容的PDF版本,基本也就是个入门指南,可怜。
网站总提到TestList这个东西用来测试,找不到这个类,下了它的源码,发现在源码的例子中有,产生测试List。
然后就用这个TestList测试了一下分页、排序、导出其它格式这些功能,发现非常吸引人,一下子觉得发现了宝藏!
然后不管是否能在我们项目应用,开始修改css,把它弄到我们的项目里,然后问项目其它同仁为何不能显示出我们的List。
修改Css很顺手,嘿嘿,目前我改css已经驾轻就熟了,很快修改出自己的漂亮的样式,很满足,哈哈。
而后,我的朋友郑浩发现了不能显示的问题,因为我们用了Hibernate,它返回的List是离线的,访问的时候需要用iterator访问,可能Displaytag的机制问题,所以无法访问到。
解决方法是每次new一个新的List,复制一遍再过去。我考!这是多大的浪费呀。把它放到DAO是不可以的,这样DAO移植后绝对是浪费,把它放到bussiness层也不合理,放到MVC的Controller还差不多,但是也感觉浪费的利害。
这时有些失望,所以去Google下,发现无数人说到这个问题。尤其是使用它的自动分页,每次如果取出所有的,然后复制List,估计性能会彻底完蛋!
所以,有些失望,Displaytag最有用的功能aotopagging不能使用了……
为了做试验,进一步修改,不用它的自动分页,但是修改了MVC,让它可以访问到一个复制过的List,来显示数据。配合刚才修改的css,效果和以前的Struts tag不相上下。(靠,完全是写css的缘故,这个有什么兴奋的!)
它的表格的控制都是英文的,应该可以中文。然后google,和问郑浩,他们用了如下代码:
<display:table name="list" width="100%" cellspacing="0" cellpadding="0" class="liebiao" pagesize="15">
 <display:setProperty name="basic.msg.empty_list">没有可显示的内容</display:setProperty>
 <display:setProperty name="paging.banner.placement">bottom</display:setProperty>
 <display:setProperty name="paging.banner.full"><span class="liebiao">[<a href="{1}">首页</a>/ <a href="{2}">前一页</a>] {0} [ <a href="{3}">下一页</a>/ <a href="{4}">最后一页 </a>]</span></display:setProperty>
 <display:setProperty name="paging.banner.first"><span class="liebiao">[首页/前一页] {0} [<a href="{3}">下一页</a> <a href="{4}">最后一页</a>]</span></display:setProperty>
 <display:setProperty name="paging.banner.all_items_found"><span class="liebiao"><br><br>本栏目共{0}条,已经全部列出</span></display:setProperty>
  <display:setProperty name="paging.banner.onepage"><span></span></display:setProperty>
 <display:setProperty name="paging.banner.one_item_found"><span class="liebiao">共一条,已经列出</span></display:setProperty>
 <display:setProperty name="paging.banner.last"><span class="liebiao">[<a href="{1}">首页</a>/ <a href="{2}">前一页</a>] {0} [下一页/最后一页]</span></display:setProperty>
 <display:setProperty name="paging.banner.some_items_found"><span class="liebiao"><br><br>共有{0}条,显示第{2}至{3}条<br></span></display:setProperty>
 <display:setProperty name="paging.banner.page.link"><a href="{1}" title="前往第{0}页">{0}</a></display:setProperty>
 <display:column property="title" title="标 题"  href="detail.jsp" paramId="id" paramProperty="id" maxLength="10" width="40%" align="left"/>
 <display:column property="reportername" title="作者" maxLength="4" width="20%" align="left"/>
 <display:column property="readtimes" title="阅读次数" align="left"/>
 <display:column property="newsdate" decorator="cn.gov.bjmy.util.SimpleDateDecorator" title="新闻日期" width="16%" align="left"/>
</display:table>

哈哈,这么用真的够累。不过想了想,在中小项目,利用它的自动分页还是不错的。
不过每次设置太麻烦了,查阅了下,1.0版本支持用displaytag.properties配置了,这样可以全局使用。
displaytag.properties的内容如下:(那些中文我已经转码了,使用了PropertiesEditor,这个Eclipse插件自动转码非常方便!)
basic.msg.empty_list=\u6ca1\u6709\u53ef\u663e\u793a\u7684\u5185\u5bb9
paging.banner.placement=bottom
paging.banner.full=<div class="pagelinks">[<a href="{1}">\u9996\u9875</a>/ <a href="{2}">\u524d\u4e00\u9875</a>] {0} [ <a href="{3}">\u4e0b\u4e00\u9875</a>/ <a href="{4}">\u6700\u540e\u4e00\u9875 </a>]</div>
paging.banner.first=<div class="pagelinks">[\u9996\u9875/\u524d\u4e00\u9875] {0} [<a href="{3}">\u4e0b\u4e00\u9875</a> <a href="{4}">\u6700\u540e\u4e00\u9875</a>]</div>
paging.banner.all_items_found=<div class="pagebanner"><br><br>\u672c\u680f\u76ee\u5171{0}\u6761\uff0c\u5df2\u7ecf\u5168\u90e8\u5217\
u51fa</div>
paging.banner.onepage=<div class="pagelinks">{0}</div>
paging.banner.one_item_found=<div class="pagebanner">\u5171\u4e00\u6761\uff0c\u5df2\u7ecf\u5217\u51fa</div>
paging.banner.last=<div class="pagelinks">[<a href="{1}">\u9996\u9875</a>/ <a href="{2}">\u524d\u4e00\u9875</a>] {0} [\u4e0b\u4e00\u9875/\u6700\u540e\u4e00\u9875]</div>
paging.banner.some_items_found=<div class="pagebanner">\u5171\u6709{0}\u6761\uff0c\u663e\u793a\u7b2c{2}\u81f3{3}\u6761</div>
paging.banner.page.link=<a href="{1}" title="\u524d\u5f80\u7b2c{0}\u9875">{0}</a>
export.banner=<div class="exportlinks">\u5bfc\u51fa\u4e3a\u5176\u5b83\u683c\u5f0f: {0}</div>
export.pdf=true
export.csv=false
把这个文件放到Web项目的Class目录下就可以了。解决了问题了。
用了下导出功能,支持pdf需要把itext-0.99.jar拷贝到WEB-INF/lib下面,然后再propertis配置中“export.pdf=true”。
不过发现这个用不了,后来发现原来是无法解析Struts的.do,我都是映射到/去的,而我的jsp文件不在/下面,所以路径出了问题。查了下,用这个参数指定,“requestURI="getUser.do?back=yes"”就可以了,里面是我用的struts的action的路径。
修改以后,自动排序和导出都正常了,不过发现导出csv的时候后缀是.do,靠,禁用它。(BTW:集图的时候天天CSV,哈哈,别的地方估计不常用吧。怀念COC,现在BOB却很少去)
下面是全部可运行的一个代码:
<display:table name="tablecontent" class="<%=lClass%>" defaultsort="1"
 defaultorder="descending" export="true"
 requestURI="getUser.do?back=yes">
 <display:column property="userId" title="ID" sortable="true"
  headerClass="sortable" />
 <display:column property="name" sortable="true" headerClass="sortable" />
 <display:column property="realname" />
 <display:column property="password" sortable="true"
  headerClass="sortable" />
 <display:column property="addr" title="Comments" />
</display:table>
对比一下Struts下面的相同代码:
<logic:iterate name="users" id="userlist" scope="session">
  <tr>
   <td class="frh"><bean:write name="userlist" property="userId"
    filter="true" /></td>
   <td class="fr"><bean:write name="userlist" property="name"
    filter="true" /></td>
   <td class="frh"><bean:write name="userlist" property="realname"
    filter="true" /></td>
   <td class="fr"><bean:write name="userlist" property="password"
    filter="true" /></td>
   <td class="frh"><bean:write name="userlist" property="addr"
    filter="true" /></td>
   <td class="fr"><bean:write name="userlist" property="level"
    filter="true" /></td>
   <td class="frh"><a
    href="/viewUser.do?id=<bean:write name="userlist" property="userId" filter="true" />">详细</a></td>
   <td class="fr"><a
    href="/deleteUser.do?id=<bean:write name="userlist" property="userId" filter="true" />">删除</a></td>
  </tr>
 </logic:iterate>
对比下发现差距也不大吧,不过,有了自动排序和导出,看起来满酷的。

酷是一方面,失望才是更大的。简单尝试和运行还是留下了遗憾,记录一下,如果有心人看到可以去改进:
1、不能读取Hibernate返回的离线List,这是个硬伤!不知道是不是我的使用问题。但是如果必须是在线的,那么内存浪费巨大。大的项目就用不了了!
2、所有的自动排序,自动分页,导出都是通过传统的服务器回写来实现的,看似酷,但是实际上过于简单。在Ajax很火爆的现在,技术有点落后了。
3、没有结合SDO这样的数据模型。其实和Ajax那个问题一样,没有SDO就不是组件模型。而只是一个傻瓜化的封装而已。
4、网站的文档不够详细,也不严谨,我觉得开源没有好的文档就永远火不起来。
5、我很欣赏所有的样式都依赖于css,而且东西很好扩展。但是居然网上有人抨击这种方式。我想反问那些满脑子程序的人,那些看不起美工的程序员,你们懂得程序是艺术么?你不懂css、不懂web standards、不懂xhtml、不懂xml,还有什么可混的么?
6、另一个问题。分页实现的太不优雅了。也许是taglib的限制。一次读取所有的数据,并且要求是在线的,仅仅为了分页,这太恐怖了。Hibernate不能这么用,JDBC也不能这么用!好的分页封装看来还要用别的。如此一看,这里面除了CSS提供看起来很好的表格外就只有导出功能了。
7、而悲观的是,导出功能除了花哨以外没有别的作用了,而导出功能还有更好的选择吧。
所以,一句话说。上手还算容易,可是深入难,看不到好的手册。Sample写的不错,可是缺乏与其它框架结合的例子,比如Hibernate、Struts。好多人说它好用,但是估计都是从简单的角度考虑的,性能的考虑是个问题。配置看起来还算容易,可是配置却没有文档来介绍,只能摸着石头过河。

所以,仅仅是结绳记事。小项目可以用。大项目用它没法发挥它带来的优势,只能使用可怜的一点点功能(我的例子只用了自动排序和导出)。不过开源项目,谁知道,没准麻雀变凤凰了呢。毕竟它的思想是对的,提供可用的Web组件(它声称要实现table、Tree等等),我也想找到一个这样的组件,那样就真的可以轻松些工作了!
等待那一天!

依赖注入DI、控制反转IoC

我也用我的话说说我的理解。
代码中的各种引用就会产生依赖。
原先用什么就在代码里声名什么,这样依赖是广泛的,任何改动丢要重新修改代码。
所以,不方便。
后来,流行工厂方法,不依赖具体类,只需要一个工厂,都准备好了。可是,这样就依赖于工厂了。如果有变动,就要修改工厂的代码。
所以,还不够理想。理想的方案是不修改代码,改变依赖之需要修改配置文件。
也就是,实现运行时依赖,而不是编译时依赖。这就是依赖注入的本质。
依赖注入DI(这是个方法),目的是实现依赖关系的完全解耦,也就是实现控制反转IoC(这是个理念)。

依赖注入就是通过IoC容器实现的一种自动依赖生成,你只需要配置依赖的字面关系,具体操作IoC容器自动完成。
Spring推荐使用的是:1、Setter 2、构造器(构造子)
关于两者的使用情景略有区别,夏昕那个文档有介绍。

用setter还是constructor。
如果依赖在生命周期不变就constructor,变就用setter。

DI实现的方式,流行的Spring实现了前两种,前两种DI都是IoC的实现。
1)通过set方法(Spring中常用这个玩意)
2)通过构造函数
3)参数传递(应该很早就开始应用了)

利用winrar自动备份重要资料

看到这个,发现很有用的文章,对于定期备份项目文件很方便。


每个人的电脑上都有很多有价值的资料,例如你写的论文、Outlook中的信件、IE收藏夹、FeedDemon中的rss链接等等,经常备份的重要性自不用多说,但怎样让备份变为轻松简单而不是繁重的劳动呢,我在网上查找了很多备份工具,发现它们要么很贵,要么存在各种缺陷(如不使用通用的压缩格式),后来发现其实只使用winrar就完全可以完成这个任务,而大部分人的电脑上都有这个压缩软件。

打开winrar的帮助主题,你会发现在winrar的命令行模式里可以指定很多参数,其格式为:

*WinRAR <command> -<switch1> -<switchN> <archive> <files> <@listfiles> <path_to_extract\> *

利用winrar可以从列表文件中读取要压缩的文件/文件夹这个功能,我们可以创建一个列表文件如C:\backup.txt,在这个文件里写入需要备份的文件/文件夹路径,格式很简单,每个路径一行即可。然后创建一个快捷方式(或批处理文件),其命令为:

*"C:\Program Files\WinRAR\WinRAR.exe" a C:\backup.rar @C:\backup.txt *

要进行备份的时候只要执行这个命令即可,这样会在C:\生成备份后的压缩文件,你最好把它转移到其他存储装置上。配合windows的计划任务,还可以进行定时自动备份。你还可以指定其他参数,例如加上-ibck可以让备份在后台执行,加上-t可以在压缩完成后验证等等,具体请参考winrar帮助主题。

这个方法的缺点是你必须自己找出那些需要备份的信息,有一些软件把信息存在注册表里不好备份,所以你可能需要在使用这种方式备份的同时手动备份注册表。不过很多专门用于备份的工具也是没有这个功能的。


以前帖子里说过用Winrar自动备份资料的方法,我现在平均每周备份两次,备份的内容包括日程(Rainlendar)、RSS频道(Rssowl)、Eclipse里的项目、常用IP设置、Outlook Express内容等等,压缩下来大约150M左右,其中主要是(带附件的)信件和项目文件占了大部分空间。

今天发现Eclipse里的一个CVS设置给搞错了,连接的是旧的CVS服务器,我在Eclipse里把服务器的地址改过来再进行Update操作,结果把我之后做的几处修改都覆盖了。还好我昨天晚上刚做了备份,这几天的工作没有白费。

类似这样的意外事件很难预料,事先做好充足的预防工作让我们有备无患,而付出的只是每周几分钟的时间,利当然远远大于弊。

关于Winrar备份我又总结了几条经验:首先可以设计两个备份任务,一个是全面备份,一个是快速备份,一些体积比较大又不是特别重要的不需要经常备份,平时每天进行快速备份,每周或每月全面备份一次就可以了;其次,在命令行里加上-ag参数可以让备份得到的压缩包文件名自动包含当前日期,从而不会覆盖掉以前的备份,该参数还可以指定日期格式,如YYYY-MM-DD等;另外,用-ms参数可以不对已经被压缩过的文件再次压缩,而是直接存放;最后,用-x命令可以排除一些我们不希望备份的文件,比如*.jar文件,一般都可以下载得到。我现在用的备份命令如下,其中backup-q.txt的内容是要备份文件的列表,得到的压缩包名像BAK20050223.rar这样:

"C:\Program Files\WinRAR\WinRAR.exe" a -agYYYYMMDD -ms -x.jar -ep2 -ibck -t c:\backup\BAK.rar @c:\backup\backup-q.txt *
这里要提醒一下,备份的文件最好定期转移到本地硬盘以外的存储地点,比如刻成光盘保存,还是不要过于相信硬盘了。


我自己的Script如下:

O:\Eclipse\Achive\backup.txt
O:\Eclipse\Workspace\Level2Demo
O:\Eclipse\Workspace\StructDemo
O:\Eclipse\Achive\do.bat
"C:\Program Files\WinRAR\WinRAR.exe" a -agYYYYMMDD -ms -x*.jar -ep2 -ibck -t O:\Eclipse\Achive\Workspace.rar @O:\Eclipse\Achive\backup.txt
cmd

安装Together for Eclipse 7.0

这里下载Together Edithion for Eclipse 7.0,这个是官方的,要注册个用户名才可以下载。大家通过其它渠道获取也可以,但要确定是7.0的。
安装很容易,有安装向导。不过要注意它只能工作于Eclipse 3.0.x,比如3.0.2,不支持3.1final的。
很容易找到的shock的破解在Windows XP下不起作用。如果大家也使用XP,请使用附件里面的ROR的给.net版做的破解,这个也可以用,而且是唯一可用的。
使用的时候先运行一遍Together(一定要使用Together安装目录下的TogetherEC.exe运行),它提示你注册的时候退出。然后运行keygen.jar(双击就可以),然后选择你安装Together目录下的license下面的ttec.slip,然后破解完成了,运行Together就可以进去了。
界面大家自己适应一下,应该容易上手,不过画图的那个palette是自动隐藏的,你用鼠标点击就可以展开(以前因为不知道以为破解没有成功,走了很多弯路,我很笨 __)由于Together默认使用自己的Perspective,所以如果和其它版本的Eclipse共享Workspace也许会报错,需要换回Perspective才可以。