SpringSide学习笔记二

来源:互联网 发布:ubuntu wine qqintl 编辑:程序博客网 时间:2024/06/17 02:16
HelloWorld
5.分析org.springside.core.web包
SS的org.springside.core.web包对Sturts DispatchAction进行了二层封装.该包包含两个类StrutsAction,StrutsEntityAction.

StrutsAction:

StrutsAction实现了对Sturts DispatchAction进行简单封装的操作,其中bindEntity,bindForm分别封装了BeanUtils的copyProperties重载函数,该函数实现表单->pojo或者pojo->表单的动态实体赋值.saveMessage,saveDirectlyMessage,saveError,saveDirectlyError利用Struts的消息机制,将消息保存到Request中带回页面,在页面上common/message.jap中可以看到

message.jsp

我们看看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.

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.

4个render*函数直接用语句生成新页面而不走action的转发.

 

StrutsEntityAction:

StrutsEntityAction实现了对StrutsAction的二次封装并且实现Spring IoC LifeCycle的InitializingBean接口,实现该接口便有能力通过重写afterPropertiesSet函数在bean被创建后做一些事情.SS在这个函数中初始化一系列范型参数.

我觉得这个类有这么几个看点,

首先是在afterPropertiesSet中利用反射分别对Class<T>,Class以及M类型进行初始化,那是相当精彩.

其次是利用模版方法搭建了客户端action的增删改操作.

先来看afterPropertiesSet函数:

/**
  * Init回调函数,初始化一系列泛型参数.
  */
 public void afterPropertiesSet() {
  // 根据T,反射获得entityClass
  entityClass = GenericsUtils.getSuperClassGenricType(getClass());

  // 根据M,反射获得符合M类型的manager
  List<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);
  }
 }

entityClass的获取与HibernateEntityDao中获取entityClass的操作一样,这里不再赘述.
entityManager的获取通过BeanUtils的getFieldsByType对运行时的StrutsEntityAction子类对象以及M的运行时对象的属性进行逐一比较,并将与M同类型的StrutsEntityAction子类对象属性放入List返回.
getFieldsByType:
 /**
  * 按Filed的类型取得Field列表.
  */
 public static List<Field> getFieldsByType(Object object, Class type) {
  List<Field> list = new ArrayList<Field>();
  Field[] fields = object.getClass().getDeclaredFields();
  for (Field field : fields) {
   if (field.getType().isAssignableFrom(type)) {
    list.add(field);
   }
  }
  return list;
 }
然后将这个列表中的第一个元素强制赋值给entityManager(通常只有一个).
获得Entity的主键类型,首先通过manager的getIdName函数获得主键名称,然后利用BeanUtils的getPropertyType方法(该方法实际调用getDeclaredField)通过遍历族树循环向上转型进而获得主键类型.
 
再来看看利用模版方法实现增删改.回调函数如下:
/**
  * form与list界面所需的参考对象注入.如categoryList,在子类重载.
  */
 protected void refrenceData(HttpServletRequest request) {
 }
 /**
  * 显示Form表单时的回调函数.为Form对象添加更多属性,在子类重载.
  */
 protected void onInitForm(ActionForm form, HttpServletRequest request, T object) {
 }
 /**
  * 保存Form表单时的回调函数.为业务对象添加更多属性,在子类重载.
  */
 protected void onInitEntity(ActionForm form, HttpServletRequest request, T object) {
 }
我想别的也就不用多说了.
 
原创粉丝点击