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來處理。 |