Model 2 架构将应用程序的 Web 层区分为 Controller、Model与View三个角色,使用JSP/Servlet技术,可以很适切的实现这个架构。
JSP/Servlet对于Model 2架构的实现对应分别为:
- Servlet 实现 Controller 角色
- JavaBean或其它自订值对象实现 Model 角色
- 没有程序逻辑的 JSP 实现 View 角色
首先使用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类:
package 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来处理。 |