在博客摘要里提到了,所有的基类的作用都是为了代码复用。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()); } } }