本专题我们讨论用JSP,Servlets,和JavaBean来构成一个系统的几种途径。下面有集中不同的结构。每一种都是从上一种发展过来的,下面的图表显示了发展过程的梗概。
[myimg]upload/yk36image002.png[/myimg]
[myimg]upload/yk36image004.png[/myimg]
[myimg]upload/yk36image006.png[/myimg]
当Sun公司开始推广JSP的时候,很多人认为可以通过Web页面来请求的企业级结构将会取代Servlet。虽然JSP是J2EE规范的关键组成部分,它处理请求和应答机制。我们需要更深入的研究JSP和Servlet的关系。
专题的另一个部分谈了JSP代码的实现细节,如何编译转化为Servlet。JSP是建立在Servlet API基础之上的,;利用了Servlet的语义。理解了这个,提出一个有意思的问题:我们是否不再需要在使用WEB的系统中开发标准的Servlet?是否有一种方法来结合JSP和Servlet?如果有的话,我们需要把Java代码放在何处?在JSP的请求过程中,是否涉及到了其他的组件,比如说 JavaBean?如果有的话,他们在这个体系结构处与什么位置,扮演什么角色?
明白这些问题是很重要的。虽然JSP技术是基本的Servlet技术的继承,但是JSP在Servlet的基础上有所创新,他们可以互相协作,互相补充对方的不足。
在这个前提下,我们来探讨这两种Java扩充技术的和其它技术,比如JavaBean,的协作问题。在讨论结构之前,我们先简单的看看开发这样的结构的系统有什么要求。
1、 代JSP码因素、角色分离:
技JSP术能够进展到现在这个地步,一个很重要的原因就是需要有一门技术,通过把静态数据变成分离的动态数据,来简化应用程序的设计。是java把代 HTML码嵌入页java面中。但是,随着应用程序越来越多的基于应用逻辑对象和多层体系结构,需要把代HTML码从页JSP面中分离出来,同时还需要保持技JSP术的完整性和灵活性。好的应用程序设计风格要求把应用对象分离出来,应用对象的声明和操作也要易于区分。
使用的WEB另一个好处是让我们更明确的把页Servlet面的设计和软件的设计区分开来。注意,通常的都JAVA是以代HTML码的形式嵌入到页Servlet面中。现在,把看java成是代HTML码的独立的容器,而的页JSP面变成了页JAVA面。新的问题又出现了,需要把多少代JSP码放在中JAVA,把代JSP 码从中Web分离出来,我们把它放在什么地方。
对于所有基于的HTML工程,都存在不同角色,不同责任的情况。例如:有人负责编写页java面,还有人负责程HTML序设计。
对于那些规模比较小的工程,也许这些都是由一个或者两个联系非常紧密的人人来完成。但是对于稍微大一点的工程,更倾向于把把任务分给多人来完成,也许这写的JAVA人不懂,JAVA写的HTML对却JAVA不很熟悉。这样,如果太依赖于别人的工作进度,工作效率就会很低。
如果能够把代JSP码从中WEB分离出来,那么,软件开发人员和设Servlet计人员的工作就相对来说更独立了一些。但是,这样的情况可能会导致容易发生一些错误,因为两部分人独立之后,每部分人都可能不经意就改变了自己的代码。
这样我们就理解了为什么我们会继续使用一些基本的。JSP它是一个装载从中JAVA分离出来的代JSP码的容器,是软件开发人员与页JSP面尽量保持一种松散的联系。当然,还需要有人来写代JSP码页面。但是其依赖性就降低了。
为了支持这样的开发人员角色的分离,要使中JAVA的代JAVA码尽量的少。我们知道,有些代Servlet码是以的Servlet形式起中间媒介作用的。象身份鉴定,是一种多次请求的代码,这样就很适合用来JSP实现。
同时,要把许多的应用逻辑和数据访问代码从中JavaBean分离出来,包装成为。JSP这样,我们可以看到从中JAVA的代Servlet码转移到了两个地方,一个是作为,JSP代码在的JavaBean前端,还有一个就是作为后端的。
Redirecting and Forwording
Redirect和Forword是JSP和Servlet经常使用的两种机制。
当JSP或者Servlet用Redirect机制来重定向客户的请求的时候,服务器给客户发一个http 302消息,告诉客户要请求的资源转移到了另一个URL。然后客户再去向新的URL发请求。而Forword机制是指Servlet发现要请求的资源在另一个URL上,那么,由Servlet自己去象这个URL请求,然后再把结果送给客户。
体系结构:
在讨论体系结构之前,有必要提一下两种使用JSP技术的基本方法
第一种是以页面为中心(Page-Centric)的(Client/Server)方式,这样方式是把请求直接发给JSP页面。
第二中方式分发方式(多层结构的)。这种方式以一个JSP或者Servlet做为一个基本的控制器,又它把请求分给JSP页面或者JavaBean。
下来,我们会用一个简单的例子来讨论这两种方式的区别。
1、首先我们看看Page-Centric的结构。这样的结构通常都是来客户机和服务器端都有一个应用程序。最常见的例子是PowerBuilder的例子。Servlet或者JSP在服务器端截获客户的请求,直接的访问数据库等资源。
[myimg]upload/yk36image008.png[/myimg]
这个结构的优点就是编程简单。允许页面的设计者根据资源的状态动态的生成页面的内容。但是,这样的结构不适合多个客户同时访问资源,这样同时会有大量的请求需要服务端来处理。每个请求都会建立一个连接,消耗一定的资源。这样,需要让这些连接共享一些资源。其中最明显的例子就是用JDBC连接数据库中用到的连接池(Connection pools)。对结构使用不适当的话,会导致JSP中出现大量的JAVA代码。这虽然对java程序设计人员不会有什么问题,可是大量的代码分散在JSP 中,不利于维护和修改。
这种基本的结构包括通过嵌入在JSP中的代码直接的向服务器发请求。这样有几个优点:从开发看来,成本很低。所有的JAVA代码都嵌入到HTML中,复杂性降低了。
[myimg]upload/yk36image010.png[/myimg]
减少了复杂性,当系统规模增大的时候,这种结构的缺点也出来了。例如,把太多的应用逻辑放到了JSP页面中。前面我们提到,利用Servlet或者Bean可以把开发者角色分的更清楚,提高代码的可重用性。
下面我们主要多层结构的JSP,在这种结构下,用一个Servlet或者JSP当作主要的控制器。将所有的客户请求分配给其它的JSP、JavaBean或者EJB。
在一个多层结构的应用系统中,服务端的被分成好几层,如下图所示:
[myimg]upload/yk36image012.png[/myimg]
在这个例子中,应用系统是一个多层结构的,中间层的JSP通过其它的对象或者Enterprise JavaBean来访问后台资源。EJB服务器和EJB提供访问访问资源的方法,支持事务,支持安全管理。目前,J2EE支持这样的编程。
多层结构应用设计的第一步,是明确系统涉及的对象和他们之间的关系。也就是首先要确定对象模式。这一步可以通过Rational Rose之类的工具来实现。通常,对象模式的确定需要特别小心,如果对象太多,会增加系统的复杂性。如果对象模式做的好的话,可以说系统就成功了一半。
然后是确定JSP和Servlet,根据他们扮演的角色的不同,分成两类。在J2EE中都叫做web组件。
1、 一类(Front-end)是用来处理应用流程的。其中有很多对后台对象(例如EJB)的调用。他们不处理页面的表示问题,只是截获从用户过来的请求,提供应用系统的一个入口。简化安全管理,而且易于控制应用系统的状态。
2、 还有一类(Presentation)是用来生成HTML或者XML的。这些JSP主要的目的就是来动态的产生页面内容。
下图表示了这两类之间的关系,第一类(Front-end)接收一个请求,然后选择一个合适的Presentation组件来处理。处理之后,或者直接把结果返回给客户,或者把结果返回给另一个前端组件。
[myimg]upload/yk36image014.png[/myimg]
有时这种对象模式的划分是比较困难的。但是,划分的越清晰,那设计也越清晰。
这种分类有点类似与模式-视图(Model-View)结构,front-end相当于Model,presentation相当与View。如下图:
[myimg]upload/yk36image016.png[/myimg]
在这个模式下,JSP用来产生表示层或者执行一些操作。Front-end组件当作控制器,处理客户的请求,生成JavaBean和EJB对象。而在Presentation JSP组件中并没有处理逻辑过程,只是简单的从别的对象中得到数据,然后动态的插入到模板中。
如果不愿意写front-end类型的Servlet,也可以写一些只包括代码,不包含任何Presentation表示部分的逻辑。不管是写 Servlet还是写JSP,这样的结构都把内容和表示分开了,将程序开发者和页面设计者比较明确的区分开来。对系统,特别是比较大规模的系统的设计是比较适合的。
在JSP中使用JavaBean和用Enterprise JavaBean是有区别的。使用JavaBean的时候,通常只是使用简单的类来包装数据信息。JavaBean通过简单的get或者set方法来存取 JavaBean的属性值。允许用jsp:usebean标签来动态的设定属性值。用Enterprise JavaBean的话,过程比较复杂一些,首先要初始化上下文,然后通过名字根据名字服务找到所需要的EJB,创建一个实例之后,就可以使用了。
Enterprise JavaBean的写法和配置我们原来谈过,这里就不再说了,感兴趣的朋友可以查阅以前的文章,这里我们只是举一个如何从JSP中调用EJB的例子。例子的环境是tomcat3.1+IAS4.1。写好EJB之后,首先要启动IAS,并且在IAS中配置好EJB。然后在IAS的安装目录下的ejb_jar 子目录下面,你会发现有jar文件,以后每次IAS启动之后,就把这个目录下所有的jar文件中的EJB都装载好,并把JNDI名字注册到JNDI的名字空间中。以后就可以直接通过JNDI名字获得EJB的接口了。
假设我们已经写好了一个EJB。IAS也已经启动了,JNDI并配置好。其名Sample字为"”JSP。要从中EJB调用,javax.naming.* 需要先把、javax.rmi.PortableRemoteObject import进EJB来,另外,还要把组home件的接remote口,接import口也进@ page import 来:
〈%= "javax.naming.*" %>/JNDI/名@ page import 字服务模块
<%= "javax.rmi.PortableRemoteObject" %>/RMI/调@ page import 用模块
<%= "samples.*" %>/EJB/的home,remote接InitialContext ctx 口
<%
= new InitialContext( );/Object ref /初始化上下文
= ctx.lookup(Sample"" );/JNDI/通过名SampleHome samplehome字得到对象的接口
;samplehome
=SampleHome()PortableRemoteObject.narrow(ref,SampleHome.class) ;
/home/把对象强制转化为接EJB口类。这样就得到了对Home象的接EJB口,然
//后再按规EJB范,根据不同的类EJB型,通过不同的方法得到的Home
//接SampleRemote remote 口类。
= samplehome.create( );
/home/通过接create口的方remote法得到接 口。
/remote/接下来就可以通过来EJB调用中的方法了。
……
……
%>