魅力生活

          用實例學習MVC模式

           
          1.1 MVC模式

          MVC是三個單詞的縮寫,這三個單詞分別為:模型(Model)、視圖(View)和控制(Controller)。MVC模式的目的就是實現(xiàn)Web系統(tǒng)的職能分工。下面以J2EE開發(fā)進行介紹。
          Model層實現(xiàn)系統(tǒng)中的業(yè)務邏輯,通常可以用JavaBean或EJB來實現(xiàn)。
          View層用于與用戶的交互,通常用JSP來實現(xiàn)。
          Controller層是Model與View之間溝通的橋梁,它可以分派用戶的請求并選擇恰當?shù)囊晥D以用于顯示,同時它也可以解釋用戶的輸入并將它們映射為模型層可執(zhí)行的操作。
          現(xiàn)在來看一個例子,看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中,我們并沒有直接去調(diào)用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請求的函數(shù)
              * @param request servlet request
              * @param response servlet response
              */
              protected void processRequest(HttpServletRequest request,HttpServletResponse response)
                  throws ServletException, java.io.IOException 
              {        
                  //代碼(1)通過if來實現(xiàn)對不同請求的分發(fā) 
                  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);
              }

              /** 一個實現(xiàn)了分發(fā)者模式的函數(shù)
              * @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對象來執(zhí)行,如代碼(1)。在處理完請求后,轉(zhuǎn)到相應的頁面中,如代碼(2)。下面,我們看一下ArticleCommand類的代碼。
          例1-d:
          package nepalon.simplestruts;

          /**
           * <p>Title: MVC framework</p>
           * <p>Description: 文章業(yè)務類<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)保存處理結(jié)果并返回跳轉(zhuǎn)頁面
                  request.setAttribute("vectorComment ", vectorComment);
                  return "/simplestruts/showallarticle.jsp";
          }
          ……
          public String getNewArticle(HttpServletRequest request, HttpServletResponse response)
                    throws javax.servlet.ServletException, java.io.IOException
              {…}
          }
          在這個類中進行的是取得所有文章的業(yè)務,最后返回如果成功執(zhí)行操作后要跳轉(zhuǎn)到的頁面。當然,這個類中可能還有別的業(yè)務的相應函數(shù),讀者可自己實現(xiàn)。下面看一下要跳轉(zhuǎn)到的頁面的代碼。
          例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>發(fā)表時間</td>
                  <td>文章內(nèi)容</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中我們要做的只是取得結(jié)果并顯示,沒有涉及到相應的業(yè)務邏輯。

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

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

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


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


          網(wǎng)站導航:
           

          My Links

          Blog Stats

          News

          常用鏈接

          留言簿(2)

          隨筆檔案

          文章分類

          文章檔案

          java站

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 秦皇岛市| 江都市| 铜山县| 涞源县| 襄樊市| 长兴县| 石渠县| 仁寿县| 汝城县| 乐东| 武陟县| 正镶白旗| 扶绥县| 仁化县| 湛江市| 盐津县| 镇雄县| 孟州市| 缙云县| 光泽县| 鄂托克前旗| 江川县| 台山市| 葫芦岛市| 北安市| 镇宁| 龙川县| 句容市| 尖扎县| 平阳县| 高雄县| 永平县| 农安县| 老河口市| 邢台县| 沙洋县| 洞口县| 苍溪县| 阜城县| 建昌县| 德安县|