| 订阅 | 在线投稿
分享
 
 
 

再战MVC(二)

来源:互联网  宽屏版  评论
2007-09-22 05:02:34

MVC模式在J2EE技术中的应用

MVC模式并不能自动保证一个结构设计是正确的,如何在一个系统的设计中正确地使用MVC架构模式与系统使用的技术有密切的关系。2EE中有几个核心的技术:JSP,JavaBean,Servlet,EJB,SessionBean,EntityBean构成了J2EE构架的基石,但是对于一个基于J2EE技术的Web应用来说,如何正确地使用MVC模式不是一句话就能得出结论的。

一般而言,一个J2EE系统应当适当地划分接收请求,根据请求采取行动,并将结果显示给用户等责任。因此也就有了开发Web应用时经常提到的一个概念Model 1/Model 2,它是对采用JSP技术构成Web应用的不同模型的描述。

Model 1架构

<<Java与模式>>提到模型一又称做以JSP为中心(JSP Centric)的设计模型,它的架构图如下图所示:

王朝网络

从上图可以看出来,JSP是整个应用系统的门户。它身兼三职啊。1负责与客户端的所有通信2处理所有的请求3处理所有的答复。在处理答复的时候,从数据库中存取数据有两种方式,可以它自己直接去存取,也可以让一些JavaBean来完成。因为JavaBean可以被放在一个请求上下文或者用户会话中,这样就可以在不同的JSP之间通信。当然这种模式在进行快速和需求不是很复杂,规模较小的 Web应用是有很大的优势的,比如说:JSP页面可以非常容易地结合业务逻辑(jsp:useBean)、服务端处理过程(jsp:scriplet)和HTML(<html>),在JSP页面中同时实现显示,业务逻辑和流程控制,从而可以快速地完成应用开发。

但是从工程化的角度考虑,它也有一些不足之处:把表现层和业务逻辑层柔和在一起,不利于以后的维护工作以及开发角色的分配,所以这种模式只能适合于小的系统开发。

Model 2架构

Servlet/JSP 规范的0.92版描述了在一个应用中使用servlet 和 JSP 的架构。在其后的规范中,Model 2 这个叫法消失了,但它已经在Java web 开发人员中非常通用了。 <<Java与模式>>提到模型二又称做以Servlet为中心(Servlet Centric)的设计模型, 它的架构图如下图所示:

王朝网络

对比这个图跟Model 1的结构图,从 JSP这个角度来看,JSP页面至少少了二个任务即获取跟处理用户的请求,因为Servlet相当于控制器(Controller)角色,它负责接收客户端请求并处理此请求,将它传递给合适的JSP,而JSP则显示给用户。所以JSP页面这时候主要做两件事情: JavaBean直接与数据库打交道取得数据后,JSP从JavaBean中读取数据,这是第一,第二件事情就是把结果返回给客户端。

根据Model 2,servlet 处理数据存取和导航流, JSP处理表现。Model 2 使Java 工程师和HTML设计者分别工作于它们所擅长和负责的部分。Model 2应用的一部分发生改变并不强求其他部分也跟着发生改变。HTML 开发人员可以改变程序的外观和感觉,并不需要改变后端servlet的工作方式。

网上找到了一个很好的例子来说声明:JSP能够生成HTML,WML甚至XML,它对应于Web应用程序中的View部分。EJB作为数据库与应用程序的中介,提供了对数据的封装。一般SessionBean封装的是数据,EntityBean是封装对数据的操作。这两个部分合起来,对应于Web应用程序的Model部分。在技术上,JSP能够直接对EJB进行存取,但这并不是好办法,那样会混淆程序中的显示逻辑和控制逻辑,使得JSP的重用性能降低。这时候有两种解决方法,通过JavaBean或者Servlet作为中介的控制逻辑,对EJB所封装的数据进行存取。这时,JavaBean或者Servlet对应于Web引用程序中的Controller部分。两种类型的Controller各有其优缺点:JSP同Servlet的交互不容易规范化,使得交互的过程变得复杂,但是Servlet可以单独同用户交互,实际上JSP的运行时状态就是Servlet;而由于JavaBean的规范性,JSP同JavaBean的交互很容易,利用JavaBean的get/set方法,JSP不需要过多的语句就可以完成数据的存取,这能够让JSP最大限度的集中在其视图功能上,而且,在桌面应用程序中使用JavaBean也很容易,而用Servlet就相对麻烦许多。根据不同的问题背景,可以选取不同的Controller,有时候也可以两者混合使用,或者直接在Servlet中调用JavaBean。

任何一种解决方案都是双刃剑,在我们获得的同时必须有一定的付出。这种模式也带来了如下一些实际的问题:1. 必须基于MVC组件的方式重新思考和设计应用结构。原来通过建立一个简单的JSP页面就能实现的应用现在变成了多个步骤的设计和实现过程。 2.所有的页面和组件必须在MVC框架中实现,所以必须进行附加地开发工作。

对于用原生的Servlet API来开发Model 2的程序的例子我将转载JavaResearch论坛上的文章,研究下对MVC模式在J2EE系统中的应用有很大帮助的。

(转载自“用实例学习MVC模式” nepalon 原作 )

下面以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代码,但这些代码只是用于显示结果,并没有涉及到任何业务逻辑。

(转载完查看原文)

MVC本身就是一个非常复杂的系统,所以采用MVC实现Web应用时,如果采用现成的MVC框架,在此之下进行开发,能够达到事半功倍的效果。

 
MVC模式在J2EE技术中的应用   MVC模式并不能自动保证一个结构设计是正确的,如何在一个系统的设计中正确地使用MVC架构模式与系统使用的技术有密切的关系。2EE中有几个核心的技术:JSP,JavaBean,Servlet,EJB,SessionBean,EntityBean构成了J2EE构架的基石,但是对于一个基于J2EE技术的Web应用来说,如何正确地使用MVC模式不是一句话就能得出结论的。 一般而言,一个J2EE系统应当适当地划分接收请求,根据请求采取行动,并将结果显示给用户等责任。因此也就有了开发Web应用时经常提到的一个概念Model 1/Model 2,它是对采用JSP技术构成Web应用的不同模型的描述。 Model 1架构    <<Java与模式>>提到模型一又称做以JSP为中心(JSP Centric)的设计模型,它的架构图如下图所示:   [img]http://images.wangchao.net.cn/images/upload/images/lsdn/1190408554614.jpg[/img] 从上图可以看出来,JSP是整个应用系统的门户。它身兼三职啊。1 负责与客户端的所有通信 2处理所有的请求 3处理所有的答复。在处理答复的时候,从数据库中存取数据有两种方式,可以它自己直接去存取,也可以让一些JavaBean来完成。因为JavaBean可以被放在一个请求上下文或者用户会话中,这样就可以在不同的JSP之间通信。当然这种模式在进行快速和需求不是很复杂,规模较小的 Web应用是有很大的优势的,比如说:JSP页面可以非常容易地结合业务逻辑(jsp:useBean)、服务端处理过程(jsp:scriplet)和HTML(<html>),在JSP页面中同时实现显示,业务逻辑和流程控制,从而可以快速地完成应用开发。 但是从工程化的角度考虑,它也有一些不足之处:把表现层和业务逻辑层柔和在一起,不利于以后的维护工作以及开发角色的分配,所以这种模式只能适合于小的系统开发。 Model 2架构  Servlet/JSP 规范的0.92版描述了在一个应用中使用servlet 和 JSP 的架构。在其后的规范中,Model 2 这个叫法消失了,但它已经在Java web 开发人员中非常通用了。 <<Java与模式>>提到模型二又称做以Servlet为中心(Servlet Centric)的设计模型, 它的架构图如下图所示: [img]http://images.wangchao.net.cn/images/upload/images/lsdn/1190408554755.jpg[/img] 对比这个图跟Model 1的结构图,从 JSP这个角度来看,JSP页面至少少了二个任务即获取跟处理用户的请求,因为Servlet相当于控制器(Controller)角色,它负责接收客户端请求并处理此请求,将它传递给合适的JSP,而JSP则显示给用户。所以JSP页面这时候主要做两件事情: JavaBean直接与数据库打交道取得数据后,JSP从JavaBean中读取数据,这是第一,第二件事情就是把结果返回给客户端。 根据Model 2,servlet 处理数据存取和导航流, JSP处理表现。Model 2 使Java 工程师和HTML设计者分别工作于它们所擅长和负责的部分。Model 2应用的一部分发生改变并不强求其他部分也跟着发生改变。HTML 开发人员可以改变程序的外观和感觉,并不需要改变后端servlet的工作方式。 网上找到了一个很好的例子来说声明:JSP能够生成HTML,WML甚至XML,它对应于Web应用程序中的View部分。EJB作为数据库与应用程序的中介,提供了对数据的封装。一般SessionBean封装的是数据,EntityBean是封装对数据的操作。这两个部分合起来,对应于Web应用程序的Model部分。在技术上,JSP能够直接对EJB进行存取,但这并不是好办法,那样会混淆程序中的显示逻辑和控制逻辑,使得JSP的重用性能降低。这时候有两种解决方法,通过JavaBean或者Servlet作为中介的控制逻辑,对EJB所封装的数据进行存取。这时,JavaBean或者Servlet对应于Web引用程序中的Controller部分。两种类型的Controller各有其优缺点:JSP同Servlet的交互不容易规范化,使得交互的过程变得复杂,但是Servlet可以单独同用户交互,实际上JSP的运行时状态就是Servlet;而由于JavaBean的规范性,JSP同JavaBean的交互很容易,利用JavaBean的get/set方法,JSP不需要过多的语句就可以完成数据的存取,这能够让JSP最大限度的集中在其视图功能上,而且,在桌面应用程序中使用JavaBean也很容易,而用Servlet就相对麻烦许多。根据不同的问题背景,可以选取不同的Controller,有时候也可以两者混合使用,或者直接在Servlet中调用JavaBean。 任何一种解决方案都是双刃剑,在我们获得的同时必须有一定的付出。这种模式也带来了如下一些实际的问题:1. 必须基于MVC组件的方式重新思考和设计应用结构。原来通过建立一个简单的JSP页面就能实现的应用现在变成了多个步骤的设计和实现过程。 2.所有的页面和组件必须在MVC框架中实现,所以必须进行附加地开发工作。 对于用原生的Servlet API来开发Model 2的程序的例子我将转载JavaResearch论坛上的文章,研究下对MVC模式在J2EE系统中的应用有很大帮助的。 (转载自“用实例学习MVC模式” [url=http://www.javaresearch.org/profile.jsp?user=17545]nepalon[/url] 原作 ) 下面以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 实例分析 首先,我们看一下这个例子的序列图 [img]http://images.wangchao.net.cn/images/upload/images/lsdn/1190408554880.png[/img] 图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代码,但这些代码只是用于显示结果,并没有涉及到任何业务逻辑。  (转载完 [url=http://www.javaresearch.org/article/showarticle.jsp?column=106&thread=11588]查看原文)[/url] MVC本身就是一个非常复杂的系统,所以采用MVC实现Web应用时,如果采用现成的MVC框架,在此之下进行开发,能够达到事半功倍的效果。
󰈣󰈤
 
 
 
>>返回首页<<
 
 热帖排行
 
 
 
静静地坐在废墟上,四周的荒凉一望无际,忽然觉得,凄凉也很美
©2005- 王朝网络 版权所有