MVC
模式概述
MVC
是三个单词的缩写
,
分别为:
模型
(Model),
视图
(View)
和控制
Controller)
。
MVC
模式的目的就是实现
Web
系统的职能分工。
Model
层实现系统中的业务逻辑,通常可以用
JavaBean
或
EJB
来实现。
View
层用于与用户的交互,通常用
JSP
来实现。
Controller
层是
Model
与
View
之间沟通的桥梁,它可以分派用户的请求并选择恰当的视图以用于显示,同时它也可以解释用户的输入并将它们映射为模型层可执行的操作。
MVC
模式的好处
各施其职,互不干涉
在
MVC
模式中,三个层各施其职,所以如果一旦哪一层的需求发生了变化,就只需要更改相应的层中的代码而不会影响到其它层中的代码。
有利于开发中的分工
在
MVC
模式中,由于按层把系统开,那么就能更好的实现开发中的分工。网页设计人员可以进行开发视图层中的
JSP
,对业务熟悉的开发人员可开发业务层,而其它开发人员可开发控制层。
有利于组件的重用
分层后更有利于组件的重用。如控制层可独立成一个能用的组件,视图层也可做成通用的操作界面。
不同
JSP
构造的应用
为什么要组合使用
servlet & JSP?
典型的做法:使用
JSP
来简化
HTML
内容的开发与维护
对于简单的动态代码,使用由脚本元素调用
JAVA
代码来完成。
对于稍微复杂一些的应用,则可使用脚本元素调用定制的类来完成。
(
即所谓的
help
类
)
对于比较复杂的应用,则使用
JAVA BEAN
和定制标签
但,这些是不够的
对于复杂的处理过程,从
JSP
开始做起会难以处理。
JSP
除了能够带来将实际的代码隔离成单独的类、
bean
、和定制标签的便利以外,它所隐含的假定是单个页面给出单个基本视图。
对
MVC
的误解
必须采用复杂的框架
框架有时很有用
Struts
JavaServer Faces (JSF)
但并非必需
!
对于大多简单或者适度复杂的应用来说,使用内建的
RequestDispatcher
就能够很好地实现
MVC
MVC
影响整个系统的设计
我们可以用
MVC
来处理单个请求
可以将它认为是
MVC
方案,而非
MVC
框架。
也被称为是模型
2
方案
用
RequestDispatcher
实现
MVC
1.
定义用以表示数据的
java bean
2.
使用一个
servlet
处理请求
servlet
读取请求参数,检查数据的缺失或异常等。
3.
填充
bean
该
servlet
调用业务逻辑或数据访问代码得到最终的结果。得出的结果被放在第一步中定义的
bean
中。
4.
将
bean
存储在请求
,
会话或
servlet
的上下文中
该
servlet
调用请求、会话或
servlet
上下文对象的
setAttribute
存储表达请求结果的
bean
的引用。
5.
将请求转发到
JSP
页面
该
servlet
确定哪个
JSP
页面适合于处理当前的情形,并使用
RequestDispatcher
的
forward
方法将控制转移到那个页面。
6.
从
bean
中提取数据
JSP
页面使用
jsp:useBean
和与第
4
步匹配的位置访问之前存储的
bean
,然后使用
jsp:getProperty
输出
bean
的属性。
JSP
页面并不创建或修改
bean
;它只是提取并显示由
servlet
创建的数据。
jsp:useBean
在
MVC
中的使用与在独立
JSP
页面中有什么不同
JSP
页面不应该创建对象
应该由
servlet
创建所有的数据对象。因此,为了保证
JSP
页面不会创建对象,我们应该使用
<jsp:useBean ... type=
“
package.Class
”
/>
而不是
<jsp:useBean ... class="package.Class" />
JSP
页面也不应该修改已有的对象
因此,我们应该只使用
jsp:getProperty
,不使用
jsp:setProperty
。
提示:
jsp:useBean
的
scope
选项
request
<jsp:useBean id="..." type="..." scope="request" />
session
<jsp:useBean id="..." type="..." scope="session" />
application
<jsp:useBean id=".." type=".." scope="application" />
page
<jsp:useBean id=
“
...
”
type=
“
...
”
scope=
“
page
”
/>
或者仅仅使用
<jsp:useBean id="..." type="..." />
MVC (Model 2)
构架不使用这个
scope
。
不同数据共享方式
向用户显示一个随机的数字。
由于每次请求应该产生新的数字,因而基于请求的共享是恰当的。
显示用户的姓和名
数据要为每个客户存储,因而基于会话的共享比较适用。
显示一个指定长度的质数。
数据在多个客户间共享,因此,基于应用的共享比较恰当。
基于请求的数据共享
Servlet
ValueObject value = new ValueObject(...);
request.setAttribute("key", value);
RequestDispatcher dispatcher =
request.getRequestDispatcher("/WEB-INF/SomePage.jsp");
dispatcher.forward(request, response);
JSP
<jsp:useBean id="key" type="somePackage.ValueObject"
scope="request" />
<jsp:getProperty name="key" property="someProperty" />
基于会话的数据共享
Servlet
ValueObject value = new ValueObject(...);
HttpSession session = request.getSession();
session.setAttribute("key", value);
RequestDispatcher dispatcher =
request.getRequestDispatcher("/WEB-INF/SomePage.jsp");
dispatcher.forward(request, response);
JSP
<jsp:useBean id="key" type="somePackage.ValueObject"
scope="session" />
<jsp:getProperty name="key" property="someProperty" />
基于
ServletContext
的数据共享
Servlet
synchronized(this)
{
ValueObject value = new ValueObject(...);
getServletContext().setAttribute("key", value);
RequestDispatcher dispatcher =
request.getRequestDispatcher("/WEB-INF/SomePage.jsp");
dispatcher.forward(request, response);
}
JSP
<jsp:useBean id="key" type="somePackage.ValueObject
“
scope="application" />
<jsp:getProperty name="key" property="someProperty" />
JSP
页面中的相对
URL
问题:
使用请求分配器进行的转发对客户来说是透明的。初始的
URL
是浏览器惟一知道的
URL
。
为什么这会比较重要?
浏览器会如何处理类似下面的这些标签:
<IMG SRC="foo.gif"
…
>
<LINK REL=STYLESHEET
HREF="JSP-Styles.css" TYPE="text/css">
<A HREF="bar.jsp">
…
</A>
答案:浏览器将会把它们看作是相对于
servlet
的
URL
最简单的解决方案:
使用以斜杠开始的
URL
Summary
MVC (Model 2)
方式适用于:
单次提交会产生多个基本外观。
几个页面拥有大量公共的处理过程。
需要为同样的数据提供多个视图的应用程序
,
它很好地实现了数据层与表示层的分离,特别适用于开发与用户图形界面有关的应用程序
构架
由一个
servlet
应答初始的请求
Servlet
完成实际的数据处理并将结果存储在
bean
中
Bean
存储在
HttpServletRequest, HttpSession,
或
ServletContext
中
Servlet
使用
RequestDispatcher
的
forward
方法将请求转发到
JSP
页面
JSP
页面通过使用
jsp:useBean
和相应的作用域
(request, session, application)
从
bean
中读出数