天乙社区流程分析

来源:互联网 发布:js 获取网页源代码 编辑:程序博客网 时间:2024/05/07 16:04
2005-10-11 16:03:27
今天在天乙社区(http://bbscs.laoer.com)发表了关于这个社区开元项目bbscs6.0流程分析的文章。由于这个项目始终没有像样的文档,我决定为初学者提供些帮助,同时也想得到高人指点。这篇文章也是我近一个月来的学习总结,原文如下:
 
天乙社区使用了当下几种流行的j2ee技术,设计较为合理,我最近一边学习相关技术,一边研究,大概有了一个初步认识。
在此,与各位天乙fans共享,如有错误,恳请各位指正。

我们从一个实际的流程入手来分析。就拿社区首页这个链接说起吧。
在left.jsp中,社区首页的链接是这样的
<html:link action="/in" target="bbscs_mainFrame"><img src="images/line_01_2_copy.gif" align="absmiddle" border="0"><img src="images/i_option_copy.gif" align="absmiddle" border="0"><bean:message key="left.ToMainText"/></html:link>

这句话有两个关键点:
1、<bean:message key="left.ToMainText"/>
2、action="/in"

1是struts的view部分特性。
2是struts的controll部分。

我们分别来说,先来看看view。
<bean:message>用于输出Resource Bundle中的一条消息,配置在<message-resources>的key中。我们在Struts-config.xml中找到
<message-resources parameter="ApplicationResources" />
对应的ApplicationResources.properties.GBK文件中,我找到了“left.ToMainText=社区首页”这句。

接下来我们看看流程是怎么往下走的,就是controll部分。
在Struts-config.xml中,我们找到action="/in"对应的mapping是这么写的:
<action input="/error.jsp" path="/in" scope="request" type="com.laoer.bbscs.web.action.In">
<forward name="in" path="/in.jsp" />
</action>
com.laoer.bbscs.web.action.In是我们想要的action。
我们来看看这个文件
public class In extends BaseAction {

public ActionForward execute(ActionMapping actionMapping,
ActionForm actionForm,
HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) {
……
UserInfo ui = getUserCache().getUserInfoFromCache(uc.getId());
if (ui == null) {
errors.add("error.getusererror", new ActionError("error.getusererror"));
saveErrors(httpServletRequest, errors);
return actionMapping.findForward("error");
}
ui = getUserInfoService().doExp(ui);
……
return actionMapping.findForward("in");
}
}
经过一番处理之后,返回到"in"。它对应的页面是/in.jsp。
这样,struts就帮我们完成了一次旅程,我们从一个链接入手,得到了一个页面。这就是VC部分。

刚才说,在action里做了一些处理,那么究竟是如何处理的呢,我们得到的页面有可能需要某些动态数据,那么这些数据又从哪里来呢
这就是spring和hibernate的事情了,就是MVC的M部分。

举两个例子。还是这个in.java文件。
getUserCache()哪来的?它来自com.laoer.bbscs.web.action.TopBaseAction。
我们来看看这个幕后的类TopBaseAction
public class TopBaseAction
extends Action {

public TopBaseAction() {
super();
}

protected SysInfo getSysInfo() {
return SysInfo.getInstance();
}

protected Forbid getForbid() {
return Forbid.getInstance();
}

protected IUserInfoService getUserInfoService() {
return (IUserInfoService) AppContext.getInstance().getAppContext().getBean("userInfoService");
}
……
protected UserInfoCache getUserCache() {
return (UserInfoCache) AppContext.getInstance().getAppContext().getBean("userInfoCache");
}
……
}

}

原来getUserCache()要从spring的配置文件applicationContext.xml中去寻找"userInfoCache"这个Bean。那么这个Bean到底是什么呢?
在applicationContext.xml中,我找到了这句:
<bean id="userInfoCache" class="com.laoer.bbscs.sys.UserInfoCache">
<property name="userInfoService">
<ref local="userInfoService"/>
</property>
</bean>
好了,我们放下一切,去com.laoer.bbscs.sys.UserInfoCache里看看究竟。这里有我们想要的函数getUserInfoFromCache:
public UserInfo getUserInfoFromCache(long id) {
UserInfo ui = (UserInfo) CacheManager.getCache(1).get(String.valueOf(
id));
if (ui == null) {
ui = this.getUserInfoService().findUserInfoById(new Long(id));
CacheManager.getCache(1).add(String.valueOf(id), ui);
}
return ui;
}
CacheManager位于com.laoer.bbscs.sys,使缓存管理类。
这个类用到了CacheFactory,如下:
public class CacheManager {
……
static {
managers = new CacheManager[4];
for (int i = 0; i < managers.length; i++) {
managers[i] = new CacheManager();
}
}

public CacheManager() {
this.cache = CacheFactory.getInstance();
}
}

这个工厂又是怎么初始化的呢?
public class CacheFactory {
……

public synchronized static ICache getInstance() {
try {
return (ICache) Class.forName("com.laoer.bbscs.sys.SysOSCache").newInstance();
}
……
}

接着看这个SysOSCache类:
public SysOSCache() {
admin = new GeneralCacheAdministrator();
}
终于找到缓存机制的根源了,GeneralCacheAdministrator()是oscache-2.0.2.jar这个缓存工具中的函数。

追溯到了底,我们往回返。在in.java中:
UserInfo ui = getUserCache().getUserInfoFromCache(uc.getId());这句就是通过spring的控制反转,找到缓存处理的类,然后从缓存中提取用户信息。
这个例子强调了spring的作用,我们在举个例子,看看spring是怎么讲流程往后走,直到数据库的。

ui = getUserInfoService().doExp(ui);
相同的经验
getUserInfoService()-[TopBaseAction.java]->"userInfoService"-[applicationContext.xml]->"com.laoer.bbscs.business.service.UserInfoSeviceImp"

好,我们来看看UserInfoSeviceImp.java这个类
public class UserInfoSeviceImp
implements IUserInfoService {
……
public UserInfo doExp(UserInfo userinfo) {
userinfo.setExp( (int) ( (userinfo.getLoginTimes() / 4) +
userinfo.getArticleNum() +
(userinfo.getStayTime() / 3600000) +
userinfo.getExpression()));
return this.getUserInfoDAO().saveUserInfo(userinfo);
}
……
}
doExp这个函数是计算经验值的,计算完毕set到userinfo中,并将它入库。
入库就是getUserInfoDAO().saveUserInfo(userinfo);这么简单的一句。我们去看看它背后的信息。
public IUserInfoDAO getUserInfoDAO() {
return this.userInfoDAO;
}
在applicationContext.xml中:
<bean id="userInfoDAO" class="com.laoer.bbscs.dao.hibernate.UserInfoHibernateDAO">
<property name="sessionFactory">
<ref local="mySessionFactory"/>
</property>
</bean>

UserInfoHibernateDAO类中,找我们需要的函数saveUserInfo()
public UserInfo saveUserInfo(UserInfo userinfo) {
try {
getHibernateTemplate().saveOrUpdate(userinfo);
return userinfo;
}
catch (DataAccessException ex) {
return null;
}
}
getHibernateTemplate()是spring.jar工具中org.springframework.orm.hibernate.support.HibernateDaoSupport中的函数,
返回值是HibernateTemplate类型。用来简化我们处理数据库事务中的工作。
我们的数据库处理流程分析到此结束,回到in.java中,我么也就知道ui = getUserInfoService().doExp(ui);的意义了。
以上就是spring的功能。最后再简单说说hibernate。
getHibernateTemplate().saveOrUpdate(userinfo);之后,我们就再不用些什么了,全交给hibernate处理。
那么它又是如何工作的呢?
在applicationContext.xml中,我们找到:
<bean id="mySessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="mappingResources">
<list>
<value>com/laoer/bbscs/bean/UserInfo.hbm.xml</value>
……
我们还看看UserInfo.hbm.xml这个文件:
<class name="com.laoer.bbscs.bean.UserInfo" table="BBSCS_USERINFO">这是对应的类和对应的表的定义。
以下是对应的表的结构:
<param name="table">BBSCS_TABLEID</param>
<param name="column">IDValue</param>
<param name="id">1</param>
<param name="increment">15</param>
</generator>
</id>
<property column="UserName" length="20" name="username" not-null="true" type="string"/>
<property column="NickName" length="60" name="nickname" not-null="true" type="string"/>
……

到此,完成了流程的简单分析。

由于还处于学习中,水平有限,以上文字仅供参考,如有谬误,还望海涵,并希望你能寓于指点。
原创粉丝点击