Servlet是如何實現MVC的

jopen 10年前發布 | 20K 次閱讀 Servlet Java開發

Servlet是一種服務器端的編程語言,是J2EE中比較關鍵的組成部分,Servlet技術的推出,擴展了Java語言在服務器端開發的功能,鞏固了Java語言在服務器端開發中的地位,而且現在使用非常廣泛的JSP技術也是基于Servlet的原理.

JSP+JavaBeans+Servlet成為實現MVC模式的一種有效的選擇。

Servlet是如何實現MVC的

如果我們要實現一個對用戶的增刪改查,并且要求符合對擴展開發,對修改關閉的原則,該怎么做呢?

首先,這是我們的類圖以及類與類之間調用的時序圖。

Servlet是如何實現MVC的

Servlet是如何實現MVC的

根據UML圖來實現代碼:

TestServlet類

package com.bjpowernode.servlet;

import java.io.IOException; import java.util.List;

import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

public class TestServlet extends HttpServlet {

protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    String requestURI = request.getRequestURI();
    System.out.println("requestURI=" + requestURI);
    String path = requestURI.substring(requestURI.indexOf("/",1),requestURI.indexOf("."));
    System.out.println("path = " +path);

    String username = request.getParameter("username");

    Action action = null;
    if("/servlet/delUser".equals(path)){
        action = new DelUserAction();
    }else if("/servlet/addUser".equals(path)){
        action = new AddUserAction();
    }else if("/servlet/modifyUser".equals(path)){
        action = new ModifyAction();
    }else if("/servlet/queryUser".equals(path)){
        action = new QueryUserAction();
    }else{
        throw new RuntimeException("請求失敗");
    }
    String forward ="";
    try {
        forward= action.execute(request, response);
    } catch (Exception e) {
        e.printStackTrace();
    }
    request.getRequestDispatcher(forward).forward(request, response);


}


protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    doGet(request,response);
}

}</pre>

抽象接口Action

package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

public interface Action {

public String execute(HttpServletRequest request, HttpServletResponse response)
throws Exception;

}</pre>

添加類,這里就只寫添加類了,其他類一樣

package com.bjpowernode.servlet;

import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

public class AddUserAction implements Action {

public String execute(HttpServletRequest request,
        HttpServletResponse response) throws Exception {
    String username = request.getParameter("username");
    //int age = Integer.parseInt(request.getParameter("username"));
    //String sex = request.getParameter("sex");

    //調用業務邏輯
    UserManager userManager = new UserManager();
    userManager.add(username);

    return "/add_success.jsp";
}

}</pre>

Web.xml配置

<welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
  
  <servlet>
      <servlet-name>TestServlet</servlet-name>
      <servlet-class>com.bjpowernode.servlet.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
     <servlet-name>TestServlet</servlet-name>
     <!-- 
     <url-pattern>/servlet/TestServlet</url-pattern>
      -->
      <url-pattern>*.do</url-pattern>
  </servlet-mapping>

這里我們發現,在testAction類中,用到了大量的if和else,而當我們需要擴展一個上傳類的時候,就需要修改if/else,所以,這就不符合對擴展開發,對修改關閉原則,所以,我們需要把這部分提取出來,配置到配置文件里,用反射進行配置。

 

我們需要先配置配置文件

<action-config>
               <action path ="/servlet/delUser" type = "com.bjpowernode.servlet.DelUserAction">
                      <forward name = "success">del_success.jsp</forward>
                      <forward name = "error">del_error.jsp</forward>
                  </action> 
                  <action path ="/servlet/addUser" type = "com.bjpowernode.servlet.AddUserAction">
                      <forward name = "success">add_success.jsp</forward>
                      <forward name = "error">add_error.jsp</forward>
                  </action> 
                  <action path ="/servlet/modifyUser" type = "com.bjpowernode.servlet.ModifyAction">
                      <forward name = "success">modify_success.jsp</forward>
                      <forward name = "error">modify_error.jsp</forward>
                  </action> 
                  <action path ="/servlet/queryUser" type = "com.bjpowernode.servlet.QueryUserAction">
                      <forward name = "success">query_success.jsp</forward>
                      <forward name = "error">query_error.jsp</forward>
                  </action> 
          </action-config>

需要獲取actionMapping對象

  ActionMapping{
              private String path;
            private String type;
           Map forwardMap;
          
          
          }
          forwardMap{
              key = "success";
              value ="/del_success.jsp"
              key ="error"
              value ="del_error.jsp";
         
         
         
          }
         
          Map map = new HashMap();
          map.put("/servlet/delUser",actionMapping);
          map.put("/servlet/addUser",actionMapping);
          map.put("/servlet/modifyUser",actionMapping);
          map.put("/servlet/queryUser",actionMapping);
         
         // 如果是刪除ActionMapping存儲如下:
          actionMapping{
              path ="/servlet/delUser";
           type ="com.bjpowernode.servlet.DelUserAction"
             forwardMap{
                 key ="success",value ="/del_success.jsp"
                 key ="error",value"/del_error.jsp"
             }
          }

最后根據獲取的對象采用反射來動態實例化Action,達到我們的目的。

  String path = "/servlet/delUser";
         
        //  根據截取的URL請求,到Map中取得本次請求對應的Action
              ActionMapping actionMapping =(ActionMapping)map.get(path);
              
        //取得本次請求對應的Action類的完整路徑
          String type = actionMapping.getType();  //com.bjpowernode.servlet.DelUserAction
         
         // 采用反射動態實例化Action
          Action action  = (Action)class.forName(type).newInstance();
         
        //動態待用Action中的execute方法
          String forward = action.execute(request.response);
         
          //根據路徑完成轉向       
         request.getRequestDispatcher(forward).forward(request, response);

這樣,我們基本就是實現了對擴展開發,對修改封閉的原則,但是,這僅僅是一個功能我們就需要做這么多事情,寫這么多代碼,對程序員來說這是一項不小的工作量,那么我們有沒有其他的辦法讓我們的工作量小一點呢?

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!