魅力生活

          用實例學習MVC模式

           
          1.1 MVC模式

          MVC是三個單詞的縮寫,這三個單詞分別為:模型(Model)、視圖(View)和控制(Controller)。MVC模式的目的就是實現Web系統的職能分工。下面以J2EE開發進行介紹。
          Model層實現系統中的業務邏輯,通常可以用JavaBean或EJB來實現。
          View層用于與用戶的交互,通常用JSP來實現。
          Controller層是Model與View之間溝通的橋梁,它可以分派用戶的請求并選擇恰當的視圖以用于顯示,同時它也可以解釋用戶的輸入并將它們映射為模型層可執行的操作。
          現在來看一個例子,看MVC模式是怎樣工作的。
          1.1.1 一個實例
          例1-a:
          <servlet>
                <servlet-name>Controller</servlet-name>
                <servlet-class>nepalon.simplestruts.Controller</servlet-class>
          </servlet>  
          <servlet-mapping>
              <servlet-name>Controller</servlet-name>
              <url-pattern>/simplestruts/servlet/control/Controller</url-pattern>
          </servlet-mapping>
          上面是web.xml文件的片段,在這里定義了一個servlet用于處理請求。
          例1-b(Test.jsp文件):
          <html>
          <%@ page contentType="text/html;charset=gb2312"%> 
          <head>
          <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
          <title>實例首頁</title>
          </head>
          <body>  
          <table border="0" width="100%">
            <tr> 
          <td><div align="center">
          <a href="/simplestruts/servlet/control/Controller?command=showarticle">顯示文章</a>
          </div></td>
            </tr>
          </table>
          </body>
          </html>
          在這個JSP中,我們并沒有直接去調用JSP或JavaBean,而是把請求分送到Servlet中。下面,我們來看看Servlet的代碼。
          例1-c:
          package nepalon.simplestruts;
          /**
           * <p>Title: MVC framework</p>
           * <p>Description: Controller<p>
           * <p>Copyright: R2003</p>
           * @author Nepalon
           * @version 1.0
           */

          import javax.servlet.*;
          import javax.servlet.http.*;
          import java.io.*;
          import java.util.*;


          public class Controller extends HttpServlet  
          {

              public void init(ServletConfig config) throws ServletException 
              {
                  super.init(config);
              }

              public void destroy() {}

              /** 用于處理HTTP的GET和POST請求的函數
              * @param request servlet request
              * @param response servlet response
              */
              protected void processRequest(HttpServletRequest request,HttpServletResponse response)
                  throws ServletException, java.io.IOException 
              {        
                  //代碼(1)通過if來實現對不同請求的分發 
                  if(request.getParameter("command").equals("showarticle"))
                  {
                      ArticleCommand command = new ArticleCommand();
                      next = command. getAllArticle (request, response);
                  }
                  //代碼(2)
                  dispatch(request, response, next);
              }
              
              protected void doGet(HttpServletRequest request,
                                  HttpServletResponse response)
                  throws ServletException, java.io.IOException 
              {
                  processRequest(request, response);
              }
              
              protected void doPost(HttpServletRequest request,
                                   HttpServletResponse response)
                  throws ServletException, java.io.IOException 
              {
                  processRequest(request, response);
              }

              /** 一個實現了分發者模式的函數
              * @param request servlet request
              * @param response servlet response
              */
              protected void dispatch(HttpServletRequest request,
                                     HttpServletResponse response,
                                     String page)
                  throws  javax.servlet.ServletException, java.io.IOException 
              {
                  RequestDispatcher dispatcher =
                      getServletContext().getRequestDispatcher(page);
                  dispatcher.forward(request, response);
              }
          }
          在Servlet中并沒有直接處理所提交的請求,而是把請求的處理推后到ArticleCommand類中,通過ArticleCommand對象來執行,如代碼(1)。在處理完請求后,轉到相應的頁面中,如代碼(2)。下面,我們看一下ArticleCommand類的代碼。
          例1-d:
          package nepalon.simplestruts;

          /**
           * <p>Title: MVC framework</p>
           * <p>Description: 文章業務類<p>
           * <p>Copyright: R2003</p>
           * @author Nepalon
           * @version 1.0
           */

          import java.util.*;
          import javax.servlet.*;
          import java.io.*;
          import java.lang.*;
          import java.sql.*;
          import javax.sql.*;

          public class Contribute
          {
              public Contribute() {}
              public String getAllArticle(HttpServletRequest request, HttpServletResponse response)
                    throws javax.servlet.ServletException, java.io.IOException
              {
                   Connection conn=null;
                  String con_user = "example1";
                  String con_password = "example1";
                  String con_dburl = "jdbc:oracle:thin:@localhost:iasdb";
                  String con_driver = "oracle.jdbc.driver.OracleDriver";
                  PreparedStatement pstmt=null;
                  ResultSet rsComment=null;    
                  Vector vectorComment = new Vector();
                  String selectSQL= "SELECT content, time FROM article ORDER BY time DESC";
                  try
                  {
                       DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
                       Class.forName(con_driver);
                       conn = DriverManager.getConnection(con_dburl,con_user,con_password);
                       pstmt=conn.prepareStatement(selectSQL);
                       rsComment=pstmt.executeQuery();
                       while(rsComment.next()) 
                       {
                             CommentItem commentItem = new CommentItem();
                          commentItem.setContent(rsComment.getString(1));
                          commentItem.setTime(rsComment.getDate(2));
                          vectorComment.add(commentItem);
                       }
                       vectorComment.trimToSize();
                    }
                  catch (Exception e){//做相應的處理}
                  //代碼(1)保存處理結果并返回跳轉頁面
                  request.setAttribute("vectorComment ", vectorComment);
                  return "/simplestruts/showallarticle.jsp";
          }
          ……
          public String getNewArticle(HttpServletRequest request, HttpServletResponse response)
                    throws javax.servlet.ServletException, java.io.IOException
              {…}
          }
          在這個類中進行的是取得所有文章的業務,最后返回如果成功執行操作后要跳轉到的頁面。當然,這個類中可能還有別的業務的相應函數,讀者可自己實現。下面看一下要跳轉到的頁面的代碼。
          例1-e(showallarticle.jsp文件):
          <html>
          <%@ page contentType="text/html;charset=gb2312"%> 
          <%@ page import="java.util.*, java.lang.*"%>
          <jsp:useBean id="vectorComment" type="java.util.Vector" scope="request"/>
          <head>
          <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
          <title>顯示文章</title>
          </head>
          <body>  
          <table border="0" width="100%">
              
            <tr> 
              <td>發表時間</td>
                  <td>文章內容</td>
            </tr>
          <%       
              if (vectorComment!=null && vectorComment.size()>0) 
              {        
                  int counter=vectorComment.size();    
                  CommentItem commentlist = null;    
                  for (int i=0;i<counter;i++)
                  {                                                             
                       commentlist=null;        
                       commentlist=(CommentItem)(vectorComment.get(i));     
          %> 
            <tr> 
              <td><%=commentlist.getCmTime()%></td>
                  <td><%=commentlist.getCmContent()%></td>
            </tr>
          <%
                  }
              }
          %>
          </table>
          </body>
          </html>
          在這個JSP中我們要做的只是取得結果并顯示,沒有涉及到相應的業務邏輯。

          1.1.2 實例分析
          首先,我們看一下這個例子的序列圖
           
          圖1.1.2-1
          1)    首先在Veiw層的test.jsp中提交一個請求/simplestruts/servlet/control/Controller?command=showarticle;
          2)    在Controller層的Controller對象中,根據請求的類型來調用相應的業務處理類,在這里,command值為showarticle的請求的業務處理類為ArticleCommand類,所以調用該類的對象的相應函數;
          3)    在Model層的ArticleCommand類主要實現請求的取得所有文章的業務功能,把結果保存在request中,并返回跳轉頁面作為返回值;
          4)    回到Controller層的Controller對象,根據上一步驟的返回值進行頁面轉發。
          5)    轉發到View層的showallarticle.jsp頁面,這個頁面從request中取得結果并進行顯示。在這個JSP中雖然也有Java代碼,但這些代碼只是用于顯示結果,并沒有涉及到任何業務邏輯。

          1.1.3 MVC模式的好處
          本來這樣一個簡單的功能我們只需要2個JSP文件就能實現了,為什么要這么麻煩把它分到幾個類中去實現呢?現在就來看一下MVC模式帶來的好處。
          1)    各施其職,互不干涉
          在MVC模式中,三個層各施其職,所以如果一旦哪一層的需求發生了變化,就只需要更改相應的層中的代碼而不會影響到其它層中的代碼。假如業務發生了變化,如在取文章時可能webmaster把一些文章作了無效標志,不能直接把所有文章取出來,只能取出有效的文章,這時業務就發生了改變。再設想一下,如果這個業務邏輯在100個頁面中都要用到,那么MVC模式就體現了它的靈活性。我們可以不更改任何JSP,只要更改model層中的相應類中的SQL語句即可。
          2)    有利于開發中的分工
          在MVC模式中,由于按層把系統開,那么就能更好的實現開發中的分工。網頁設計人員可以進行開發視圖層中的JSP,對業務熟悉的開發人員可開發業務層,而其它開發人員可開發控制層。
          3)    有利于組件的重用
          分層后更有利于組件的重用。如控制層可獨立成一個能用的組件,視力層也可做成通用的操作界面。

          posted on 2005-07-13 11:47 cutelife 閱讀(222) 評論(0)  編輯  收藏 所屬分類: JAVA編程


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 鄂尔多斯市| 哈密市| 扶沟县| 怀仁县| 伊金霍洛旗| 区。| 舒城县| 阳江市| 虹口区| 淮安市| 电白县| 合川市| 渭源县| 呈贡县| 麦盖提县| 务川| 吴桥县| 三都| 赤水市| 昌吉市| 苗栗市| 德格县| 靖边县| 新龙县| 台山市| 闽侯县| 元朗区| 咸宁市| 平舆县| 盘山县| 蒙自县| 郯城县| 兰溪市| 宾川县| 博客| 双鸭山市| 六枝特区| 陵川县| 新巴尔虎左旗| 马尔康县| 股票|