您的位置:首页 > 其它

对天乙社区bbscs8实现的详细分析十六

2008-07-14 11:32 579 查看
加根Hr,其它类似,我们重点分析如下:
<s:iterator id="b1" value="%{boardList}">
<li>
<s:if test="%{urlRewrite}">
<a href="javascript:;" onclick="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:;" onclick="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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: