StrutsAction:
StrutsAction实现了对Sturts DispatchAction进行简单封装的操作,其中bindEntity,bindForm分别封装了BeanUtils的copyProperties重载函数,该函数实现表单->pojo或者pojo->表单的动态实体赋值.saveMessage,saveDirectlyMessage,saveError,saveDirectlyError利用Struts的消息机制,将消息保存到Request中带回页面,在页面上common/message.jap中可以看到
<logic:messagespresent message="true"> </logic:messagespresent>
我们看看saveMessage以及saveDirectlyMessage
/**
* 保存单条信息到Message的简化函数.
*/
protected void saveMessage(HttpServletRequest request, String key, String... values) {
ActionMessages msgs = new ActionMessages();
msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(key, values));
saveMessages(request.getSession(), msgs);
}
/**
* 直接保存文本信息(非i18n)到messages.
*
* @param message 直接的文本信息
*/
protected void saveDirectlyMessage(HttpServletRequest request, String message) {
ActionMessages msgs = new ActionMessages();
msgs.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage(DIRECTLY_MESSAGE_KEY, message));
saveMessages(request.getSession(), msgs);
}
在saveMessage中,值得关注的是ActionMessages Map的每个元素的key值都是ActionMessages.GLOBAL_MESSAGE,这与struts的 <html:message> 中,属性message="ture"相呼应.在saveDirectlyMessage中,只是value ActionMessage的key值变成了软编码的DIRECTLY_MESSAGE_KEY,该值="message".对应资源文件message={0},,直接输出message. </html:message>
SS对Error信息的输出并没有采用struts的 <html:error> 机制,它也是通过与message的形式输出,其实saveError和saveDirectlyMessage与前两者完全一样,但在页面上,error部分的 <html:message> 的message属性为false(默认),但还是能显示出来.查了孙卫琴写的<精通Struts:基于MVC的java Web设计与开发>,她提到,"message如果为false,则根据name属性来检索ActionMessage对西那个,如果此时没有设置name属性,将采用默认值Globals.ERROR_KEY."也就是说,至少在saveError和saveDirectlyMessage中ActionMessages Map的Key值应该是Globals.ERROR_KEY,或者在保存时采用saveError. </html:message> </html:error>
4个render*函数直接用语句生成新页面而不走action的转发.
StrutsEntityAction:
StrutsEntityAction实现了对StrutsAction的二次封装并且实现Spring IoC LifeCycle的InitializingBean接口,实现该接口便有能力通过重写afterPropertiesSet函数在bean被创建后做一些事情.SS在这个函数中初始化一系列范型参数.
我觉得这个类有这么几个看点,
首先是在afterPropertiesSet中利用反射分别对Class<t></t>,Class以及M类型进行初始化,那是相当精彩.
其次是利用模版方法搭建了客户端action的增删改操作.
先来看afterPropertiesSet函数:
/**
* Init回调函数,初始化一系列泛型参数.
*/
public void afterPropertiesSet() {
// 根据T,反射获得entityClass
entityClass = GenericsUtils.getSuperClassGenricType(getClass());
// 根据M,反射获得符合M类型的manager
List<field></field> fields = BeanUtils.getFieldsByType(this, GenericsUtils.getSuperClassGenricType(getClass(), 1));
Assert.isTrue(fields.size() == 1, "subclass's has not only one entity manager property.");
try {
entityManager = (M) BeanUtils.forceGetProperty(this, fields.get(0).getName());
Assert.notNull(entityManager, "subclass not inject manager to action sucessful.");
} catch (Exception e) {
ReflectionUtils.handleReflectionException(e);
}
// 反射获得entity的主键类型
try {
idName = entityManager.getIdName(entityClass);
idClass = BeanUtils.getPropertyType(entityClass, idName);
} catch (Exception e) {
ReflectionUtils.handleReflectionException(e);
}
}