Java Web - Create a dispatch Servlet to execute model's method

本篇主要是說明如何建立一個簡單的分派Servlet,來達到web.xml減少設定Servlet進入點的

目的。要達到這樣的目的,需要用到的技術為前端頁面useBean物件的建立(sessionScope)及

傳送至後端的方法名稱配合Java Reflection及Polymorphism。

一般來說,針對一個網頁如果有多個功能,可能會在各個頁面傳送至後端的程式設置各自的

進入點程式(Servlet),雖然可以以JSP來取代,但是JSP程式內夾雜著Java的寫法並不好維

護,也缺乏架構。因此在這邊我們會建立一個統一的分派Servlet來當作一個指揮的角色,

並透過所有後端程式的父類別(AbstractModel)做為型態,相對的子類別Model為實體來進行

相對應method的呼叫達到目的。

參考架構圖


前端片段程式

首先宣告一model實體並儲存在session內
<c:remove var="execModel" scope="session"/>
<jsp:useBean id="execModel" class="com.grid.action.EmployeeModel" scope="session"/>

這段程式主要為ExtJS的Store元件,撈取後端所組成的JSON Data,在此需設定好action的name

,如此一來才可以呼叫到model程式內對應的method。

// create the Data Store
    var store = new Ext.data.Store({
        // load using HTTP
        url: "<%=request.getContextPath()%>/ActionServlet?action=composeGridData",
  // 此讀取器可以解析JSON DATA, 並轉換成Record. Record需定義其欄位名稱與型別
        reader: new Ext.data.JsonReader({
            root: 'rows',
            id: 'EmployeeID',
            totalRecords: 'totalRows'
        },rawDataFormat) 
    });


後端程式 - ActionServlet

設定web.xml

protected void action(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
  response.setContentType("text/html; charset=UTF-8");
  response.setHeader("Cache-Control", "no-cache");
  response.setCharacterEncoding("UTF-8");

  AbstractModel model = (AbstractModel)request.getSession().getAttribute("execModel");
  model.setResponse(response);
  String action = request.getParameter("action");
  model.setAction(action);
  
  try {
   model.execute(request);
  } catch (NoSuchMethodException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (SecurityException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

ActionServlet在doPost及doGet內共同呼叫一個action method,由於前端的程式可能會用Get或

POST方法,如上面的片段Store程式即是利用GET來傳值。

這時取得session內的model實體,並由父類別AbstractModel來設置相關的變數(response及

action),最後再呼叫execute method來進行下一步,即呼叫該支model內method的動作。

後端程式 - AbstractModel

這支程式為所有Model程式的父類別,定義為抽象類別
public void execute(HttpServletRequest request) throws NoSuchMethodException, SecurityException{
  Class amodel = this.getClass();
  Method m = amodel.getDeclaredMethod(action, HttpServletRequest.class);
  try {
     m.invoke(this, request);
  } catch (IllegalAccessException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (IllegalArgumentException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } catch (InvocationTargetException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  } 
 }

如上,this所代表的為EmployeeModel實體,再透過Java Reflection來呼叫action所設定的method

如下:

public class EmployeeModel extends AbstractModel {
   public void composeGridData(HttpServletRequest request){
       ...
       ...
       outputResponse(jsonData.toString()); 
   }
}

最後再透過AbstractModel內定義的outputResponse來進行response輸出
public void outputResponse(String resp){
  System.out.println("Response Content:"+resp);
  try {
   getResponse().getWriter().println(resp);
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }

留言