javaMVC模式是将servlet和jsp结合起来的技术。servlet适合数据处理,而jsp适合显示。这个模式充分发挥了每项技术的优点。
一、MVC 需求
如果需要大量的数据处理servlet很合适,但是servlet对html的处理很冗长难以修改,这就是使用jsp的原因。将视图从复杂的数据和逻辑处理中解放出来。
但是当jsp显示内容需要根据不同的需求生成差异较大的页面的时候我们就需要将jsp显示和servlet的逻辑处理结合起来。通常使用的模式是MVC模式。可以
使每项技术发挥它最大的功效。初始请求由servlet来处理,调用逻辑和数据处理代码,并穿件bean来表示响应的结果(即模型)。然后servlet确定由哪个jsp页面显示比较合适并将请求转发到jsp(即视图)。servlet就是控制器。
使用MVC的目的就是将逻辑操作和数据操作和显示代码分离。在相对较复杂的项目中使用框架是更好的更方便的选择。(Apache struts2)。但是相对于使用框架来说
从头开始自己创建MVC的实现(使用RequestDispatcher请求转发)更直观更灵活。
二、使用RequestDispatcher来手动创建MVC。
1.定义bean来表示数据
2.使用servlet来处理请求
3.填写bean
4.将bean存储到请求,会话或者servletcontext中
5.将请求转发给jsp
这里要说的是当一个请求转发的时候是将HttpServletRequest对象转发到jsp页面,而重定向(sendRedirect)是重新创建一个请求。(这里要注意的是如果jsp页面的显示只有在servlet上下文中才有意义的话可以讲页面放在WEB-INF目录中,因为这个目录用户是不能直接访问的,但是服务器可以访问)
如果是将bean存储在会话或者servletcontext 中时有的情况下使用重定向要比请求转发更有效
6.从bean中读取数据并显示
读取的时候jsp页面是使用的jsp:useBean标签及子标签来显示的,但是需要注意的是在这不能重新创建bean使用的标签应该这样:
<jsp:useBean ... type="package.class" />来代替创建新bean 的<jsp:useBean ... class="package.class" />
还有一点要注意的是jsp页面不能用来设置bean只能读取即<jsp:getProperty />标签。还要注意读取bean是基于那种共享(Request,session,application)
三、目的页面中相对URL的解释
使用RequestDispatcher来转发请求时最终URL是最初的servlet请求维持最初的请求不变,使用sendRedirect重定向的时候是重新创建请求并且URL是最终显示页面的URL
还有一个需要注意的是如果jsp页面使用图像和导入js或者css的时候,RequestDispatcher的相对路径应该是相对于初始servlet的相对路径,而sendRedirect 的文件相对路径是相对于最终请求的页面的相对路径
四、三种数据共享方式的对比
当数据在每个请求不同的时候使用请求共享,
当数据在会话的时候不变的情况下使用会话共享,
如果在整个程序运行的状态下数据都不需要重新定义的话使用应用程序共享。
五、在jsp中使用转发
在jsp中使用转发的方式可以是<jsp:forward page="relative URL">和scriptlet中,但是使用xml标签显然要比封装到RequestDispatcher中要方便许多,还有一个原因是效率要高。jsp:forward标签可以使用jsp:param作为子标签,为转到的页面提供额外的参数。在servlet中的后台实现就是RequestDispatcher类的forward方法。
六、包含页面
使用jsp转发是利用servlet产生数据用jsp输出servlet不产生输出。还有一种方法是使用页面包含,可以讲servlet自身的输出及一个或多个jsp页面的输出组合到一起。RequestDispatcher的include方法就是jsp标签<jsp:include>的后台实现。如:
import javax.servlet.*;
//doSomething
RequestDispatcher rd=request.getRequestDispatcher("jsp路径");
rd.include(当前servlet的Request对象,当前servlet的response对象);
//doSomething
这端代码就是jsp:include的实现方法只包含页面的输出内容而不是如<%@ include%>命令那样讲整个文件的内容包含进去。
七、EL表达式
EL(表达式语言)是为了计算和输出存储在标准位置的java对象的值。另一个特性是用jsp语法(而非Java语法)定义定制标签的能力。
优点:1.精确访问存储对象。输出用setAttribute存储的对象。
2.bean属性的简略记法。使用bean(name).attribute(name)访问bean属性。
3.对集合元素的简单访问。使用${variable[index or key]}
4.请求参数、cookie和其他请求数据的简单访问。
5.实现一些简单的运算。
6.选择性输出。(${test?option1:option2})
7.自动类型转换。
8.空值取代错误消息。
停用EL表达式
1.停用整个WEB应用中的表达式语言。
修改web.xml文件的兼容版本
2.停用多个jsp页面中的表达式语言。
修改web.xml文件,在其中添加如下标签:
<jsp-property-group>
<url-pattern>jsp Path</url-pattern>
<el-ignored>true or false</el-ignored>
</jsp-property-group>
true为停用false为启用
3.停用个别页面中的表达式语言。
在需要停用EL表达式的页面加入如下语句:
<%@ page ignored="false"%>
true为启用false为停用
4.停用表达式语言的个别语句。
将$符号用$替换,这个表达式就失效了
需要注意的是在jsp2.0的jsp页面上如果想要输出${}这个符号需要使用转意字符\${}表示这个和将$用$是一样的效果
就自己的理解与体会,谈谈Java中的MVC模式开发,希望对初学Java的朋友有点帮助.
就目前而言,Java主要用于Web开发,即J2EE应用部分,说得难听点,从表面来看就是做
网站,当然,这种网站不是简简点点由一些HTML堆成的.
就我看来,目前在厦门招的Java程序员,主要也是从事MVC模式的开发居多.
以下以一个在线图书借阅系统为例.
1. 问题出现
如果是要开发一个在线图书借阅系统,比如说是集美大学图书馆的借阅系统,这个系统
希望被做成B/S模式的,用户只要有浏览器就可以使用这个系统.
那么,在开发语言方面,我们可以选择使用纯JSP来开发.
OK. 如果你选用纯JSP来开发,那么对于一个图书查询功能来说,你可能会这样实现:
在一个JSP页面中,比如叫BookSearch.jsp中,你放置了一个表单,用户在这个页面中
填写图书查询关键字,并提交这个表单,这个表单提交到自身页面,即BookSearch.jsp
进行处理.BookSearch.jsp会在初始化页面时进行判断,如果有接收到用户提交的查询
关键字,则查询数据库,并把查询结果显示出来.如果没有,则只显示图书查询表单.即,
整个完整的业务功能流程是:
(提交查询请求) (拦截请求)
BookSearch.jsp <----> BookSearch.jsp
(显示查询结果) (执行业务逻辑)
如果你用这种方式完成了整个系统.那么,如果现在客户----集大图书馆希望除了B/S外,
还有个客户端,即桌面应用程序Application, 你便会发现,只为了多一个Application客
户端,你却基本上要重写这个系统.因为你之前写的那些jsp页面对于你写Application没
有什么帮助,代码无法重用.
2. 什么是MVC? 为什么要使用MVC?
如果我们使用MVC模式来开发,那么,以上代码无法重用的问题便迎刃而解.
M: Model,即模型,负责业务逻辑部分,含执行业务逻辑部分和业务对象部分,一般为普通
Java类或EJB
V: View,即视图,负责呈现在用户面前的部分,一般为JSP页面.
C: Controller,即控制器,负责整个流程的控制,一般为Servlet.
MVC就是视图、控制器、模型相分离的一种开发模式。
如果用MVC模式来实现图书查询功能,那便会是这样的:
在一个JSP页面中用户提交图书查询请求,Servlet拦截这个请求,并转发到相应的Java类/
EJB进行图书信息查询. 执行完图书查询后,返回查询结果给Servlet. Servlet把查询结果
传给JSP,JSP显示查询结果.
即流程为:
(提交查询请求) (拦截请求/C) (执行业务逻辑)
BookSearch.jsp(V) <----> Servlet(C) <---> 普通Java类/EJB(M)
(显示查询结果) (转发到JSP)
如果是基于以上MVC模式实现,那么,如果此时希望系统多一个Application的客户端,
则只需要添加C和V部分即可,M部分可以代码重用,大大提高工作效率.
除了代码重用外,MVC还可以让逻辑更加清晰,各个组件都在实现什么功能非常清楚----
V作视图,C作控制器,M执行业务逻辑,这样对开发效率也有非常大的提高.试想一下,如果
是像以上的纯JSP实现方式那样,把MVC混合在一个.jsp中,那么调试维护都是很困难的.
3. MVC模式的具体实现
在具体的实现上,View一般为JSP页面,它包含提交请求的页面(图书查询页面)和业务逻
辑执行结果的显示页面(查询结果页面).这两个页面,有时可以集合成一个页面.JSP页面
提交业务逻辑执行请求给Servlet,Servlet从普通Java类/EJB取得返回结果并返回给JSP,
组织返回结果显示给用户. JSP只负责显示信息,不处理业务逻辑.
在JSP页面中,我们可以使用scriptlet,即嵌入在jsp页面中的java代码,控制组织显示界面
.
但我认为这不是一个好的选择.因为,如果网页美工与Java程序员不是同一个人,而且美工
不懂Java(虽然俺还没有真的见过这种情况,现在很多小公司都是前后台同一个人,即网页
美工同时也是Java程序员),那么,面对在.jsp页面中的一大堆Java代码,美工人员会很头疼
.
而且,假设前后台开发人员不分离,那么在一个页面中调试与维护一个嵌入大量代码的jsp
页面也是很麻烦的, 比如.jsp中的
<%
}
%>
多了,总让人看了头晕. 更好的选择是使用TabLib,如JSTL。 使用JSTL,可以把形如
<%
if() {
....
}
%> 的scriptlet变成
<c:if ****>
之类的标签,这样对于jsp代码的阅读、调试与维护非常有利。如果在JSTL的基础上加上JS
P2.0
的表达式语言(Expression Language),则更进一步有利于写出清晰的JSP代码. 以下是一
个
JSTL+ EL的例子:
<c:if test="${!empty NotFoundMsg}">
<c:out value="<BR><font color=red>${NotFoundMsg}</font><BR>"
escapeXml="false" default=""/>
</c:if>
(如果参数NotFoundMsg不为空,则显示参数NotFoundMsg的内容).
以下提到的Struts中,有非常丰富的标签,那些标签基本上都覆盖了JSTL.
另外,在jsp页面中嵌入大量的CSS和Javascript代码,我认为也不是一个好的选择,同样的,
我认为分离和CSS和Javascript是更好的选择,分离出他们二者会让jsp代码各清晰,也各有
利于CSS代码和Javascript代码的复用.
Controller则一般为Servlet, Servlet拦截JSP提交的请求,并把请求转发到相应的Java
类/EJB上进行执行业务逻辑, 然后把Java类返回的结果,传给JSP.
Model一般为普通Java类/EJB,实现业务逻辑.这些普通Java类/EJB接收Servlet传过来的参
数,并由此执行业务逻辑,并把结果返回给Servlet. 目前, 大部分的中小项目都不使用EJB
了,EJB似乎越来越冷,甚至现在有一个口号叫: "J2EE without EJB",不过,以前EJB是J2EE
的核心.与EJB越来越冷相对的,Hibernate等ORM框架正在越来越热.
除了最原始的JSP+Servlet+Java类的实现外,现在还有很多的MVC框架,像Struts,WebWorks
等.其中,在中国现在最流行的是Struts框架,现在已经有越来越多的公司用Struts来进行
开发了.