對天乙社區bbscs8實現的詳細分析十六

加根Hr,其它類似,我們重點分析如下:
<s:iterator id="b1" value="%{boardList}">
    <li>
    <s:if test="%{urlRewrite}">
    <a href="javascript:;" οnclick="loadChild('<s:property value="#b1.id"/>','<s:property

value="#b1.boardType"/>')"><img id="img<s:property value="#b1.id"/>" src="images/expand.gif"

alt="展開" width="25" height="15" border="0" align="absmiddle"/></a><a href="forum-index-

<s:property value="#b1.id"/>.html"><s:property value="#b1.boardName"/></a>
    </s:if>
    <s:else>
    <s:url action="forum?action=index" id="furl">
    <s:param name="bid" value="#b1.id"/>
    </s:url>
    <a href="javascript:;" οnclick="loadChild('<s:property value="#b1.id"/>','<s:property

value="#b1.boardType"/>')"><img id="img<s:property value="#b1.id"/>" src="images/expand.gif"

alt="展開" width="25" height="15" border="0" align="absmiddle"/></a><a

href="${furl}"><s:property value="#b1.boardName"/></a>
    </s:else>
    <div id="child<s:property value="#b1.id"/>" class="nag" style="display:none">
    <s:set name="bl2" value="%{boardMap.get(#b1.id)}"></s:set>
    <ul>
    <s:iterator id="b" value="#bl2">
    <s:url action="forum?action=index" id="burl">
    <s:param name="bid" value="#b.id"/>
    </s:url>
    <li>
    <s:if test="%{urlRewrite}">
    <img id="img<s:property value="#b.id"/>" src="images/node.gif" alt=""

align="absmiddle"/><a href="forum-index-<s:property value="#b.id"/>.html"><s:property

value="#b.boardName"/></a>
    </s:if>
    <s:else>
    <s:url action="forum?action=index" id="burl">
    <s:param name="bid" value="#b.id"/>
    </s:url>
    <img id="img<s:property value="#b.id"/>" src="images/node.gif" alt=""

align="absmiddle"/><a href="${burl}"><s:property value="#b.boardName"/></a>
    </s:else>
    </li>
    </s:iterator>
    </ul>
    </div>
    </li>
好,我們看in!首先看它的interceptor:
<action name="in" class="inAction">
   <interceptor-ref name="mainUserAuthInterceptorStack"></interceptor-

ref>
   <interceptor-ref name="requestBasePathInterceptor"></interceptor-

ref>//講過
   <result name="success">/WEB-INF/jsp/in.jsp</result>
</action>
這裏有一個mainUserAuthInterceptorStack:
<interceptor-stack name="mainUserAuthInterceptorStack">
    <interceptor-ref name="defaultStack"></interceptor-ref>
    <interceptor-ref name="userLoginInterceptor"></interceptor-

ref>//講過
    <interceptor-ref

name="userSessionInterceptor"></interceptor-ref>
    <interceptor-ref name="userOnlineInterceptor"></interceptor

-ref>
    <interceptor-ref

name="userPermissionInterceptor"></interceptor-ref>//講過!
   </interceptor-stack>
好,我們看看UserSessionInterceptor和userOnlineInterceptor吧:
public String intercept(ActionInvocation invocation) throws Exception {
ActionContext ac = invocation.getInvocationContext();
Object action = invocation.getAction();

if (action instanceof UserSessionAware) {
   HttpServletRequest request = (HttpServletRequest) ac.get

(ServletActionContext.HTTP_REQUEST);
   HttpServletResponse response = (HttpServletResponse) ac.get

(ServletActionContext.HTTP_RESPONSE);

   ServletContext servletContext = (ServletContext) ac.get

(ServletActionContext.SERVLET_CONTEXT);
   WebApplicationContext wc =

WebApplicationContextUtils.getWebApplicationContext(servletContext);

   if (wc == null) {
    logger.error("ApplicationContext could not be found.");
   } else {
    SysConfig sysConfig = (SysConfig) wc.getBean("sysConfig");
    UserCookie userCookie = new UserCookie(request, response,

sysConfig);//得到UserCookie!
    ((UserSessionAware) action).setUserCookie(userCookie);
   
    UserSession us = (UserSession) ac.getSession().get

(Constant.USER_SESSION_KEY);//得到UserSession!
        ((UserSessionAware)

action).setUserSession(us);
   }
}

return invocation.invoke();//將兩個都放到UserSessionAware(它有兩個公開實現的

方法),以便action類使用!
/**
public interface UserSessionAware {
public void setUserCookie(UserCookie userCookie);
public void setUserSession(UserSession userSession);
}
*/
}
現在,我們要認真地分析下userOnlineInterceptor:
   long nowTime = System.currentTimeMillis();//現在的時間long
   long addedTime = nowTime - us.getLastActiveTime();//相隔的時間
   us.setAddedOnlineTime(us.getAddedOnlineTime() + addedTime);//累加在

線時間
   us.setAddedOnlineHour(us.getAddedOnlineHour() + addedTime);//累加在

線小時數
其實這個攔截器是在us.getAddedOnlineTime()>(sysConfig.getUserOnlineTime()*1000)這個條件去改變

相關的數據的!若不存在在線信息,添加之!若存在uo,其中比較了uo 和us的validateCode:
if (uo != null && !uo.getValidateCode().equals(us.getValidateCode())) { // 用戶重複登錄

      String ajax = "html";
      Map map = ac.getParameters();//action的參數


      String[] _ajax = (String[]) map.get("ajax");
      if (_ajax != null) {
       ajax = _ajax[0];//ajax="html"
      }

      ResourceBundleMessageSource messageSource =

(ResourceBundleMessageSource) wc
        .getBean("messageSource");
      String errorMsg = messageSource.getMessage

("error.login.re", null, ac.getLocale());
      if (ajax.equalsIgnoreCase("html") ||

ajax.equalsIgnoreCase("shtml")) {
       return "relogin";
      } else {
       AjaxMessagesJson ajaxMessagesJson =

(AjaxMessagesJson) wc.getBean("ajaxMessagesJson");
       ajaxMessagesJson.setMessage

("E_LOGIN", errorMsg);
       ac.getValueStack().set

("ajaxMessagesJson", ajaxMessagesJson);
       return "ajaxjson";
      }
這裏的relogin:
<result name="relogin" type="redirect-action">login?action=relogin</result>注意你有個

actionerror!
接下來,是修改相應的userinfo信息及清理us!
UserInfo ui = userService.findUserInfoById(us.getId());

     if (ui != null) { // 取得正確用戶信息

      ui.setStayTime(ui.getStayTime() +

(us.getAddedOnlineTime() / 1000)); // 增加用戶在線時長
      us.setAddedOnlineTime(0);


      // 刷新權限
      if (Constant.USE_PERMISSION_CACHE) {
       logger.debug("刷新用戶權限");
       us.setGroupID(ui.getGroupID());
       us.setBoardPermissionArray

(userService.getUserPermission(ui));
      }

      if (us.getAddedOnlineHour() >= 3600000) {
       logger.info("用戶在線累計超過1個小時

,增加用戶經驗值");
       ui.setExperience(ui.getExperience()

+ (int) (us.getAddedOnlineHour() / 3600000));
       us.setAddedOnlineHour(0);

      }
最後,我們應該改變useronline的時間(用戶在線存在時),以及us的活躍時間!
us.setLastActiveTime(nowTime);
ac.getSession().put(Constant.USER_SESSION_KEY, us);
好的,我們回到in:
<action name="in" class="inAction">
   <interceptor-ref name="mainUserAuthInterceptorStack"></interceptor-

ref>//它有默認

defaultStack,userLoginInterceptor,userSessionInterceptor,userOnlineInterceptor,userPermissio

nInterceptor(請注意聯繫與順序)
   <interceptor-ref name="requestBasePathInterceptor"></interceptor-

ref>
   <result name="success">/WEB-INF/jsp/in.jsp</result>
</action>
我們進入In.java不過它只實現了RequestBasePathAware:
其execute由index去完成!我們注意到extends BaseMainAction,而BaseMainAction:
public class BaseMainAction extends BaseAction implements UserSessionAware {
private UserCookie userCookie;//get/set
private UserSession userSession;
public String execute() {
try {
   return this.executeMethod(this.getAction());
} catch (Exception e) {
   logger.error(e);
   this.addActionError(this.getText("error.msg"));
   return ERROR;
}
}
-->
protected String executeMethod(String method) throws Exception {
Class[] c = null;
Method m = this.getClass().getMethod(method, c);
Object[] o = null;
String result = (String) m.invoke(this, o);
return result;
}
這個Action類注入有這些服務

userService,notService,friendService,userOnlineService,forumService,sysConfig,sysStatService

,boardService!而也於表單的或其它的屬性(頁面調用)有:

onlineHighest,sysinfo,lastLoginTime,titleValue,userTitle,newNoteNumInbox,noteAllNumInbox,fre

indNum,onlineGuestNum,friendOnlineNum,guest,newForums

(List<Forum>),boardList,boardMap,urlRewrite,usePass,actionUrl,toUrl,forumSite,useAuthCode.
我們先看onlineNum和onlineGuestNum的做法:
long atime = System.currentTimeMillis() - (this.getSysConfig().getUserOnlineTime() * 1000);

long onlineNum = this.getUserOnlineService().getUserOnlineNum(atime, 0, 0,

Constant.NORMAL_USER_GROUPS);
long onlineGuestNum = this.getUserOnlineService().getUserOnlineNum(atime, 0,

0, Constant.GUEST_USER_GROUPS);
this.getSysStatService().saveOnline(onlineNum + onlineGuestNum);
this.setSysinfo(this.getText("bbscs.sysinfo", new String[] {
    String.valueOf(this.getSysStatService().getPostMainNum()),
    String.valueOf(this.getSysStatService().getPostNum()),
   String.valueOf(this.getSysStatService().getAllUserNum()), reguserurl

}));//bbscs.sysinfo=社區信息:主題數: {0} / 帖子總數: {1} / 社區人數: {2} / 歡迎新用戶: {3}
其中:
long foNum = this.getUserOnlineService().getUserOnlineNumInIds(atime,
     this.getFriendService().findFriendIds

(this.getUserSession().getId(), 0), 0, 0,
     Constant.NORMAL_USER_GROUPS);
   this.setFriendOnlineNum(foNum);
其實struts2.0的Action我覺得比Struts1.2強在不僅能從表單得到數據,也能將數據傳遞過JSP界面,通

過標籤或表達式語言show出來!
到in.jsp看看:
對於這個主頁充分體現了strut2在界面上做的一些工作!請參考相關資料:

http://www.blogjava.net/max/archive/2006/10/18/75857.aspx
http://www.blogjava.net/max/archive/2007/04/28/114417.html
總體上對版區的顯示是:
<s:iterator id="board" value="%{boardList}">
<s:if test="#board.boardType==1">
</s:if>
      <s:if test="#board.boardType==3">
</s:if>
   <s:set name="bl2" value="%{boardMap.get(#board.id)}"></s:set>
      <s:iterator id="b" value="#bl2">
</s:iterator>
      </s:iterator>
下面的最新貼由action傳遞過來的值:
<table width="100%" border="0" cellpadding="3" cellspacing="0">
       <s:iterator id="newf" value="%{newForums}">
                        <tr>
                          <td>
                            <s:if test="%{urlRewrite}">
                              <a href="read-topic-<s:property value="#newf.boardID"/>-

<s:property value="#newf.mainID"/>-0-1-index-1.html"><s:property value="#newf.title"/></a>

                              [<a href="forum-index-<s:property

value="#newf.boardID"/>.html"><s:property value="#newf.boardName"/></a>]
                            </s:if>
       <s:else>
         <s:url action="read?action=topic"

id="posturl">
         <s:param name="bid"

value="#newf.boardID"/>
         <s:param name="id"

value="#newf.mainID"/>
         <s:param name="fcpage" value="1"/>
         <s:param name="fcaction"

value="index"/>
         </s:url>
         <a href="${posturl}"><s:property

value="#newf.title"/></a>
         <s:url action="forum?action=index"

id="forumurl">
         <s:param name="bid"

value="#newf.boardID"/>
         </s:url>
                              [<a href="${forumurl}"><s:property

value="#newf.boardName"/></a>]
                            </s:else>
                          </td>
                        </tr>
                      </s:iterator>
                    </table>
而其它的(如:班竹推薦,積分榜)大多由bbscs標籤完成!我們來看看我
<table width="100%" border="0" cellpadding="3" cellspacing="0">
                    <bbscs:in type="commend"/>
                </table>
這裏我們重點分析一下bbscs在這頁的一些tag:
<bbscs:face value="%{userSession.id}"/>
<bbscs:datetimes format="yyyy-MM-dd HH:mm:ss" datetype="date" value="%{lastLoginTime}"/>
<bbscs:boardmaster value="#board.boardMaster"/>
<bbscs:in type="commend"/>
<bbscs:in type="userexp"/>
<bbscs:in type="userlit"/>
<bbscs:in type="userknow"/>
我們一個一個來看:
<tag>
<name>face</name>
<tag-class>com.laoer.bbscs.web.taglib.UserFaceTag</tag-class>
<body-content>empty</body-content>
<attribute>
   <name>value</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
我們直接看UserFace.java:
public boolean start(Writer writer) {
boolean result = super.start(writer);

if (value == null) {
   value = "top";
} else if (altSyntax()) {
   if (value.startsWith("%{") && value.endsWith("}")) {
    value = value.substring(2, value.length() -

1);//userSession.id
   }
}
String userId = "";
Object idObj = this.getStack().findValue(value);//從棧中取值!
if (idObj != null) {
   userId = (String) idObj;
}
StringBuffer sb = new StringBuffer();

if (StringUtils.isBlank(userId)) {
   sb.append("<img src="");
   sb.append(facePicName);
   sb.append("" alt="Face" />");
   try {
    writer.write(sb.toString());
   } catch (IOException e) {
    e.printStackTrace();
   }
   return result;
} else {
   if (userId.startsWith(Constant.GUEST_USERID)) { // 遊客
    sb.append("<img src="");
    sb.append(facePicName);
    sb.append("" alt="Face" />");

   } else { // 正常用戶
    WebApplicationContext wc =

WebApplicationContextUtils.getWebApplicationContext(this.pageContext
      .getServletContext());

    UserService us = (UserService) wc.getBean("userService");
    UserInfoSimple uis = us.getUserInfoSimple(userId);

    if (uis.getHavePic() == 1 && !uis.getPicFileName().equals

("-")) {
     sb.append("<a href="");
     sb.append(BBSCSUtil.getUserWebPath(uis.getId()));
     sb.append(uis.getPicFileName());//大圖
     sb.append("" target="_blank">");
     sb.append("<img src="");
     sb.append(BBSCSUtil.getUserWebPath(uis.getId()));
     sb.append(uis.getPicFileName());
     sb.append(Constant.IMG_SMALL_FILEPREFIX);//小圖
     sb.append("" alt="Face" border="0"

class="pic1"/>");
     sb.append("</a>");
    } else {
     sb.append("<img src="");
     sb.append(facePicName);
     sb.append("" alt="Face" />");
    }
   }
   try {
    writer.write(sb.toString());
   } catch (IOException e) {
    e.printStackTrace();
   }
}

return result;
}
我們看第二個:
<bbscs:datetimes format="yyyy-MM-dd HH:mm:ss" datetype="date" value="%{lastLoginTime}"/>
<tag>
<name>datetimes</name>
<tag-class>com.laoer.bbscs.web.taglib.DateTimesTag</tag-class>
<body-content>empty</body-content>
<attribute>
   <name>value</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
   <name>datetype</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
   <name>format</name>
   <required>false</required>
   <rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
我們看com.laoer.bbscs.web.taglib.DateTimes關鍵的代碼片斷:
Date date = null;
if (this.datetype.equalsIgnoreCase("timestamp")) {
   long atime = (Long) this.getStack().findValue(value);
   date = new Date(atime);
} else if (this.datetype.equalsIgnoreCase("date")) {
   date = (Date) this.getStack().findValue(value);
} else {
   date = new Date();
}
String stime = Util.formatDate(date, format);//format有默認格式!
try {
   writer.write(stime);
} catch (IOException e) {
   logger.error(e);
}
好,我們看第三個:<bbscs:boardmaster value="#board.boardMaster"/> #board是個標誌!
<tag>
<name>boardmaster</name>
<tag-class>com.laoer.bbscs.web.taglib.BoardMasterTag</tag-class>
<body-content>empty</body-content>
<attribute>
   <name>value</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
其主要的代碼如下:
Map boardMasterMap = (Map) this.getStack().findValue(value);//返回的是Map對象!

if (boardMasterMap != null) {
   StringBuffer sb = new StringBuffer();
   // Set bmSet = boardMasterMap.entrySet();
   Iterator bmit = boardMasterMap.values().iterator();
   while (bmit.hasNext()) {
    com.laoer.bbscs.bean.BoardMaster bm =

(com.laoer.bbscs.bean.BoardMaster) bmit.next();
    if (bm.getIsHidden() == 0) {//不是隱身的!
     sb.append("<a href="");
     sb.append(BBSCSUtil.getActionMappingURL("/userInfo?

action=name&username=" + bm.getUserName(),
       request));
     sb.append("">");
     sb.append(bm.getUserName());
     sb.append("</a> ");
    }
   }
   try {
    writer.write(sb.toString());
   } catch (IOException e) {
    e.printStackTrace();
   }
}
好,我們看最後一個了:<bbscs:in type="userknow"/> type有四種!
<tag>
<name>in</name>
<tag-class>com.laoer.bbscs.web.taglib.InTag</tag-class>
<body-content>empty</body-content>
<attribute>
   <name>type</name>
   <required>true</required>
   <rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
由於InTag中:
public Component getBean(ValueStack arg0, HttpServletRequest arg1,

HttpServletResponse arg2) {
return new InComponent(arg0);
}

protected void populateParams() {
super.populateParams();

InComponent tag = (InComponent)component;

tag.setType(type);
}
所示其執行者爲InComponent,而非In!這可在InComponent.java裏看到:
if (this.getType().equalsIgnoreCase("commend")) {
   File commendFile = new File(BBSCSUtil.getIncludePath() +

"ForumCover_Commend_0.html");
   String commendlist = "";
   try {
    commendlist = FileUtils.readFileToString(commendFile,

Constant.CHARSET);
    if (commendlist == null) {
     commendlist = "";
    }
   } catch (IOException ex) {
    logger.error(ex);
    commendlist = "";
   }

   this.write(writer, commendlist);
   return result;
}
-->
private void write(Writer writer, String txt) {
try {
   writer.write(txt);
} catch (IOException e) {
   e.printStackTrace();
}
}
最後,我們應該對in.jsp中的一些東西有點感覺:
<s:property value="%{sysinfo}" escape="false"/>
其後面提供了google對本系統的搜索,也提供了搜索用戶的表單:
<s:form action="userInfo">
<s:hidden name="action" value="name"></s:hidden>

===========================================================================================


在分析三,我們已經分析出jsp頁面如何通過struts2的標籤與action配合,將數據在表示層傳遞(set/get),並且把主要的開始流程給分析完了。這裏我們將前臺的主要請求大致分析一下:從導航部分開始,對於社區首頁in.bbscs我們已經講過,它這裏只不過是將框架的target=mainForm以便從任何位置轉到首頁!進入個人中心,點擊修改簽名,觸發了signSet.bbscs:
<action name="signSet" class="signSetAction">
   <interceptor-ref name="mainUserAuthInterceptorStack"></interceptor-ref>//用戶權限!
   <result name="success">/WEB-INF/jsp/signSet.jsp</result>
   <result name="input">/WEB-INF/jsp/signEdit.jsp</result>
</action>
-->
注意到BaseMainAction:
public String execute() {
try {
   return this.executeMethod(this.getAction());
} catch (Exception e) {
   logger.error(e);
   this.addActionError(this.getText("error.msg"));
   return ERROR;
}
}
而在BaseAction:private String action = "index";
public String index() {
String[] userSign = new String[3];
userSign[0] = this.getUserSession().getSignDetail()[0];//從UserSession的SignDetail數組中把三個對象拿出來!
userSign[1] = this.getUserSession().getSignDetail()[1];
userSign[2] = this.getUserSession().getSignDetail()[2];
userSign = BBSCSUtil.filterUserSign(userSign, this.getSysConfig().isSignUseHtml(), this.getSysConfig()
    .isSignUseUBB(), this.getSysConfig().isSignUseSmile());
this.setUserSign0(userSign[0]);
this.setUserSign1(userSign[1]);
this.setUserSign2(userSign[2]);
return SUCCESS;
}

發佈了76 篇原創文章 · 獲贊 4 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章