從ActionErrors過渡到ActionMessages

          Posted on 2006-06-27 23:02 killvin 閱讀(1553) 評論(0)  編輯  收藏 所屬分類: java

          在Struts中我們經常這樣循環的打印Message
          <logic:messagesPresent message="true">
          ? <html:messages id="msg" message="true">
          ??? <div class="success">
          ????? <bean:write name="msg"/>
          ??? </div><br/>
          ? </html:messages>
          </logic:messagesPresent>

          查閱struts tag的文檔我們看到了關于messagesPresent的message屬性注釋如下

          message

          By default the tag will retrieve the request scope bean it will iterate over from the Globals.ERROR_KEY constant string, but if this attribute is set to 'true' the request scope bean will be retrieved from the Globals.MESSAGE_KEY constant string. Also if this is set to 'true', any value assigned to the name attribute will be ignored


          也就是說在將message設置為true時,會去request中尋找Globals.MESSAGE_KEY所代表的bean,然而我們在具體的Action使用ActionMessages類的時候往往是這樣的
          ActionMessages messages = getErrors(request);
          messages.add(ActionMessages.GLOBAL_MESSAGE , new ActionMessage(key , value0));
          saveMessages(request,messages);

          而往往困擾人的就在于為什么要給messages中放入名稱為"ActionMessages.GLOBAL_MESSAGE"的ActionMessage對象,而且還需要再次的調用saveErrors(request,messages)方法?

          首先要說明的是你為ActionMessage起任何的名稱都沒有關系,因為ActionMessages本身維持著一個HashMap,而參數property就是這個HashMap中的key值,如果不存在則會建立相應的key,并將需要保存的ActionMessage對象存入到這個key所對應的List中。
          ??? public void add(String property, ActionMessage message) {

          ??????? ActionMessageItem item = (ActionMessageItem) messages.get(property);
          ??????? List list = null;

          ??????? if (item == null) {
          ??????????? list = new ArrayList();
          ??????????? item = new ActionMessageItem(list, iCount++, property);

          ??????????? messages.put(property, item);
          ??????? } else {
          ??????????? list = item.getList();
          ??????? }

          ??????? list.add(message);

          ??? }

          至于為什么一定要調用saveMessages(request,messages)?看看它具體的實現邏輯就清楚了
          ??? protected void saveMessages(
          ??????? HttpServletRequest request,
          ??????? ActionMessages messages) {

          ??????? // Remove any messages attribute if none are required
          ??????? if ((messages == null) || messages.isEmpty()) {
          ??????????? request.removeAttribute(Globals.MESSAGE_KEY);
          ??????????? return;
          ??????? }

          ??????? // Save the messages we need
          ??????? request.setAttribute(Globals.MESSAGE_KEY, messages);
          ??? }

          再對比前面介紹的messagesPresent標簽的使用,是不是就清楚了呢?原來它是將ActionMessages對象保存在request中,并且名稱是Globals.ERROR_KEY!從而為tag的順利解析鋪平了道路。當然按理你可以選擇將這樣的對象放置在任何的scope中,但Action只是提供了request , session兩種Scope(不過page , application不經常使用,可以理解,但不提供相應的結構就不太好了)

          至于messagesPresent標簽是如何在scope中尋找ActionMessages對象

          org.apache.struts.taglib.logic.MessagesPresentTag
          ??? protected boolean condition(boolean desired) throws JspException {
          ??????? ActionMessages am = null;

          ??????? String key = name;
          ??????? if (message != null && "true".equalsIgnoreCase(message)){
          ?????????? key = Globals.MESSAGE_KEY;
          ??????? }

          ??????? try {
          ??????????? am = TagUtils.getInstance().getActionMessages(pageContext, key);
          ???????????
          ??????? } catch (JspException e) {
          ??????????? TagUtils.getInstance().saveException(pageContext, e);
          ??????????? throw e;
          ??????? }

          ??????? Iterator iterator = (property == null) ? am.get() : am.get(property);

          ??????? return (iterator.hasNext() == desired);

          ??? }

          org.apache.struts.taglib.TagUtils
          ?? public ActionErrors getActionErrors(PageContext pageContext, String paramName)
          ??????????? throws JspException {

          ??????? ActionErrors errors = new ActionErrors();

          ??????? Object value = pageContext.findAttribute(paramName);
          ??????? if (value != null) {
          ??????????? try {
          ??????????????? if (value instanceof String) {
          ??????????????????? errors.add(
          ??????????????????????????? ActionMessages.GLOBAL_MESSAGE,
          ??????????????????????????? new ActionMessage((String) value));

          ??????????????? } else if (value instanceof String[]) {
          ??????????????????? String keys[] = (String[]) value;
          ??????????????????? for (int i = 0; i < keys.length; i++) {
          ??????????????????????? errors.add(
          ??????????????????????????????? ActionMessages.GLOBAL_MESSAGE,
          ??????????????????????????????? new ActionMessage(keys[i]));
          ??????????????????? }

          ??????????????? } else if (value instanceof ActionErrors) {
          ??????????????????? errors = (ActionErrors) value;

          ??????????????? } else {
          ??????????????????? throw new JspException(
          ??????????????????????????? messages.getMessage(
          ??????????????????????????????????? "actionErrors.errors",
          ??????????????????????????????????? value.getClass().getName()));
          ??????????????? }

          ??????????? } catch (JspException e) {
          ??????????????? throw e;

          ??????????? } catch (Exception e) {
          ??????????????? log.debug(e, e);
          ??????????? }
          ??????? }
          ??????? return errors;
          ??? }

          PageContext中的findAttribute會幫你在scope中尋找名稱為Globals.MESSAGE_KEY的ActionMessage對象。


          注意
          雖然Struts已經聲明:不推薦使用ActionErrors & ActionError對象,但在一些遺留的系統中,依然還是可以看到其影子,所以如果你的系統不幸屬于這樣的兩種混合系統,有以下的幾種方法可以參考
          1。兩次調用messagesPresent,如下
          <!-- Print ActionErrors Object -->
          <logic:messagesPresent>
          ? <html:messages id="msg" message="true">
          ??? <div class="success">
          ????? <bean:write name="msg"/>
          ??? </div><br/>
          ? </html:messages>
          </logic:messagesPresent>

          <!-- Print ActionMessages Object -->
          <logic:messagesPresent message="true">
          ? <html:messages id="msg" message="true">
          ??? <div class="success">
          ????? <bean:write name="msg"/>
          ??? </div><br/>
          ? </html:messages>
          </logic:messagesPresent>

          2.分別使用<html:messages> <html:errors>標簽,當然在老系統中需要調用Action的saveErrors方法,而在新的應用中要調用saveMessages方法。

          3.更換所有的ActionErrors為ActionMessages,并將所有調用saveErrors的地方更換成saveMessages,并將<html:errors>標簽相應的更換成<html:messages message="true"> - 推薦!

          ?

          主站蜘蛛池模板: 阿拉善左旗| 永吉县| 正宁县| 曲阳县| 淮南市| 青浦区| 成武县| 沭阳县| 青阳县| 鹰潭市| 鞍山市| 和田县| 景泰县| 安顺市| 怀化市| 绥芬河市| 乌兰浩特市| 赤城县| 江门市| 蛟河市| 吴川市| 南靖县| 凌云县| 灌云县| 新邵县| 霍城县| 手游| 阳山县| 云南省| 赤城县| 桐城市| 望奎县| 晋江市| 灵宝市| 唐河县| 旌德县| 盐山县| 定西市| 长沙市| 永丰县| 乡宁县|