事实是最近读《J2EE设计模式》讲述表达层模式的那几章,书中有一个前端控制器 command模式的workflow例子,就琢磨着可以很简单地扩展成一个MVC框架。
6。前端控制器(FrontController),它的任务我们已经很清楚,初始化配置文件;存储所有action到ServletContext供整个框架使用;得到发起请求的path,提供给Dispachter查找相应的action;调用Dispatcher,执行getNextPage方法得到下一个页面的url并转发:
-
- public void init() throws ServletException {
-
- //初始化配置文件
-
- ServletContext context=getServletContext();
- String config_file =getServletConfig().getInitParameter("config");
- String dispatcher_name=getServletConfig().getInitParameter("dispatcher");
- if (config_file == null || config_file.equals(""))
- config_file = "/WEB-INF/strutslet-config.xml"; //默认是/WEB-INF/下面的strutslet-config
- if(dispatcher_name==null||dispatcher_name.equals(""))
- dispatcher_name=Constant.DEFAULT_DISPATCHER;
-
- try {
- Map<String, ActionModel> resources = ConfigUtil.newInstance() //工具类解析配置文件
- .parse(config_file, context);
- context.setAttribute(Constant.ACTIONS_ATTR, resources); //存储在ServletContext中
- log.info("初始化strutslet配置文件成功");
- } catch (Exception e) {
- log.error("初始化strutslet配置文件失败");
- e.printStackTrace();
- }
-
- //实例化Dispacher
-
- try{
- Class c = Class.forName(dispatcher_name);
- Dispatcher dispatcher = (Dispatcher) c.newInstance();
- context.setAttribute(Constant.DISPATCHER_ATTR, dispatcher); //放在ServletContext
- log.info("初始化Dispatcher成功");
- }catch(Exception e) {
- log.error("初始化Dispatcher失败");
- e.printStackTrace();
- }
-
- .....
doGet()和doPost方法我们都让它调用process方法:
-
- protected void process(HttpServletRequest request,
- HttpServletResponse response) throws ServletException, IOException {
- ServletContext context = getServletContext();
-
- //获取action的path
- String reqURI = request.getRequestURI();
- int i=reqURI.lastIndexOf(".");
- String contextPath=request.getContextPath();
- String path=reqURI.substring(contextPath.length(),i);
-
- request.setAttribute(Constant.REQUEST_ATTR, path);
- Dispatcher dispatcher = (Dispatcher) context.getAttribute(Constant.DISPATCHER_ATTR);
-
- // make sure we don't cache dynamic data
- response.setHeader("Cache-Control", "no-cache");
- response.setHeader("Pragma", "no-cache");
-
- // use the dispatcher to find the next page
- String nextPage = dispatcher.getNextPage(request, context);//调用Dispatcher的getNextPage
-
- // forward control to the view
- RequestDispatcher forwarder = request.getRequestDispatcher("/"
- + nextPage);
- forwarder.forward(request, response); //转发页面
- }
7。最后,web.xml的配置就非常简单了,配置前端控制器,提供启动参数(配置文件所在位置,为空就查找/WEB-INF/下面的strutslet-config.xml文件),我们把所有以action结尾的请求都交给FrontController处理:
-
- <servlet>
- <servlet-name>StrutsletController</servlet-name>
- <servlet-class>com.strutslet.core.FrontController</servlet-class>
- <!--
- <init-param>
- <param-name>config</param-name>
- <param-value>/WEB-INFstrutslet-config.xml</param-value>
- </init-param>
- -->
- <load-on-startup>0</load-on-startup>
- </servlet>
- <servlet-mapping>
- <servlet-name>StrutsletController</servlet-name>
- <url-pattern>*.action</url-pattern>
- </servlet-mapping>
最后,让我们看看整个框架图: