用實例學習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) 有利于組件的重用
分層后更有利于組件的重用。如控制層可獨立成一個能用的組件,視力層也可做成通用的操作界面。
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編程