对天乙社区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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值