Front Controller模式要求在WEB应用系统的前端(Front)设置一个入口控制器(Controller),所有的request请求都被发往该控制器统一处理。Front Controller一般可以用来做一个共通处理比如认证,页面导航,Session管理,国际化或本地化处理等。

Front Controller(前端控制器)模式介绍
我们从问题,解决方法,策略,优点几个方面介绍Front Controller(前端控制器)模式。最后给出Front Controller的实现范例以及相关联结。

问题


我们使用一个模式,都是为了解决某些问题而使用的。Front Controller模式用来解决什么问题呢?
我们在开发WEB应用系统(但不拘于WEB应用)时,存在很多不恰当的设计方法,比如让客户端(Client,一般指浏览器)可以直接访问各个视图(view,JSP等)。这样逻辑被分散到各个视图中,从而产生了各种问题:
1,对已有的功能修改困难,可维护性低。假如session管理,一旦session内容需要发生改变,则需要修改所有view中的相关代码。
2,很难增加新的功能,缺乏可扩展性。例如,我们需要在已有的系统中加入安全控制功能,控制用户对某些页面的访问,因为没有统一的处理入口,我们需要在所有的view中都加上认证代码。

对于系统中需要提供的类似以下功能:
J2EE核心模式 - Front Controller(前端控制器)_职场 认证
J2EE核心模式 - Front Controller(前端控制器)_职场 页面导航与转发等
J2EE核心模式 - Front Controller(前端控制器)_职场 Session管理
J2EE核心模式 - Front Controller(前端控制器)_职场 国际化或本地化处理
J2EE核心模式 - Front Controller(前端控制器)_职场 日志
J2EE核心模式 - Front Controller(前端控制器)_职场 其它共通处理
等,都会存在代码分散重复,可维护性低,缺乏可扩展性等问题。
J2EE核心模式 - Front Controller(前端控制器)_职场_07

图1:相同的逻辑被重复分散在各个view里。

解决方法


使用Front Controller,强制分离view的显示逻辑与业务处理逻辑。如图:
J2EE核心模式 - Front Controller(前端控制器)_职场_08
图2:前端控制器
Controller作为所有request的最初访问点。

策略


Front Controller模式可以有多种实现策略:
Servlet(+ Dispatcher,+Command,+…)Front Controller策略
Filter Controller策略
JSP Front Controller策略
等,一般推荐使用前2种实现方法。

优点:


使用Front Controller模式有以下好处:
- 集中控制
- 提高可管理性和安全控制能力
- 提高可重用性可扩展性

范例

下面是一个Servlet Controller的实现范例。该范例让doPost与doGet方法调用processRequest方法,processRequest方法执行“认证”“session管理”等共通操作,同时结合Command模式调用了业务逻辑。

代码:
  1. public class SampleController extends HttpServlet {   
  2.   protected void processRequest(HttpServletRequest    
  3.     request, HttpServletResponse response)   
  4.     throws ServletException, java.io.IOException {   
  5.   
  6.     String page = null;   
  7.     try {   
  8.       //process authority   
  9.       processAuthority(request, response);   
  10.       //manage session   
  11.       processSession(request, response);   
  12.   
  13.       // Use a helper object to gather parameter    
  14.       // specific information.   
  15.       RequestHelper helper = new  
  16.          RequestHelper(request);   
  17.   
  18.       Command cmdHelper= helper.getCommand();   
  19.   
  20.       // Command helper perform custom operation   
  21.       page = cmdHelper.execute(request, response);   
  22.   
  23.     }   
  24.     catch (Exception e) {   
  25.       LogManager.logMessage("Error Message HERE");   
  26.       page = resource.getErrorPage(e);   
  27.     }   
  28.     // dispatch control to view   
  29.     dispatch(request, response, page);   
  30.   }   
  31.   
  32.   protected void doGet(HttpServletRequest request,    
  33.     HttpServletResponse response)   
  34.     throws ServletException, java.io.IOException {   
  35.       processRequest(request, response);   
  36.   }   
  37.   
  38.   protected void doPost(HttpServletRequest request,    
  39.     HttpServletResponse response)   
  40.     throws ServletException, java.io.IOException {   
  41.         processRequest(request, response);   
  42.   }   
  43.   
  44.   protected boolean processAuthority(HttpServletRequest request,    
  45.     HttpServletResponse response) {   
  46.       ... //authority control code here   
  47.   }   
  48.   
  49.   protected void processSession(HttpServletRequest request,    
  50.     HttpServletResponse response) {   
  51.       ... //session management code here   
  52.   }   
  53.   
  54.   protected void dispatch(HttpServletRequest request,    
  55.     HttpServletResponse response,   
  56.     String page)    
  57.   throws  javax.servlet.ServletException,    
  58.     java.io.IOException {   
  59.     RequestDispatcher dispatcher =    
  60.       getServletContext().getRequestDispatcher(page);   
  61.     dispatcher.forward(request, response);   
  62.   }   
  63. }