`
qinwei6060
  • 浏览: 6934 次
  • 性别: Icon_minigender_1
  • 来自: 南京
文章分类
社区版块
存档分类
最新评论

Jforum请求流程

    博客分类:
  • Java
阅读更多

请求的流程也是在类net.jforum.JForum.java中:
public class JForum extends JForumBaseServlet {	
	public void service(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException
	{
		Writer out = null;
		JForumContext forumContext = null;
		RequestContext request = null;
		ResponseContext response = null;
		String encoding = SystemGlobals.getValue(ConfigKeys.ENCODING);

		try {
			// Initializes the execution context
			JForumExecutionContext ex = JForumExecutionContext.get();

			request = new WebRequestContext(req);
            response = new WebResponseContext(res);

			this.checkDatabaseStatus();

            forumContext = new JForumContext(request.getContextPath(),
                SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION),
                request,
                response
            );
            ex.setForumContext(forumContext);

            JForumExecutionContext.set(ex);
            // 准备freemarker数据模型
			// Setup stuff
			SimpleHash context = JForumExecutionContext.getTemplateContext();
			
			ControllerUtils utils = new ControllerUtils();
			utils.refreshSession();
			
			context.put("logged", SessionFacade.isLogged());
			
			//加载当前用户的权限到cache中
			// Process security data
			SecurityRepository.load(SessionFacade.getUserSession().getUserId());

			utils.prepareTemplateContext(context, forumContext);
			//取得请求的模块
			String module = request.getModule();
			//取得模块对应的处理类
			// Gets the module class name
			String moduleClass = module != null 
				? ModulesRepository.getModuleClass(module) 
				: null;
			//请求中模块为空,向客户端返回找不到页面的错.
			if (moduleClass == null) {
				// Module not found, send 404 not found response
				response.sendError(HttpServletResponse.SC_NOT_FOUND);
			}
			else {
				//判断客户端地址是否是被禁止了
				boolean shouldBan = this.shouldBan(request.getRemoteAddr());
				
				if (!shouldBan) {
					//正常的请求
					context.put("moduleName", module);
					context.put("action", request.getAction());
				}
				else {
					//被禁止的请求,更改请求的模块为forums,action为banded,即请求路径为:/forums/banned
					moduleClass = ModulesRepository.getModuleClass("forums");
					context.put("moduleName", "forums");
					((WebRequestContext)request).changeAction("banned");
				}
				
				if (shouldBan && SystemGlobals.getBoolValue(ConfigKeys.BANLIST_SEND_403FORBIDDEN)) {
					//被禁止的请求,向客户端返回禁止访问页面
					response.sendError(HttpServletResponse.SC_FORBIDDEN);
				}
				else {
					//正常的请求,将请求代理为具体的命令执行
					context.put("language", I18n.getUserLanguage());
					context.put("session", SessionFacade.getUserSession());
					context.put("request", req);
					context.put("response", response);
					
					out = this.processCommand(out, request, response, encoding, context, moduleClass);
				}
			}
		}
		catch (Exception e) {
			//异常处理:设置允许事务回滚,向异常页面输出异常信息
			this.handleException(out, response, encoding, e, request);
		}
		finally {
			this.handleFinally(out, forumContext, response);
		}		
	}
	private void handleFinally(Writer out, JForumContext forumContext, ResponseContext response) throws IOException
	{
		//关闭输出流
		try {
			if (out != null) { out.close(); }
		}
		catch (Exception e) {
		    // catch close error 
		}
		//获取重定向页面
		String redirectTo = JForumExecutionContext.getRedirectTo();
		//对数据库连接进行事务回滚或提交,并释放连接
		JForumExecutionContext.finish();
		
		if (redirectTo != null) {
			//将请求重定向到指定页
			if (forumContext != null && forumContext.isEncodingDisabled()) {
				response.sendRedirect(redirectTo);
			} 
			else {
				response.sendRedirect(response.encodeRedirectURL(redirectTo));
			}
		}
	}

	private void handleException(Writer out, ResponseContext response, String encoding, 
		Exception e, RequestContext request) throws IOException
	{
		//设置允许事务回滚
		JForumExecutionContext.enableRollback();
		//向异常页面输出异常信息
		if (e.toString().indexOf("ClientAbortException") == -1) {
			response.setContentType("text/html; charset=" + encoding);
			if (out != null) {
				new ExceptionWriter().handleExceptionData(e, out, request);
			}
			else {
				new ExceptionWriter().handleExceptionData(e, new BufferedWriter(new OutputStreamWriter(response.getOutputStream())), request);
			}
		}
	}
	/**
	 * 判断用户地址,或者用户账号被列入禁止列表
	 */
	private boolean shouldBan(String ip)
	{
		Banlist b = new Banlist();
		
		b.setUserId(SessionFacade.getUserSession().getUserId());
		b.setIp(ip);
		
		return BanlistRepository.shouldBan(b);
	}
	private Writer processCommand(Writer out, RequestContext request, ResponseContext response, 
			String encoding, SimpleHash context, String moduleClass) throws Exception
	{
		//根据模块的类名,实例化相应的命令,一个请求对应一个实例,利用反射生成类的实例
		// Here we go, baby
		Command c = this.retrieveCommand(moduleClass);
		Template template = c.process(request, response, context);

		//不是重定向请求
		if (JForumExecutionContext.getRedirectTo() == null) {
			String contentType = JForumExecutionContext.getContentType();
			
			if (contentType == null) {
				contentType = "text/html; charset=" + encoding;
			}
			
			response.setContentType(contentType);
			
			//如果不是请求的二进程文件,向输出流中输出模板处理的结果,即返回请求的结果页面
			// Binary content are expected to be fully 
			// handled in the action, including outputstream
			// manipulation
			if (!JForumExecutionContext.isCustomContent()) {
				out = new BufferedWriter(new OutputStreamWriter(response.getOutputStream(), encoding));
				template.process(JForumExecutionContext.getTemplateContext(), out);
				out.flush();
			}
		}
		
		return out;
	}
}

public class ControllerUtils
{
	/**
	 * 用户没有登录:如果配置了自动登录,则进行自动登录,否则则生成一个匿名用户登录
	 */
	public void refreshSession()
	{
		UserSession userSession = SessionFacade.getUserSession();
		RequestContext request = JForumExecutionContext.getRequest();
	
		if (userSession == null) {// 如果用户还未登录
			userSession = new UserSession();
			userSession.registerBasicInfo();
			userSession.setSessionId(request.getSessionContext().getId());
			userSession.setIp(request.getRemoteAddr());
			SessionFacade.makeUnlogged();
	
			if (!JForumExecutionContext.getForumContext().isBot()) {
				// Non-SSO authentications can use auto login
				if (!ConfigKeys.TYPE_SSO.equals(SystemGlobals.getValue(ConfigKeys.AUTHENTICATION_TYPE))) {// 不是SSO认证
					if (SystemGlobals.getBoolValue(ConfigKeys.AUTO_LOGIN_ENABLED)) {// 如果配置了自动登录
						this.checkAutoLogin(userSession);
					} else {// 没有配置自动登录,生成一个匿名用户
						userSession.makeAnonymous();
					}
				} else {//转向SSO认证
					this.checkSSO(userSession);
				}
			}
	
			SessionFacade.add(userSession);
		} else if (ConfigKeys.TYPE_SSO.equals(SystemGlobals.getValue(ConfigKeys.AUTHENTICATION_TYPE))) {//用户已经登录,且SSO认证
			SSO sso;
			
			try {
				sso = (SSO) Class.forName(SystemGlobals.getValue(ConfigKeys.SSO_IMPLEMENTATION)).newInstance();
			}
			catch (Exception e) {
				throw new ForumException(e);
			}
	
			// If SSO, then check if the session is valid
			if (!sso.isSessionValid(userSession, request)) {//session无效
				SessionFacade.remove(userSession.getSessionId());
				refreshSession();
			}
		} else {// 更新用户在线时长
			SessionFacade.getUserSession().updateSessionTime();
		}
	}
}

核心的处理请求的命令类
public abstract class Command 
{
	public Template process(RequestContext request, ResponseContext response, SimpleHash context)
	{
		this.request = request;
		this.response = response;
		this.context = context;
		//取得对模块的动作,对应为模块处理类的具体方法名
		String action = this.request.getAction();

		if (!this.ignoreAction) {
			try {
				//以无参形式执行请求对应的具体类的某个方法
				this.getClass().getMethod(action, NO_ARGS_CLASS).invoke(this, NO_ARGS_OBJECT);
			}
			catch (NoSuchMethodException e) {		
				//如果请求的方法不存在,默认执行list方法
				this.list();		
			}
			catch (Exception e)
            {
                throw new ForumException(e);
			}
		}

		if (JForumExecutionContext.getRedirectTo() != null) {
			//是重定向请求
			this.setTemplateName(TemplateKeys.EMPTY);
		}
		else if (request.getAttribute("template") != null) {
			//从请求中取得模板名,从缓存中取得模板名对应的具体页面,具体的对应关系在系统初始化时从templatesMapping.properties文件加载,并放到缓存中
			this.setTemplateName((String)request.getAttribute("template"));
		}
		//如果请求的是二进制文件,返回
		if (JForumExecutionContext.isCustomContent()) {
			return null;
		}
		//如果没找到缓存对应的页面,抛出动作对应的模板未找到的未常
		if (this.templateName == null) {
			throw new TemplateNotFoundException("Template for action " + action + " is not defined");
		}

        try {
        	//返回页面的模板
            return JForumExecutionContext.templateConfig().getTemplate(
                new StringBuffer(SystemGlobals.getValue(ConfigKeys.TEMPLATE_DIR)).
                append('/').append(this.templateName).toString());
        }
        catch (IOException e) {
            throw new ForumException( e);
        }
    }
}
分享到:
评论

相关推荐

    Jforum相关文档和PPT

    这个压缩包文件包含了关于Jforum的多个重要知识点,包括配置、初始化流程、处理请求的MVC架构、数据库访问实现、文件监控、缓存机制以及权限控制等内容。下面将对这些主题进行详细阐述。 首先,Jforum的配置是论坛...

    jforum说明文档 源码解析 单点登录 jforum缓存

    Jforum的控制器基于Struts框架,提供了一种灵活的方式来组织和管理应用的流程。 **数据库和重要配置文件** Jforum的数据库设计是其核心部分,包含了用户信息、论坛板块、主题、帖子等数据表。配置文件如`database....

    jforum3源代码

    **JForum3源代码详解** JForum是一款广受欢迎的开源论坛软件,以其强大的功能、友好的用户界面和清晰的代码结构...无论是对Java框架的深入理解,还是对Web应用开发流程的整体把握,JForum3都是一份宝贵的教育资源。

    jforum2论坛源码

    5. **二次开发流程**:包括阅读源码,理解业务逻辑,使用版本控制系统(如Git)获取最新代码,编写单元测试,修改代码,构建新的jar包,部署并验证修改。这个过程涉及到软件开发的完整生命周期。 6. **数据库设计**...

    jforum二次开发 详解 BBS开源安装

    2. 控制器(Controller):处理用户的请求,协调模型和视图之间的交互。 3. 视图(View):展示论坛内容,如帖子、板块、用户信息等,通常使用JSP页面实现。 4. 服务层(Service):封装业务逻辑,如用户注册、发帖...

    jforum-2.1.8.zip

    1. **Struts框架**:JForum采用Struts作为MVC框架,处理HTTP请求并控制业务流程。 2. **Spring框架**:用于依赖注入,管理Bean,实现事务控制等。 3. **Hibernate**:作为ORM框架,负责数据持久化,与数据库进行交互...

    jforum开源论坛 官方源代码(2.1.9)

    总的来说,JForum开源论坛的2.1.9版本是一份宝贵的教育资源,对于Java Web开发者而言,它不仅提供了实践机会,还能帮助理解Web应用的架构设计和开发流程。通过研究源代码,我们可以提升自己的编程技巧,理解如何构建...

    JForum Source Analysis JForum开源论坛的源码分析

    处理请求流程 - **前端处理器**:`JForum` 类作为前端处理器,负责接收客户端的请求,并根据请求内容执行相应的操作。 - **初始化流程**:`JForumBaseServlet` 类中定义了 `init` 方法,该方法在Servlet初始化时被...

    jforum3 JAVA论坛源码

    本文将深入探讨Jforum3的核心特性、开发环境以及运行流程。 首先,Jforum3采用Java技术栈,这使得它具备跨平台的特性,可以在多种操作系统上运行。Java的面向对象特性也使得代码结构清晰,易于维护和扩展。同时,...

    jforum-2.5.0安装包+安装方式.rar

    **JForum 2.5.0 安装详解** JForum 是一个开源的、基于Java的Web论坛系统,提供强大的讨论板功能...在实际操作过程中,可能还需要处理一些特定的错误或配置问题,但基本流程如上所述,希望能为你提供一个清晰的指导。

    开源jsp论坛jforum-2.1.9源码带mysql数据库文件

    总之,开源论坛jforum-2.1.9源码提供了丰富的学习资源,无论是对JSP、Servlet、JavaBean技术的实践,还是对MySQL数据库管理的理解,或是对Web应用开发流程的掌握,都具有很高的学习价值。对于希望深入理解Java Web...

    JForum-2.1.4.rar_JForum-2.1.4_jforum_jsp_jsp struts_struts

    2. **配置驱动**:通过XML配置文件定义请求映射和业务流程,提高了代码的可维护性。 3. **拦截器**:利用拦截器机制,可以添加额外的功能,如日志、事务管理等,无需改动核心代码。 4. **插件体系**:Struts支持各种...

    jforum序列图和ER图

    "jforum.gif"可能是JForum系统的整体工作流程图或者某一特定功能的简略表示。"jforum.htm"可能是一个介绍JForum的网页,包含了系统的基本信息和使用指南。"jforum_model.vsd"可能是一个Visio文档,用于绘制更复杂的...

    [论坛社区]JForum开源论坛 2.1.6_jforum216.zip

    【JForum开源论坛2.1.6】是一个基于Java技术和JSP(JavaServer Pages)的开源讨论论坛系统,适用于学生毕业设计和学习实践...同时,参与开源项目也可以让你接触到实际的开发流程,学习到团队合作和代码质量管理的经验。

    jforum序列图 and ER图

    在jforum的序列图中,我们可以看到各个组件如何协同工作来完成特定的业务流程,例如用户登录、发表帖子等。序列图通过时间轴展示了消息的传递顺序,有助于理解系统中各组件间的动态交互关系。 jforum的序列图可能...

    [论坛社区]JForum开源论坛 2.1.6_jforum216(毕设 + 课设).zip

    JForum是一款基于Java技术开发的开源论坛系统,...通过分析和修改JForum的源代码,学生可以深入理解Web应用的开发流程,掌握用户认证、权限控制、数据持久化等核心概念,对提升编程技能和理解Web系统架构有极大的帮助。

    java源码:Java论坛系统 JForum.zip

    **Java源码:Java论坛系统 JForum** JForum是一款基于Java技术开发的开源论坛系统,以其高效、稳定和可扩展性而闻名。...通过深入研究其源码,开发者可以提升自己的Java技术水平,了解Web应用的完整开发流程。

    仿照小米商城做的java web购物网站.zip

    这个描述暗示了开发者需要对电子商务流程有深入理解,并能利用Java Web技术实现这些功能。 【标签】"java"表明该项目的核心编程语言是Java,这包括了Servlet、JSP、Spring MVC、Hibernate等Java Web开发框架。Java...

    java开源包1

    集中管理请求参数与参数映射 以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息...

    java开源包11

    集中管理请求参数与参数映射 以运行时异常的方式来管理错误的响应 使用泛型来做强类型编程 多协议扩展支持(REST, RPC, SOAP, etc) Rails3消息队列系统 Sidekiq Sidekiq 为 Rails 3 应用程序提供一个高效的消息...

Global site tag (gtag.js) - Google Analytics