jforum Action的基类

前言

在博客摘要里提到了,所有的基类的作用都是为了代码复用。java web程序,也不例外。


而java web程序,里面的基类代码复用,主要是复用什么呢?

答:主要是复用各种servlet对象。


除此之外,当前也会有一些共同的通用的业务方法需要复用,比如,web程序里,浏览器发出请求(数据),服务器要把所请求的数据发送到请求端的浏览器,所以可以复用这个响应数据的方法。



基类

package net.jforum;

import java.io.IOException;

import net.jforum.context.RequestContext;
import net.jforum.context.ResponseContext;
import net.jforum.exceptions.ForumException;
import net.jforum.exceptions.TemplateNotFoundException;
import net.jforum.repository.Tpl;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;
import net.jforum.util.preferences.TemplateKeys;
import freemarker.template.SimpleHash;
import freemarker.template.Template;

/**
 * Action类的基类,所有的自定义Action类都要继承该基类<p>
 * 
 * <code>Command</code> Pattern implementation.
 * All View Helper classes, which are intead to configure and processs
 * presentation actions must extend this class. 
 * 
 * @author Rafael Steil
 * @version $Id: Command.java,v 1.27 2007/07/28 14:17:11 rafaelsteil Exp $
 */
public abstract class Command 
{
	private static Class[] NO_ARGS_CLASS = new Class[0];
	private static Object[] NO_ARGS_OBJECT = new Object[0];
	
	private boolean ignoreAction;
	
	protected String templateName;
	protected RequestContext request;
	protected ResponseContext response;
	protected SimpleHash context;
	
	protected void setTemplateName(String templateName)
	{
		this.templateName = Tpl.name(templateName);
	}
	
	protected void ignoreAction()
	{
		this.ignoreAction = true;
	}
	
	/**
	 * Base method for listings. 
	 * May be used as general listing or as helper
	 * to another specialized type of listing. Subclasses
	 * must implement it to the cases where some invalid
	 * action is called ( which means that the exception will
	 * be caught and the general listing will be used )
	 */
	public abstract void list() ;
	
	/**
	 * Process and manipulate a requisition.
	 * @return <code>Template</code> reference
     * @param request WebContextRequest
     * @param response WebContextResponse
	 */
	public Template process(RequestContext request, ResponseContext response, SimpleHash context)
	{
		this.request = request;
		this.response = response;
		this.context = context;
		
		String action = this.request.getAction(); //获取请求url中的方法名(例如,ForumAction.list()方法)

		if (!this.ignoreAction) {
			try {
				this.getClass().getMethod(action, NO_ARGS_CLASS).invoke(this, NO_ARGS_OBJECT);
			}
			catch (NoSuchMethodException e) {		
				this.list();		
			}
			catch (Exception e)
            {
                throw new ForumException(e);
			}
		}
		
		if (JForumExecutionContext.getRedirectTo() != null) {
			this.setTemplateName(TemplateKeys.EMPTY);
		}
		else if (request.getAttribute("template") != null) {
			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());
//        }
		try {
			String sb = new StringBuffer(SystemGlobals.getValue(ConfigKeys.TEMPLATE_DIR)).append('/').append(this.templateName).toString();
            return JForumExecutionContext.templateConfig().getTemplate(sb);
        }
        catch (IOException e) {
            throw new ForumException( e);
        }
    }
}



总结:不知道为什么很多地方要提到命令模式,jforum里面的这个基类的原始注释也是这么介绍的,说使用了命令模式啊什么的。


其实,本质上,就是自定义Action类与基类的关系。



子类

/**
 * 论坛Action
 */
package net.jforum.view.forum;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.jforum.Command;
import net.jforum.JForumExecutionContext;
import net.jforum.SessionFacade;
import net.jforum.dao.DataAccessDriver;
import net.jforum.dao.ForumDAO;
import net.jforum.dao.ModerationDAO;
import net.jforum.entities.Forum;
import net.jforum.entities.MostUsersEverOnline;
import net.jforum.entities.UserSession;
import net.jforum.repository.ForumRepository;
import net.jforum.repository.SecurityRepository;
import net.jforum.security.SecurityConstants;
import net.jforum.util.I18n;
import net.jforum.util.preferences.ConfigKeys;
import net.jforum.util.preferences.SystemGlobals;
import net.jforum.util.preferences.TemplateKeys;
import net.jforum.view.admin.ModerationAction;
import net.jforum.view.forum.common.ForumCommon;
import net.jforum.view.forum.common.PostCommon;
import net.jforum.view.forum.common.TopicsCommon;
import net.jforum.view.forum.common.ViewCommon;

/**
 * 版块Action(例如,小说版)<p>
 * --------------------------------<p>
 * 如果一个请求url(例如,document.location = "forums/list.page";)中的模块是forums,那么就由该类来处理!<p>
 * 
 * 注:一个请求url,要注意两点,<br>
 * 1.是哪个模块,即由哪个XXXAction类来处理;<br>
 * 2.是哪个方法,即由该XXXAction类的这个方法来处理
 * @author Rafael Steil
 * @version $Id: ForumAction.java,v 1.76 2007/09/03 12:24:32 rafaelsteil Exp $
 */
public class ForumAction extends Command
{
	/**
	 * 进入版块页面(即论坛首页):列出所有的版块
	 * List all the forums (first page of forum index)?
	 */
	public void list()
	{
		this.setTemplateName(TemplateKeys.FORUMS_LIST); //"forums.list"

		this.context.put("allCategories", ForumCommon.getAllCategoriesAndForums(true));
		this.context.put("topicsPerPage", new Integer(SystemGlobals.getIntValue(ConfigKeys.TOPICS_PER_PAGE)));
		this.context.put("rssEnabled", SystemGlobals.getBoolValue(ConfigKeys.RSS_ENABLED));

		this.context.put("totalMessages", new Integer(ForumRepository.getTotalMessages()));
		this.context.put("totalRegisteredUsers", ForumRepository .totalUsers());
		this.context.put("lastUser", ForumRepository.lastRegisteredUser());

		SimpleDateFormat df = new SimpleDateFormat(SystemGlobals.getValue(ConfigKeys.DATE_TIME_FORMAT));
		GregorianCalendar gc = new GregorianCalendar();
		this.context.put("now", df.format(gc.getTime()));

		this.context.put("lastVisit", df.format(SessionFacade.getUserSession().getLastVisit()));
		this.context.put("forumRepository", new ForumRepository());

		// Online Users
		this.context.put("totalOnlineUsers", new Integer(SessionFacade.size()));
		int aid = SystemGlobals.getIntValue(ConfigKeys.ANONYMOUS_USER_ID);

		List onlineUsersList = SessionFacade.getLoggedSessions();

		// Check for an optional language parameter
		UserSession currentUser = SessionFacade.getUserSession();

		if (currentUser.getUserId() == aid) {
			String lang = this.request.getParameter("lang");

			if (lang != null && I18n.languageExists(lang)) {
				currentUser.setLang(lang);
			}
		}

		// If there are only guest users, then just register
		// a single one. In any other situation, we do not
		// show the "guest" username
		if (onlineUsersList.size() == 0) {
			UserSession us = new UserSession();

			us.setUserId(aid);
			us.setUsername(I18n.getMessage("Guest"));

			onlineUsersList.add(us);
		}

		int registeredSize = SessionFacade.registeredSize();
		int anonymousSize = SessionFacade.anonymousSize();
		int totalOnlineUsers = registeredSize + anonymousSize;

		this.context.put("userSessions", onlineUsersList);
		this.context.put("totalOnlineUsers", new Integer(totalOnlineUsers));
		this.context.put("totalRegisteredOnlineUsers", new Integer(registeredSize));
		this.context.put("totalAnonymousUsers", new Integer(anonymousSize));

		// Most users ever online
		MostUsersEverOnline mostUsersEverOnline = ForumRepository.getMostUsersEverOnline();

		if (totalOnlineUsers > mostUsersEverOnline.getTotal()) {
			mostUsersEverOnline.setTotal(totalOnlineUsers);
			mostUsersEverOnline.setTimeInMillis(System.currentTimeMillis());

			ForumRepository.updateMostUsersEverOnline(mostUsersEverOnline);
		}

		this.context.put("mostUsersEverOnline", mostUsersEverOnline);
	}

	public void moderation()
	{
		this.context.put("openModeration", true);
		this.show();
	}

	/**
	 * 获取子版块的所有帖子<p>
	 * Display all topics in a forum
	 */
	public void show()
	{
		int forumId = this.request.getIntParameter("forum_id");
		ForumDAO fm = DataAccessDriver.getInstance().newForumDAO();

		// The user can access this forum?
		Forum forum = ForumRepository.getForum(forumId);

		if (forum == null || !ForumRepository.isCategoryAccessible(forum.getCategoryId())) {
			new ModerationHelper().denied(I18n.getMessage("ForumListing.denied"));
			return;
		}

		int start = ViewCommon.getStartPage();

		List tmpTopics = TopicsCommon.topicsByForum(forumId, start);

		this.setTemplateName(TemplateKeys.FORUMS_SHOW);

		// Moderation
		UserSession userSession = SessionFacade.getUserSession();
		boolean isLogged = SessionFacade.isLogged();
		boolean isModerator = userSession.isModerator(forumId);

		boolean canApproveMessages = (isLogged && isModerator 
			&& SecurityRepository.canAccess(SecurityConstants.PERM_MODERATION_APPROVE_MESSAGES));

		Map topicsToApprove = new HashMap();

		if (canApproveMessages) {
			ModerationDAO mdao = DataAccessDriver.getInstance().newModerationDAO();
			topicsToApprove = mdao.topicsByForum(forumId);
			this.context.put("postFormatter", new PostCommon());
		}

		this.context.put("topicsToApprove", topicsToApprove);

		this.context.put("attachmentsEnabled", SecurityRepository.canAccess(SecurityConstants.PERM_ATTACHMENTS_ENABLED,
		        Integer.toString(forumId))
		        || SecurityRepository.canAccess(SecurityConstants.PERM_ATTACHMENTS_DOWNLOAD));

		this.context.put("topics", TopicsCommon.prepareTopics(tmpTopics));
		this.context.put("allCategories", ForumCommon.getAllCategoriesAndForums(false));
		this.context.put("forum", forum);
		this.context.put("rssEnabled", SystemGlobals.getBoolValue(ConfigKeys.RSS_ENABLED));
		this.context.put("pageTitle", forum.getName());
		this.context.put("canApproveMessages", canApproveMessages);
		this.context.put("replyOnly", !SecurityRepository.canAccess(SecurityConstants.PERM_REPLY_ONLY, Integer
		        .toString(forum.getId())));

		this.context.put("readonly", !SecurityRepository.canAccess(SecurityConstants.PERM_READ_ONLY_FORUMS, Integer
		        .toString(forumId)));

		this.context.put("watching", fm.isUserSubscribed(forumId, userSession.getUserId()));

		// Pagination
		int topicsPerPage = SystemGlobals.getIntValue(ConfigKeys.TOPICS_PER_PAGE);
		int postsPerPage = SystemGlobals.getIntValue(ConfigKeys.POSTS_PER_PAGE);
		int totalTopics = forum.getTotalTopics();

		ViewCommon.contextToPagination(start, totalTopics, topicsPerPage);
		this.context.put("postsPerPage", new Integer(postsPerPage));

		TopicsCommon.topicListingBase();
		this.context.put("moderator", isLogged && isModerator);
	}

	// Make an URL to some action
	private String makeRedirect(String action)
	{
		String path = this.request.getContextPath() + "/forums/" + action + "/";
		String thisPage = this.request.getParameter("start");

		if (thisPage != null && !thisPage.equals("0")) {
			path += thisPage + "/";
		}

		String forumId = this.request.getParameter("forum_id");

		if (forumId == null) {
			forumId = this.request.getParameter("persistData");
		}

		path += forumId + SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION);

		return path;
	}

	// Mark all topics as read
	public void readAll()
	{
		String forumId = this.request.getParameter("forum_id");
		
		if (forumId != null) {
			Map tracking = SessionFacade.getTopicsReadTimeByForum();
			
			if (tracking == null) {
				tracking = new HashMap();
			}
			
			tracking.put(new Integer(forumId), new Long(System.currentTimeMillis()));
			SessionFacade.setAttribute(ConfigKeys.TOPICS_READ_TIME_BY_FORUM, tracking);
		}

		if (forumId != null) {
			JForumExecutionContext.setRedirect(this.makeRedirect("show"));
		}
		else {
			JForumExecutionContext.setRedirect(this.request.getContextPath() + "/forums/list"
		        + SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION));
		}
	}

	// Messages since last visit
	public void newMessages()
	{
		this.request.addParameter("from_date", SessionFacade.getUserSession().getLastVisit());
		this.request.addParameter("to_date", new Date());

		SearchAction searchAction = new SearchAction(this.request, this.response, this.context);
		searchAction.newMessages();
		
		this.setTemplateName(TemplateKeys.SEARCH_NEW_MESSAGES);
	}

	public void approveMessages()
	{
		if (SessionFacade.getUserSession().isModerator(this.request.getIntParameter("forum_id"))) {
			new ModerationAction(this.context, this.request).doSave();
		}

		JForumExecutionContext.setRedirect(this.request.getContextPath() + "/forums/show/"
			+ this.request.getParameter("forum_id") + SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION));
	}

	/**
	 * Action when users click on "watch this forum"
	 * It gets teh forum_id and userId, and put them into a watch_forum table in the database;
	 */
	public void watchForum()
	{
		int forumId = this.request.getIntParameter("forum_id");
		int userId = SessionFacade.getUserSession().getUserId();

		this.watchForum(DataAccessDriver.getInstance().newForumDAO(), forumId, userId);

		JForumExecutionContext.setRedirect(this.redirectLinkToShowAction(forumId));
	}

	public void banned()
	{
		this.setTemplateName(TemplateKeys.FORUMS_BANNED);
		this.context.put("message", I18n.getMessage("ForumBanned.banned"));
	}

	private String redirectLinkToShowAction(int forumId)
	{
		int start = ViewCommon.getStartPage();

		return this.request.getContextPath() + "/forums/show/" + (start > 0 ? start + "/" : "") + forumId
			+ SystemGlobals.getValue(ConfigKeys.SERVLET_EXTENSION);
	}

	/**
	 * 
	 * @param dao ForumDAO
	 * @param forumId int
	 * @param userId int
	 */
	private void watchForum(ForumDAO dao, int forumId, int userId)
	{
		if (SessionFacade.isLogged() && !dao.isUserSubscribed(forumId, userId)) {
			dao.subscribeUser(forumId, userId);
		}
	}

	/**
	 * Unwatch the forum watched.
	 */
	public void unwatchForum()
	{
		if (SessionFacade.isLogged()) {
			int forumId = this.request.getIntParameter("forum_id");
			int userId = SessionFacade.getUserSession().getUserId();

			DataAccessDriver.getInstance().newForumDAO().removeSubscription(forumId, userId);

			String returnPath = this.redirectLinkToShowAction(forumId);

			this.setTemplateName(TemplateKeys.POSTS_UNWATCH);
			this.context.put("message", I18n.getMessage("ForumBase.forumUnwatched", new String[] { returnPath }));
		}
		else {
			this.setTemplateName(ViewCommon.contextToLogin());
		}
	}
}


你可能感兴趣的:(jforum)