Java杂谈(八)--Servlet/Jsp

Ant 2007-11-05 09:39:57
Java杂谈(八)--Servlet/Jsp

终于正式进入J2ee的细节部分了,首当其冲的当然是Servlet和Jsp了,上篇曾经提到过J2ee只是一个规范和指南,定义了一组必须要遵循的接口,核心概念是组件和容器。曾经有的人问笔者Servlet的Class文件是哪里来的?他认为是J2ee官方提供的,我举了一个简单的反例:稍微检查了一下Tomcat5.0里面的Servlet.jar文件和JBoss里面的Servlet.jar文件大小,很明显是不一样的,至少已经说明了它们不是源自同根的吧。其实Servlet是由容器根据J2ee的接口定义自己来实现的,实现的方式当然可以不同,只要都遵守J2ee规范和指南。

上述只是一个常见的误区罢了,告诉我们要编译运行Servlet,是要依赖于实现它的容器的,不然连jar文件都没有,编译都无法进行。那么Jsp呢?Java Server Page的简称,是为了开发动态网页而诞生的技术,其本质也是Jsp,在编写完毕之后会在容器启动时经过编译成对应的Servlet。只是我们利用Jsp的很多新特性,可以更加专注于前后台的分离,早期Jsp做前台是满流行的,毕竟里面支持Html代码,这让前台美工人员可以更有效率的去完成自己的工作。然后Jsp将请求转发到后台的Servlet,由Servlet处理业务逻辑,再转发回另外一个Jsp在前台显示出来。这似乎已经成为一种常用的模式,最初笔者学习J2ee的时候,大量时间也在编写这样的代码。

尽管现在做前台的技术越来越多,例如Flash、Ajax等,已经有很多人不再认为Jsp重要了。笔者觉得Jsp带来的不仅仅是前后端分离的设计理念,它的另外一项技术成就了我们今天用的很多框架,那就是Tag标签技术。所以与其说是在学习Jsp,不如更清醒的告诉自己在不断的理解Tag标签的意义和本质。

1. Servlet以及Jsp的生命周期
Servlet是Jsp的实质,尽管容器对它们的处理有所区别。Servlet有init()方法初始化,service()方法进行Web服务,destroy()方法进行销毁,从生到灭都由容器来掌握,所以这些方法除非你想自己来实现Servlet,否则是很少会接触到的。正是由于很少接触,才容易被广大初学者所忽略,希望大家至少记住Servlet生命周期方法都是回调方法。回调这个概念简单来说就是把自己注入另外一个类中,由它来调用你的方法,所谓的另外一个类就是Web容器,它只认识接口和接口的方法,注入进来的是怎样的对象不管,它只会根据所需调用这个对象在接口定义存在的那些方法。由容器来调用的Servlet对象的初始化、服务和销毁方法,所以叫做回调。这个概念对学习其他J2ee技术相当关键!

那么Jsp呢?本事上是Servlet,还是有些区别的,它的生命周期是这样的:
a) 一个客户端的Request到达服务器 ->
b) 判断是否第一次调用 -> 是的话编译Jsp成Servlet
c) 否的话再判断此Jsp是否有改变 -> 是的话也重新编译Jsp成Servlet
d) 已经编译最近版本的Servlet装载所需的其他Class
e) 发布Servlet,即调用它的Service()方法

所以Jsp号称的是第一次Load缓慢,以后都会很快的运行。从它的生命的周期确实不难看出来这个特点,客户端的操作很少会改变Jsp的源码,所以它不需要编译第二次就一直可以为客户端提供服务。这里稍微解释一下Http的无状态性,因为发现很多人误解,Http的无状态性是指每次一张页面显示出来了,与服务器的连接其实就已经断开了,当再次有提交动作的时候,才会再次与服务器进行连接请求提供服务。当然还有现在比较流行的是Ajax与服务器异步通过xml交互的技术,在做前台的领域潜力巨大,笔者不是Ajax的高手,这里无法为大家解释。

2. Tag标签的本质
笔者之前说了,Jsp本身初衷是使得Web应用前后台的开发可以脱离耦合分开有效的进行,可惜这个理念的贡献反倒不如它带来的Tag技术对J2ee的贡献要大。也许已经有很多人开始使用Tag技术了却并不了解它。所以才建议大家在学习J2ee开始的时候一定要认真学习Jsp,其实最重要的就是明白标签的本质。

Html标签我们都很熟悉了,有<html>、<head>、<body>、<title>,Jsp带来的Tag标签遵循同样的格式,或者说更严格的Xml格式规范,例如<jsp:include>、<jsp:useBean>、<c:if>、<c:forEach>等等。它们没有什么神秘的地方,就其源头也还是Java Class而已,Tag标签的实质也就是一段Java代码,或者说一个Class文件。当配置文件设置好去哪里寻找这些Class的路径后,容器负责将页面中存在的标签对应到相应的Class上,执行那段特定的Java代码,如此而已。
说得明白一点的话还是举几个简单的例子说明一下吧:

<jsp:include>去哪里找执行什么class呢?首先这是个jsp类库的标签,当然要去jsp类库寻找相应的class了,同样它也是由Web容器来提供,例如Tomcat就应该去安装目录的lib文件夹下面的jsp-api.jar里面找,有兴趣的可以去找一找啊!

<c:forEach>又去哪里找呢?这个是由Jsp2.0版本推荐的和核心标记库的内容,例如<c:if>就对应在页面中做if判断的功能的一断Java代码。它的class文件在jstl.jar这个类库里面,往往还需要和一个standard.jar类库一起导入,放在具体Web项目的WEB-INF的lib目录下面就可以使用了。

顺便罗唆一句,Web Project的目录结构是相对固定的,因为容器会按照固定的路径去寻找它需要的配置文件和资源,这个任何一本J2ee入门书上都有,这里就不介绍了。了解Tag的本质还要了解它的工作原理,所以大家去J2ee的API里找到并研究这个包:javax.servlet.jsp.tagext。它有一些接口,和一些实现类,专门用语开发Tag,只有自己亲自写出几个不同功能的标签,才算是真正理解了标签的原理。别忘记了自己开发的标签要自己去完成配置文件,容器只是集成了去哪里寻找jsp标签对应class的路径,自己写的标签库当然要告诉容器去哪里找啦。

说了这么多,我们为什么要用标签呢?完全在Jsp里面来个<% %>就可以在里面任意写Java代码了,但是长期实践发现页面代码统一都是与html同风格的标记语言更加有助于美工人员进行开发前台,它不需要懂Java,只要Java程序员给个列表告诉美工什么标签可以完成什么逻辑功能,他就可以专注于美工,也算是进一步隔离了前后台的工作吧!

3. 成就Web框架
框架是什么?曾经看过这样的定义:与模式类似,框架也是解决特定问题的可重用方法,框架是一个描述性的构建块和服务集合,开发人员可以用来达成某个目标。一般来说,框架提供了解决某类问题的基础设施,是用来创建解决方案的工具,而不是问题的解决方案。

正是由于Tag的出现,成就了以后出现的那么多Web框架,它们都开发了自己成熟实用的一套标签,然后由特定的Xml文件来配置加载信息,力图使得Web应用的开发变得更加高效。下面这些标签相应对很多人来说相当熟悉了:
<html:password>
<logic:equal>
<bean:write>
<f:view>
<h:form>
<h:message>

它们分别来自Struts和JSF框架,最强大的功能在于控制转发,就是MVC三层模型中间完成控制器的工作。Struts-1实际上并未做到真正的三层隔离,这一点在Struts-2上得到了很大的改进。而Jsf向来以比较完善合理的标签库受到人们推崇。

今天就大概讲这么多吧,再次需要强调的是Servlet/Jsp是学习J2ee必经之路,也是最基础的知识,希望大家给与足够的重视!
...全文
220 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
SINCE1978 2007-11-08
  • 打赏
  • 举报
回复
尚未用过struts2和jsf,尤其后者风头正劲。论坛上有骂jsf不好用的,但是也有骂struts1的,所以说实话还是不了解。
框架、设计这些东西现在我的感觉终究有点虚:各类框架开始时候老外的想法是好的:利用技术优势重用不变的东西、统一标准、快速开发...但是我觉得在国内也害了一些人...而在设计上,现在的java流行的是web,现在web下的java开发还用的着设计吗?最多最多是对框架选选型!你还有的别的选择吗?没有。框架变来变去、理论没完没了。
“再次需要强调的是Servlet/Jsp是学习J2ee必经之路,也是最基础的知识”楼主这句话比较厚道,楼主适合真正做点技术,选择外企或出国吧。
kaoloveting 2007-11-08
  • 打赏
  • 举报
回复
hava a look
Ant 2007-11-07
  • 打赏
  • 举报
回复
楼上这位朋友的观点我还是满赞同的,死扣概念没有意义……
MVC只是一个设计理念,甚至本身并不是源自J2ee或者Web开发,所以控制层这个概念显得可有可无,只是大家想表达MVC的核心思想就是前端控制器时候加上去的,
我们不必去追究它的视图和模型到底是属于Web开发的哪一个层次。Action是否属于模型层是要看程序员怎么去用,M和V还有C甚至都可以属于表示层也没有问题。

那么我们再说Struts-2和Strut-1的区别,在J2ee开发的服务端是存在着分层概念的,涉及页面及Request和Response的都属于Web层即我们常说的表示层,Web层之后应该是模型层即业务层然后再是数据层,我们不必死扣那个名字。我们如果用Action来处理业务方法的话,真正做到隔离是不能在Action中获得对Request对象的引用的,因为当到达业务层之后要完全脱离Request和Response对象,这一点不可否认Struts-1最初是没有考虑到的而在Struts-2得到改善,因为Request被当成参数传进了execute方法中。

当然,你也可以不在Action中处理业务逻辑,那么这个时候Action只做为一个解析页面传过来数据的一个工具,它调用后台其他类来做业务逻辑,把数据传过去,这样子的话Action就属于Web层了,那么它并未脱离Request对象就没什么不合理的地方了。(实际上现在很多开发也正是这么做的)

我指的隔离是指真正处理业务逻辑的对象即Business Object,不应该跟Request有耦合关系,不管它是由Action来充当还是别的对象来充当。

SINCE1978 2007-11-07
  • 打赏
  • 举报
回复
回复楼上的朋友:“那么Jsp呢?Java Server Page的简称,是为了开发动态网页而诞生的技术,其本质也是servlet”——这句话是我写的、楼主原文是“其本质也是jsp”。

回复楼主:无论struts1、2、3...n还是jsf 其表现层的底层仍然全部是用jsp的特性,没用过Struts-2,不过按你说的应该是对request处理并包装了一下,不知你对“隔离”怎么定义的,如果就是包装一下换个类名就叫隔离了那只是表象。现有的mvc框架是不可能脱离request、response的而且也不应该。实际编程当中你也脱离不开。Action是否属于模型层一直有争议,Action由控制层直接调用得到其execute方法处理结果,并且action决定下一步的转发,我的看法是action属于控制层。很多理论其实是来源于实践总结的,死扣mvc理论没什么意思。
DirectRay 2007-11-06
  • 打赏
  • 举报
回复
回复四楼的朋友,JSP的确是这样缩写的,而且JSP里面的所有Java代码都会被容器编译成Servlet,所以,这话并没有错。
Ant 2007-11-06
  • 打赏
  • 举报
回复
其实很明显的是我们在模型层的Action的execute方法中还可以获得表示层的request和response对象,这就说明了模型层并未真正与表现层隔离,如果仁兄你看看Struts-2的话,所有的Request到Action前都会被拦截下来做一部解析处理再到模型层的Action的
SINCE1978 2007-11-06
  • 打赏
  • 举报
回复
不知道你是怎么得出“Struts-1实际上并未做到真正的三层隔离”这种结论的。
SINCE1978 2007-11-06
  • 打赏
  • 举报
回复
“ 说了这么多,我们为什么要用标签呢?...”
用标签的意义远远不止于和美工协作。
标签必须和相应的mvc框架一起用才能产生真正的价值,比如struts标签可以说支撑起struts核心功能的70%,说起来不起眼,就是协助mvc分层,实则作用巨大。写过jsp的人用用struts后再回头看看自己写的jsp才能明白。
SINCE1978 2007-11-06
  • 打赏
  • 举报
回复
“那么Jsp呢?Java Server Page的简称,是为了开发动态网页而诞生的技术,其本质也是servlet”
找着一个口误、呵呵。
Ant 2007-11-05
  • 打赏
  • 举报
回复
http://topic.csdn.net/u/20070924/21/18482496-082f-4907-8751-b80ab5d56622.html
这是第一篇,版主让我每次完成续篇都追加到回复中
所以里面都有
约翰羊 2007-11-05
  • 打赏
  • 举报
回复
请问能不能把前几篇的地址一并粘出来?谢谢.
Ant 2007-11-05
  • 打赏
  • 举报
回复
培训结束,终于有继续写续篇,希望对大家有帮助

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧