Pragmatic Struts
Struts 1.2同样可以写得非常精简,不一定要如传统观念认为的那么繁重。
1.DispatchAction
以一个Controller响应一组动作绝对是Controller界的真理,Struts的DispatchAction同样可以做到这点。
<action path="/admin/user" name="userForm" scope="request" parameter="method" validate="false">
<forward name="list" path="/admin/userList.jsp"/>
</action>
其中parameter="method" 设置了用来指定响应方法名的url参数名为method,即/admin/user.do?method=list 将调用UserAction的public ActionForward list(....) 函数。
public ActionForward unspecified(....) 函数可以指定不带method方法时的默认方法。
2. struts-config.xml使用通配符
对一些CRUD的Action,可以使用通配符,如果这批action里某个action某个方法还存在特殊路径,可以在代码里直接new ActionForward("/foo.jsp");
3.No FormBean
Struts 1.2.7 之后一共有三种方法,不需要定义FormBean Java类也不需要在struts-config.xml里详细定义formBean的属性。
第一种是appfuse里使用的,定义DynaValidatorForm里的内嵌属性为pojo.
第二种是直接用BeanValidatorForm,直接把Pojo作FormBean,无需继承于FormBean接口。
<form-bean name="userForm" type="org.springside.helloworld.domain.User"/>
User user = (User) userForm.getInstance();
第3种是用LazyValidatorForm ,特别适合于Form中并没有POJO商业对象的所有属性的情况,因为通常项目里都属于这种情况,所以springside默认使用lazyValidatorForm.
比如User对象 有 id,name,status三个属性,而form中只有id和name属性,如果使用方法1,2,直接把user 作为 form bean, user对象的status因为没设值,将为null, copy 到作为商业对象的user时,就会以null覆盖原值。而lazyBean就没有这个问题,如果form中没有status属性,它不会将它copy给商业对象。
另外,apache commons-beantuils 1.7.0的lazybean仍有小bug,需要使用commons-1.7.1 snapshot版。
BeanUtils.copyProperties(user, form);
注意User对象被自动绑定,默认Integer id 在空值时会被赋值为0,需要增加converter,让其默认为null,虽然也可以在web.xml里进行相关配置,但还是在基类里配置了比较安全。
static {
ConvertUtils.register(new IntegerConverter(null), Integer.class);
}
4. StrutsEntityAction
SpringSide 演示了如何为单个对象的CRUD操作(增删改查)封装了默认Action,子类只需要范型声明所管理的对象类型,并实现一个getManager()的函数即可拥有CRUD操作的能力。
大家各自项目的习惯不同,可以参考SpringSide的封装,封装自己的版本。
典型子类代码如下:
public class UserAction extends StrutsEntityAction<User> {
private UserManager userManager;
public void setUserManager(UserManager userManager) {
this.userManager = userManager;
}
@Override
protected IEntityDao<User> getManager() {
return userManager;
}
}
只需留意三点:
第一 extends StrutsEntityAction<User>,声明管理的Entity类型是User;
第二 依赖注入userManager;
第三 实现getManager() 函数,将userManager返回给EntityAction父类进行业务操作,要求userManager类必须实现IEntityDao接口。
子类扩展点:
EntityAction必须预留足够的扩展点给子类重载,具体函数注释见StrutsEntityAction的JavaDoc
, 包括:
1.list、edit、view、save、delete: 五种action的流程封装;
2.doListEntity、doGetEntity、doNewEntity、doSaveEntity(),doDeleteEntity: 五种业务函数调用;
3.initEntity、initForm : FormBean与业务对象的初始化函数及refrenceData,onInitForm,onInitEntity 三个回调函数;
4.savedMessage、deletedMessage: 两种业务成功信息。
整个封装思路很清晰,大家可以参考来设计自己的封装。