1,键入http://localhost:8080/JForum/;进入欢迎页面index.htm
2,index.htm有一个自动跳转;跳转到forums/list.page
3,服务器截获forums/list.page请求;交给一个名为net.jforum.JForum的Servlet处理
4,如果名叫net.jforum.JForum的Servlet是第一次启动,先要执行其init()方法。在该方法中:
4.1调用父类JForumBaseServlet的init()方法。
(1)装载/WEB-INF/log4j.xml日志文件
(2)使用ConfigLoader类装载系统全局变量属性文件/WEB-INF/config/SystemGlobals.properties和数据库属性文件/WEB_INF/config/database/mysql/mysql.properties
(3)使用ConfigLoader类启动缓存引擎即net.jforum.cache.DefaultCacheEngine类的对象
(4)创建FreeMarker的配置对象Configuration
(5)创建FreeMarker的模板加载器FileTemplateLoader
(6)在配置对象Configuration设置模板加载器FileTemplateLoader
(7)借助ModulesRepository类在缓存中加载模块库,缓存中模块库对应的键名是entries,对应的值类型是Properties,该Properties对象是通过ConfigLoader的loadModulesMapping方法加载modulesMapping.properties文件实现的。这样就实现了字符串与特定Action类的映射。
(8)加载urlPattern.properties文件、templatesMapping.properties文件、加载国际化属性文件
(9)在JForumExecutionContext设置FreeMarker的配置对象Configuration。
4.2调用父类JForumBaseServlet的startApplication()方法
(1)借助SystemGlobals类装载WEB-INF/config/database/generic/generic_queries.sql文件
(2)借助SystemGlobals类装载WEB-INF/config/database/generic/mysql.sql文件
(3)借助SystemGlobals类装载WEB-INF/config/quartz-jforum.properties
(4)借助ConfigLoader类的createLoginAuthenticator()方法创建登录认证器net.jforum.sso.DefaultLoginAuthenticator类的对象,并把该对象添加到一个SystemGlobals对象的objectProperties属性中。该属性类型是Map。
(5)借助ConfigLoader类的loadDaoImplementation()方法创建DataAccessDriver类的子类GenericDataAccessDriver对象
(6)借助ConfigLoader类的listenForChanges()方法加载配置文件监听器
(7)借助ConfigLoader类startSearchIndexer()方法启动搜索索引器
(8)借助ConfigLoader类的startSummaryJob()方法启动摘要任务
4.3调用ForumStartup类的startDatabase()方法,在连接池中生成一个连接对象
(1)创建一个net.jforum.PooledConnection类的数据库连接池对象,该类是C3P0PooledConnection的一个子类空实现。
(2)通过连接池对象获取一个连接对象
(3)将连接对象放入到连接池中
4.4获取连接对象,设置是否自动提交,修复MySql问题
4.5创建JForumExecutionContext对象,并将该对象存储到ThreadLocal中
4.6将在4.3步骤中创建的连接对象存储到JForumExecutionContext对象中
4.7因为JForumExecutionContext对象内容已经更新,所以再次存储JForumExecutionContext对象到ThreadLocal中
4.8调用ForumStartup类的startForumRepository方法
(1)借助GenericDataAccessDriver对象创建GenericForumDAO对象
(2)借助GenericDataAccessDriver对象创建GenericCategoryDAO对象
(3)借助GenericDataAccessDriver对象创建GenericConfigDAO对象
(4)将上述三个DAO对象存储到一个ForumRepository对象中,并将该ForumRepository对象存储到缓存中
4.9调用RankingRepository类的loadRanks()方法创建GenericRankingDAO对象,并存储到缓存中
4.10调用SmiliesRepository类的loadSmilies()方法创建GenericSmilieDAO对象,并存储到缓存中
4.11调用BanlistRepository类的loadBanlist()方法创建GenericBanlistDAO对象,并存储到缓存中。该表可以阻止不受欢迎的用户对论坛的访问。
5,名叫net.jforum.JForum的Servlet执行service()方法
5.1取得JForumExecutionContext对象
5.2创建WebRequestContext对象
(1)获取请求的方法类型并转换成大写(GET/POST)
(2)获取请求的上下文路径,即web项目的名称,比如:/JForum
(3)提取uri剔除原始uri中含有的上下文部分,比如:/forums/list.page
(4)获取编码方式,即UTF-8
(5)获取servlet截获的后缀名,比如:.page
(6)如果是GET请求并且查询字符串为空并且以page为后缀,
a.设定请求编码
b.调用本类的parseFriendlyURL()方法,对URI进行分析。
b1.将/forums/list.page转换成forums.list.0
b2.在本类的Map中存储"modules"--"list"与"actions"与"list"的映射
(7)设定请求编码
(8)设定容器编码
5.3创建WebResponseContext对象
5.4检查数据库状态
(1)通过net.jforum.JForum的isDatabaseUp标记观察数据库是否启动。
(2)如果没有启动,调用ForumStartup类的startDatabase()方法启动数据库————
(3)创建一个net.jforum.PooledConnection类的数据库连接池对象,该类是C3P0PooledConnection的一个子类空实现。
(4)通过连接池对象获取一个连接对象
(5)将连接对象放入到连接池中
5.5创建JForumContext类对象,该对象持有/JForum上下文路径、servlet截获的后缀名、request对象、response对象。
5.6将上述JForumContext类对象存储到JForumExecutionContext中,并更新到ThreadLocal。
5.7借助ControllerUtils的refreshSession()方法刷新用户UserSession
(1)借助SessionFacade的getUserSession()方法返回UserSession对象。本质上还是通过JForumExecutionContext获取UserSession对象
(2)通过JForumExecutionContext获取RequestContext对象
(3)如果获取UserSession对象为空
a.创建UserSession对象
b.注册UserSession基本信息,包括访问本站的开始时间,最后访问时间,设置UserId(如果还未登录,设置匿名用户id,该id是1)。
c.设置会话id
d.设置用户IP
e.借助SessionFacade类的makeUnlogged()方法清除登录StandardSessionContext中的logged属性
f.判断是否是机器人发送的请求,如果不是
f1.判断是否是单点登录,如果不是
f11.判断是否是自动登录,如果不是
f111.调用UserSession类的makeAnonymous()方法,进行匿名登录的设置。在该方法中:
step1:调用UserSession类的registerBasicInfo()方法在UserSession中设置startTime、lastVisit、userid属性的值。其中userid设置为匿名用户id,其值为1。
step2:借助ControllerUtils类的addCookie()方法设置名为jforumAutoLogin的cookie值为null。
step3:借助ControllerUtils类的addCookie()方法设置名为jforumUserId的cookie值为1。
step4:借助SessionFacade类的makeUnlogged()方法擦除“logged”属性。
g.调用SessionFacade类的add()方法添加用户userSession。在该方法中:
g1.调用DefaultCacheEngine类的add()方法,将sessionid与usersession之间的映射关系存储到缓存中。存储的机制是缓存里有一个Map,该Map与字符串"sessions"之间有一个映射关系。通过字符串"sessions"可以取得该Map。这个Map对象存储着sessionid与usersession之间的映射。"sessions"存储在SessionFacade.FQN中。
g2.匿名用户登录的数量加1,实现的具体细节是:
判断是否是机器人登录,如果不是
g21.判断是否是匿名用户登录,如果是
g211.调用SessionFacade类的changeUserCount方法,使匿名用户登录的数量加1。在该方法中:
step1:调用DefaultCacheEngine类的get方法取出当前匿名用户的登录数量。取出的机制是缓存里有一个Map,该Map与字符串"sessions/count"有一个映射关系。通过字符串"sessions/count"可以取得该Map。"sessions/count"存储在SessionFacade.FQN_COUNT中。这个Map里存储着一些数值,其中就有匿名用户登录的数量。该值与字符串" anonymousCount"之间有一个映射关系。" anonymousCount"存储在SessionFacade.ANONYMOUS_COUNT中。
step2:数量加1。changeUserCount方法的第二个参数表示数量增减的标记,登录加1,登出减1。
step3:数量改变后,重新存入缓存。
5.8在FreeMarker的SimpleHash中设置登录标记"logged"。
5.9借助SecurityRepository类的load方法加载用户权限,实际上创建了一个PermissionControl对象。在缓存中有一个"security"字符串与一个存储权限的Map映射。在该Map中,维护着userid与该用户对应的PermissionControl对象间的映射。在PermissionControl对象中,存储着该用户的角色列表。
5.10借助ControllerUtils类的prepareTemplateContext()方法,将模板的运行环境存储到SimpleHash中。
5.11依据"module"值,获取对应的Action的全限定类名称,即net.jforum.view.forum.ForumAction。
5.12通过远程访问的IP地址,借助JForum类的shouldBan()方法判定是否为不受欢迎的用户。
5.13如果不在阻止的用户列表中,就把模块名即module的值与模块的方法名即action的值存储到SimpleHash中。
5.14在SimpleHash中添加语言类型、用户Session、Http请求Request对象req、外覆类ResponseContext对象response。
5.15调用JForum类的processCommand()方法。在该方法中:
(1)借助JForum类的retrieveCommand()方法,创建module对应的Action的实例,即net.jforum.view.forum.ForumAction类的对象。
(2)调用父类Command的process()方法处理特定的业务逻辑。在该方法中:
a.获取处理特定业务逻辑的方法名,即"action"的值"list"。
b.调用net.jforum.view.forum.ForumAction类的list()方法。
c.借助JForumExecutionContext.templateConfig().getTemplate(
new StringBuffer(SystemGlobals.getValue(ConfigKeys.TEMPLATE_DIR)).
append('/').append(this.templateName).toString(),"UTF-8");装载模板Template对象。注意:"UTF-8"否则中文无法正常显示。
(3)Template对象输出。
5.16调用JForum类的handleFinally方法,如果检测到重定向URL不为空,就执行重定向操作。
来源:CSDN
作者:deadspace
链接:https://blog.csdn.net/deadspace/article/details/6117316