一对一免费咨询: 13913005726 025-66045668

文/For A

怎么才算好的源码分析呢?当然我这个肯定不算。我想大概分为几个层面吧,写写注释那算最基本的了,写写要点思路和难点,算是还不错拉,再难的就是跳出源码举一反三,形成自己的一套思路吧。

这次针对的是jforum2.1.8,大概jforum团队已经没心情理这个版本了,都冲着jforum3去了。选择这个版本,主要是因为jforum在java论坛类应用中算是佼佼者了,很多人都拿这个来做二次开发,而jforum3使用的是另外一套架构了,而且还没完全release,所以斟酌一下,还是选择这个经典的版本。

关于jforum的介绍网上已经很多了,这里也简单抄录一段:JForum 是一个功能强大 ,易于管理的论坛。它的设计完全遵从MVC设计模式,能够在任何Servlet容器与EJB服务器上运行。而且可以轻松的定制与扩展JForum论坛。

上面这段简述还是中肯的。另外,jforum是模仿phpbb写的,使用的是classic-blue风格,但不能自己选择风格,要的话只能自己修改了。

再说几句,说jforum比较优秀是因为java开源的论坛系列精品少,而且jforum的bug也真的不少,不信试试就知道了。不过作为一个成型的组件,功能强大并且适合二次开发,还是应该列入考虑范围的。

不管怎样,jforum是个不错的学习范本,至少让你觉得写个山寨框架不是什么难事,而事实也的确是这样的。重要的一点是,不要轻易拿出来害人就是了:)这里先列举出可能一些分析点:

web.xml

初始化流程

处理请求流程(mvc)

文件监控

缓存实现

数据库访问实现

权限控制

首先了解一个web应用,首要的就是知道处理流程。首先来看看入口web.xml,里边的内容还是挺清晰的,可以看到里边有个监听器ForumSessionlistener,*.page的过滤器ClickstreamFilter,还有2个*.page的处理器,其中InstallServlet是安装相关的,JForum则是前端处理器。基本上整个流程就是client request - ForumSessionlistener - ClickstreamFilter - JForum - server response.

ForumSessionlistener实现了HttpSessionlistener接口,但是只是对session destory做了处理,在这个过程中,保存session的历史记录到DB,并清除用户信息和相关的security信息。

ClickstreamFilter实现了Filter接口,主要的任务就交给BotChecker了,是用来检测client是不是一个robot来的。

主要的工作还是在JForum上面,不过先来看看jforum是怎么检测robot的?

BotChecker只有一个静态工具方法isBot,首先是检测是否请求robot.txt(这是标准的robot协议文件),接下去判断User-Agent头部,最后是判断remotehost。而已知的robot都是写在文件clickstream-jforum.xml里边的(包括agent和host),并通过ConfigLoader加载进来的(SAX方式)。

可以看到JForum和InstallServlet都继承了JForumBaseServlet这个HttpServlet,而JForumBaseServlet包括2个重要的方法init和startApplication。众所周知,init是servlet初始化时调用的方法,JForumBaseServlet里边的init方法的流程是:

调用父类的init(正常情况这是必须调用的) - 配置log4j - startSystemglobals(加载全局参数配置SystemGlobals.properties - 加载数据库配置database.driver.config(如mysql就是WEB-INF/config/database/mysql/mysql.properties) - 加载自定义配置(默认的是jforum-custom.conf)) - 配置缓存引擎 - 配置freemarker模板引擎 - 加载模块配置modulesMapping.properties - 加载url映射配置urlPattern.properties - 加载I18n配置(languages/*) - 加载页面映射配置(templatesMapping.properties) - 加载BBcode配置bb_config.xml - 结束

jforum实现了自己的mvc,整个mvc的脉络就是client request - 解析url(urlPattern.properties),获取module/action/param - 通过module获取相应的module class,并通过action识别并调用相应的方法(modulesMapping.properties) - 使用dao完成业务逻辑 - 调用template进行渲染(templatesMapping.properties),其实整个mvc和struts没什么两样的,具体的流程以后再提。

JForumBaseServlet里边的startApplication方法的流程是:

加载通用sql文件sql.queries.driver(就是/database/generic/generic_queries.sql) - 加载特定sql文件(如mysql就是/database/mysql/mysql.sql) - 加载Quartz定时任务配置 - 加载登录验证器(验证方式) - 加载Dao实现方式 - 加载文件修改监听器 - 加载查询索引管理器 - 加载定时统计任务

jforum实现了南京网店设计自己的orm,当然不是hibernate那种,是类似ibatis的那种sql 网站程序设计基础 mapping,并提供了多套的sql文件来实现数据库无关的特性,整个流程也是比较清晰的,加载数据库配置 - 加载sql mapping file - 设置DAO实现 - 通过named sql找到对应的sql(在*.sql里边对应着) - 运行出数据

继续重点。JForum的init流程如下:

JForumBaseServlet.init - JForumBaseServlet.startApplication - 启动数据库 - 预加载一些数据到缓存中(ForumRepository[Categories,Forums,同时在线最大人数,最后登录用户,注册用户数等等],用户等级,表情数据,屏蔽列表) - 结束

上面简单提到了Jforum处理请求的过程,现在在来看看这个过程,就是service方法,这次采用代码概要的方式展示:

// 初始化JForumExecutionContext

JForumExecutionContext ex = JForumExecutionContext.get();

// 包装request和response

request = new WebRequestContext(req);

response = new 新乡网站建设公司 WebResponseContext(res);

// 检查数据库状态

this.checkDatabaseStatus();

// 创建JForumContext并设置到JForumExecutionContext中去

.......

JForumExecutionContext.set(ex);

// 刷新session

utils.refreshSession();

// 加载用户权限

SecurityRepository.load(SessionFacade.getUserSession().getUserId());

// 预加载模板需要的上下文

utils.prepareTemplateContext(context, forumContext);

// 从request中解析module name

String module = request.getModule();

// module name - module class

String moduleClass = module != null ? ModulesRepository.getModuleClass(module) : null;

// 判断是否在ban list里边

......

boolean shouldBan = this.shouldBan(request.getremoteAddr());

// 主角出场

out = this.processCommand(out, request, response, encoding, context, moduleClass);

// 扫尾工作,例如db的rollback

this.handleFinally(out, forumContext, response);

processCommand会调用Command的process方法:湘潭网站建设公司

// 获取一个module实例(继承了Command)

Command c = this.retrieveCommand(moduleClass);

// 进入process

Template template = c.process(request, response, context);

// 这里开始是process方法

//获取action

String action = this.request.getAction();

//如果不是ignore的,就调用这个action

if (!this.ignoreAction) {this.getClass().getMethod(action, NO_ARGS_CLASS).invoke(this, NO_ARGS_OBJECT);}

//如果是转发的,就把TemplateName清空

if (JForumExecutionContext.getredirectTo() != null) {this.setTemplateName(TemplateKeys.EMPTY);}

//不是转发且attribute里边存在template,则设置为templateName

else if (request.getAttribute("template") != null) {this.setTemplateName((String)request.getAttribute("template"));}

//是否coustomContent?例如下载,验证码子类的不需要页面的操作

if (JForumExecutionContext.isCustomContent()) {return null;}

//返回一个template

return JForumExecutionContext.templateConfig().getTemplate(

new StringBuffer(SystemGlobals.getValue(ConfigKeys.TEMPLATE_DIR)).

append('/').append(this.templateName).toString());

}

// 从process出来,回到processCommand

// 设置content type

response.setContentType(contentType);

//生成页面并flush

if (!JForumExecutionContext.isCustomContent()) {

out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), encoding));

template.process(JForumExecutionContext.getTemplateContext(), out);

out.flush();

}

}

这是一般的流程,就像上面提到的customContent,就是要自己处理了,可以参考CaptchaAction.generate().


 


 南京牧狼文化传媒有限公司简介:


      牧狼传媒,牧者之心,狼者之性,以牧之谦卑宽容之心待人,以狼之团结无畏之性做事!


  公司注册资金100万,主营众筹全案服务、网站营销全案服务、网站建设、微信小程序开发、电商网店设计、H5页面设计、腾讯社交广告投放以及电商营销推广全案等相关业务,致力于为客户提供更有价值的服务,创造让用户满意的效果!


  为百度官方及其大客户、苏宁易购、金山WPS秀堂、美的、创维家电、新东方在线、伊莱克斯、宝丽莱等国内国外知名品牌服务过,服务经验丰富!同时,公司也是南京电子商务协会会员单位、猪八戒网官方认证签约服务商、江苏八戒服务网联盟、南京浦口文化产业联合会会员单位,可以为您提供更好的服务!


  主营项目:众筹全案服务、网站营销全案服务、网站建设、微信小程序开发、电商网店设计、H5页面设计、腾讯社交广告投放、竞价托管、网站优化、电商代运营等


  合作客户:百度、苏宁易购、饿了么、美的、创维家电、新东方在线、宝丽莱、金山WPS秀堂、伊莱克斯


  资质荣誉:百度商业服务市场2017年度最佳图片服务商、南京电子商务协会会员单位、猪八戒网官方认证签约服务商、江苏八戒服务网联盟、南京浦口文化产业联合会会员单位、八戒通TOP服务商、"易拍即合杯"H5创意大赛"三等奖"。



致力于为客户创造更多价值
13913005726 025-66045668
需求提交
电话咨询
在线咨询