Unmi 的 Struts2 学习笔记(七)

小时候,大人们的谆谆教诲:做人要诚实。并真以此为做人原则。长大后才知道何谓社会。譬如530,再如艳照门,风声乍起之时,有人辟谣;直东窗事发后,道貌岸然者有之、恬不知耻者亦有之。原本成功就不属于规矩之人。纵观,无玄武门之血腥,何来一代宗皇;老毛若不有理而造反,一味守规矩,或为一介书匠耳。雅各一碗红豆汤便谋得以扫的长子权,再行骗去亚伯拉罕的祝福,并顺理成章让耶和华与他同在,可见上帝之“贤明”?。高等教育中有一句,顺利的是骗子,倒霉的是傻子,我是?不还有企业家的原罪吗?有时竟被社会所放任?

1. 前面讲的自定义类型转换器是基于 OGNL 的 DefaultTypeConverter 类并实现 convertValue() 方法,两个转换方向的逻辑都写在这一个方法中。而 Struts 2 为我们提供了一个 DefaultTypeConverter 的抽象子类 StrutsTypeConverter 来继承,并实现其中两个抽象方法 convertFromString() 和 convertToString(),这要简单易懂。对比 Struts 1 的转换器是要实现 org.apache.commons.beanutils.Converter 接口,以及它的 convert() 方法的。 阅读全文 >>

Unmi 的 Struts2 学习笔记(六)

米洗毕,水适量,盖合上,心摇摆,总觉水多了一分或是少了几点,于是重又加上或倒出少许,其实这丁点份量完全无碍煮出香喷喷的饭来。及至将熟之际,亦有犹豫,心中默数至少10,如再有不定辄至20,掐火,20对最终质量来说或有所损。

1. Struts2 的 Action 中可直接用属性来封装请求参数和处理结果,此谓之属性驱动。也可以像 Struts1 那样使用专门的 ActionForm 来处理请求参数和结果,只不过 Struts2 用的是一个更单纯的 POJO,这就做模型驱动;此时的 Action 需要实现 ModelDriven 接口,并实现其 getModel() 方法将 Action 与对应 Model 相关联。

2. 例子说明采用模型驱动的 Action (UserBean 是一个普通 JavaBean,其中定义了 username 和 password 两个属性): 阅读全文 >>

Unmi 的 Struts2 学习笔记(五)

常有这样的梦:不知何来一本似乎是无字天书,而其中的字句却是慢慢地、渐显可辨。同时现实中的自己完全能察觉这是一个梦,极怕即刻醒来,想多记取那些天外之语。但总不能如愿,醒来时还留有某些字句痕迹,再过后就全然忘却。仿佛进入的是一个太虚幻境。

1. 动态 Action:<action ../> 元素的一个前所未有的特性是,name 属性可以用通配符,class 和 method 属性中可以用 name 中的匹配参数,{0}/{1} 的形式。举两个例子说明:
    ① <action name="*Action" class="com.unmi.LoginRegistAction" method="{1}">
         URL 是 registAction.action 时,会执行 LoginRegistAction 类实例的 regist() 方法
    ② <action name="*_*" class="actions.{1}Action" method="{2}">
         URL 是 Book_save.action 时,会执行 actions.BookAction 类实例的 save() 方法 阅读全文 >>

Unmi 的 Struts2 学习笔记(四)

在这个陌生的城市里,的确承受着巨大的压力。房东的驱赶与无理的加价,想置个家电须顾及到搬迁。也开始学会了算计着过活,两块五与三块的公交,宁愿等待与拥挤,就连省下一顿饭钱都能暗自庆幸。周末了,老老实实呆在家里吧!

1. 按这个顺序加载 Struts2 的常量,struts-default.xml、struts-plugin.xml、struts.xml、web.xml;后加载的会覆盖前面的同名常量。强烈不推荐在 web.xml 中配置 Struts2 常量。

2. Struts1 中有一种 Action 类型是 ForwardAction,而在 Struts2 中相应的配置方式是 <action name="Showcase"><result>/showcase.jsp</result></action>,Showcase.action 直接映射到 /showcase.jsp。 阅读全文 >>

Unmi 的 Struts2 学习笔记(三)

连续几日熬夜,以致左胸又起闷痛感,何来如此辛苦?不由自忖,人生至今,印象中从来就没有过安逸与幸福感。常要回避刺疼。

1. WebWork 的核心控制器是 ServletDispatcher,映射到 *.action 的 <url-pattern> 即可。在 WebWork 与 Struts2 的 struts.xml 和 struts.properties 相对应的分别是 xwork.xml 和 webwork.properties,文件内容几乎一样,只几个关键字的差异。

2. Struts2 的 struts.xml 中 <action ../> 的 name 属性相当于 struts1 的 <action ../> 的 path 属性,但在这里不需要以 "/" 开始。

3. Action 中使用业务逻辑组件实例时,通常不直接 New,而会通过工厂方法或 IOC 容器。虽然 WebWork 有 IOC 容器,但 Struts2 通常会使用 Spring 的 IOC。 阅读全文 >>

Unmi 的 Struts2 学习笔记(二)

记笔记,尤其是在 Blog 里记,实则是浪费时间。让学习、阅读的速度以数量级的下降,收获时当时掌握的更细,却并不代表着真记得牢。一小段时间不用它,同样可以忘得很干净,也就是方便于以后能由此泛起些涟漪,如能抛砖引玉就更幸运了。入正题:

1. 记得 Struts1 的 struts-config.xml 通常是放在 WEB-INF 目录下的,Struts2 的 struts.xml 却要放到 WEB-INF/classes 下的,傻眼了吧,反正我是。没看仔细之前,总给我报 There is no Action mapped for namespace / and action name Login. - [unknown location]  错误。因未在 web.xml 指定 struts.xml,所以用 ClassLoader 来加载它了。

2. 最简单的 Struts2 应用都要用到 freemarker-xxx.jar 包,因为 UI 标签要用到 FreeMarker ftl 的模板。

3. FilterDispatcher 要处理所有的 Web 请求,所以它的 url-pattern 是 /*,并自动对 *.action 转给业务 Action 处理。 阅读全文 >>

Unmi 的 Struts2 学习笔记(一)

Struts 从1.1使用到1.3已有多年,都升成2了,却来了个大变脸,须重新审视一番了。从头学习,记下笔记,以要点式。

1. Struts2 与 Struts1 似乎没什么血缘关系了,承自于 WebWork,直害 WebWork 不再推出新版本了,原先的 WebWork 使用者只需顺其然,即是水道渠成;相反 Struts1 的开发经验对于 Struts2 却没有太大的帮助。

2. Struts1 的核心控制器是 ActionServlet,而 Struts2 的核心控制器是 FilterDispatcher。Struts2 的业务 Action 会在运行时生成 Action 代理。

3. Struts1 的 Action 须继承抽象 Action 类,侵入了 Servlet API;而 Struts2 的 Action 可以实现 ActionSupport,或者只要一个纯净的 POJO 来充当,完全与 Servlet 绝缘。也因此带来测试性 Struts2 要比 Struts1 强,可把 Struts TestCase 扔到一旁去了。 阅读全文 >>

用 AOP 来记录每个方法的执行时间(Spring 或直接 AspectJ)

有时候我们要跟踪方法的执行时间,来观察系统的性能、时间分布。特别是要找出那些十分耗时的操作。如果是在每个方法中起始和结束位置记下时间相减,那是不太现实的,对代码的侵入性太过份,而且在产品环境中又得屏闭那部份代码。

幸好现在有了 AOP,通过配置方式再加上外部辅助代码就能达到我们的要求,正式上线时只需要简单改个配置项拆卸下来即可。

下面介绍三种方式来打印每个方法的执行时间,分别是:

1. Spring 2.0 用 AspectJ 实现 AOP
2. Spring 通用的方法拦截
3. 直接用 AspectJ 实现 阅读全文 >>

Spring 整合 Hibernate 的一处简化配置[转]

在过去使用 Spring 整合 Hibernate 的时候,都是用这样的配置方式。

阅读全文 >>

Hibernate 保存对象出现 org.hibernate.NonUniqueObjectException 及解决

Hibernate save 在 session 中已存在相同 OID(主键) 的对象,会出现异常,详细内容如下:

Exception in thread "main" org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [com.unmi.LoanDetail#1]
 at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:168)
 at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121)
 at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
 at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
 at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient 阅读全文 >>