Model 2 架构将应用程序的 Web 层区分为 Controller、Model与View三个角色,使用JSP/Servlet技术,可以很适切的实现这个架构。
JSP/Servlet对于Model 2架构的实现对应分别为:
首先使用Servlet来实现一个简单的控制器,在这之前,您需要先了解 Command 模式。使用 Command 模式,可以使控制器的实现更具弹性,不过作为一个范例,这边仅实作出概念,因而接下来会简化一些实作内容。
首先,实作Command 模式中实际执行请求的对象,先定义一个IAction接口:
package onlyfun.caterpillar;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface IAction {
public void execute(HttpServletRequest req,
HttpServletResponse res);
}
真正执行客户端请求的对象必须实作 IAction 接口,具体要实作的Action留在下一个主题,先来看看如何实现Command 模式中的Invoker类:
Invoker.javapackage onlyfun.caterpillar;
import java.io.IOException;
import java.util.*;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class Invoker {
private Map actions;
private String defaultPage;
public Invoker() {
actions = new HashMap();
}
public void addCommand(String actionName,
IAction action) {
actions.put(actionName, action);
}
public void request(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
IAction action =
(IAction) actions.get(req.getServletPath());
if(action != null) {
action.execute(req, res);
}
else {
RequestDispatcher dispatcher =
req.getRequestDispatcher(defaultPage);
dispatcher.forward(req, res);
}
}
public String getDefaultPage() {
return defaultPage;
}
public void setDefaultPage(String defaultPage) {
this.defaultPage = defaultPage;
}
}
这是一个很简单的控制转发类,这个类将根据客户端请求的Servlet路径来了解实际该调用的Action对象,如果找不到,则转发至预设的页面。
接下来在 Controller 中使用 Invoker 类,Controller 使用 Servlet 来实现:
package onlyfun.caterpillar;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class DispatcherServlet extends HttpServlet {
private Invoker invoker;
public void init() throws ServletException {
invoker = new Invoker();
invoker.addCommand("/welcome.action",
new WelcomeAction());
invoker.addCommand("/login.action",
new LoginAction());
invoker.setDefaultPage("/welcome.action");
}
public void doPost(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
invoker.request(req, res);
}
public void doGet(HttpServletRequest req,
HttpServletResponse res)
throws ServletException, IOException {
doPost(req, res);
}
}
为了简化程序以方便说明,直接将可用的请求路径写在init()中,目前只有两个可用的请求路径,实际上设计时,这个部份该可以在属性档案中设定,以这个Model 2架构的程序更有弹性而可以重用。
这边实现Model 2架构的方式将采用前端控制器(Front Controller)模式,客户端所有的请求将透过上面这个DispatcherServlet,在web.xml中可以这么设定来达到目的:
<?xml version="1.0" encoding="ISO-8859-1"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <description> Model 2 Example </description> <display-name>Model 2 Examples</display-name> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> onlyfun.caterpillar.DispatcherServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
按照这个web.xml的设定,所有以*.action结尾的请求都将由DispatcherServlet来处理。