基于JSP Servlet的Web应用框架的设计与实现.docx
- 文档编号:23064714
- 上传时间:2023-04-30
- 格式:DOCX
- 页数:16
- 大小:78.28KB
基于JSP Servlet的Web应用框架的设计与实现.docx
《基于JSP Servlet的Web应用框架的设计与实现.docx》由会员分享,可在线阅读,更多相关《基于JSP Servlet的Web应用框架的设计与实现.docx(16页珍藏版)》请在冰豆网上搜索。
基于JSPServlet的Web应用框架的设计与实现
基于JSP/Servlet的Web应用框架的设计与实现
周云,余青松,敬宗儒
(华东师范大学计算中心,上海200062)
摘要:
Web应用程序的开发过程中存在着Framework的应用。
这些Framework使开发过程十分规范。
它们自动地处理了部分非业务逻辑的过程.从而使得程序员的主要精力专注于业务逻辑的实现。
文中设计并且实现了一个简单的Framework模型,实现了部分的自动化处理。
该模型的构建,验证了采用最基本的Java语言工具以及设计方式实现Framework的可能性。
关键词:
Web应用框架;MVC;设计和实现
0.引言
在开发Web应用程序的过程中,特别是JSP应用程序,到处充斥着Framework的应用。
这些Framework的技术相当成熟,规范十分完整。
它们对于程序员的编码规范以及后台Model实体的管理相当完善。
文中关注的重点是如何用最基本的Java语言工具和设计方式来设计和实现一个带有自动化操作功能的Framework,从而深人理解一些Framework内在处理机制。
1.Framework概述
人们需要一个Framework来对软件开发提供支持,并且对程序员所书写的代码进行规范。
一些公共的非逻辑的处理过程应该做成共通模块,一些不好的编成习惯应该得到限制和纠正。
同时,与数据库打交道的数据Model也应该得到妥善管理。
另外,这些操作的共通特性都是高于模块级别但又属于代码级别的。
所以,应该设计出一个类似于规约性质同时又是以实际代码形式出现的管理体制。
于是,Framework便诞生了。
目前流行的Framework有很多,比如Struts,印ring,JSF等等[I]。
它们使JSP程序员从散兵游勇转化为了正规军。
它们的共同点都是拥有自动化操作“前端”以及资源管理的“后端”.笔者参照Struts的前端自动化操作过程设计并且实现了一个Framework模型,希望借此深入了解一些Framework的内部实现机制。
2.Framework模型的设计原则
最根本的原则是Framework要给开发过程带来便利,使得开发过程更加规范完善。
为了实现这个根本原则,必须解决两个问题:
(1)尽量将非业务逻辑自动化处理;
(2)将程序员的发挥空间进行限制。
对于第一个问题,通过对比研究可以发现,前台视图层回传参数一Servlet接受参数,并将参数封装到一个对象当中~Servlet选择正确的视图,并且进行显示,这三个步骤与业务逻辑没有关系[21。
不管你是什么业务逻辑,这三个步骤总会独立地执行。
业务逻辑只会出现在这三个步骤的间隙之间。
应该据此对这三个步骤分别进行封装,实现自动化处理。
对于第二个问题,可以提出一个简单的解决办法:
让程序员“只可能将正确的代码写在正确的地方”。
把其他与业务逻辑没有关系的代码全部进行封装即可。
综合所述,文中所描述的Framework模型的设计原则就是,封装非业务逻辑的操作,限制程序员的自由度。
当然,这只是一个Framework模型初步设计与实现,进一步的应用,需要按照标准的封装方式完善整个Framework模型。
3.Framework模型的设计
Web程序的设计遵循现在成熟的MVC设计模式。
Model的设计组合独立于Framework之外。
View是属于前台视图层。
Controler负责接收参数,调用对应的业务模型实体进行处理,返回对应的视图。
由此可见,对于业务模型实体的设计重要的一点就是它要能够自动地生成并且被Controller自动地调用,同时Controller还必须将对应的数据缓冲区传递给它。
那么业务模型所需要的就是一个标记,一个能够表明它身份的标记。
Framework模型的框架如图1所示,其Sequence图如图2所示;其UM类图如图3所示。
3.1获取前台视图传回的参数
先从获取前台视图传回的参数开始进行分析。
既然要对这个过程进行自动处理,那么程序要获取HttpServletRequest当中各个参数的名字,进行数据缓冲的实体的引用,进行数据缓冲实体当中各个对应属性的名字,进行属性设置和读取的所有方法的名字。
可以利用Java的RTTI机制解决这个问题。
3.2获取相应的ActionForm实体(数据缓冲区)引用
如果获取了HttpServletRequest当中所有的参数名字以及值,那么就可以把它们封装到一个具体的实体当中。
简言之,这个实体就是一个普通的Java类实体。
那么,这一步所遇到的问题就是如何获得这个实体的引用。
因为这个实体的创建应该由程序员完成,所以实体的类型就是千差万别的。
针对这种情况,应该把这些类做统一的管理,即把它们全部继承自一个Framework系统当中定义的基类。
同时,由于Action-Form只是纯粹的数据实体,业务处理方法没有存在的必要,所以ActionForm当中没有对方法进行扩展的必要。
因此,规定所有的ActionForm实体均继承自Framework当中指定的基类,这样就可以获取所有ActionForm实体的引用了。
3.3获取相应的Action实体(业务实体)的引用
创建了ActionForm实体之后,应该创建Action实体进行业务逻辑的处理。
为了获取Action实体的引用,可以采用类似于获取ActionForm引用的处理方法。
另外,,Action实体当中的业务处理方法也是千差万别,没有任何规律。
为了保证这些业务方法都被系统调用,可以采用类似于Servlet类的处理方式—定义一个被Framework调用的方法,其余的业务方法均被此方法调用。
这个被Framework调用的方法叫做executeAction,并且这个方法应该在基类当中定义。
Framework在获取了Action的引用之后,立即调用这个方法,从而执行所需的业务操作。
3.4创建视图层使用的PageBean实体
PageBean应该是在Action实体当中创建的。
它是属于视图层的。
其实Action-Fom,也可以用作PageBean,只是笔者认为一个独立的PageBean使得流程更为清晰PageBean只是一个POJO而已。
3.5返回到对应的视图层
在Action当中进行完业务处理之后,返回一个新的视图层的url给Controler,以便Controller进行正确的:
esponse导向。
3.6小结
综合分析可知,所需要知道和掌握的变量是:
HttpServletRequest当中的参数的名字,数据缓冲区中相应属性名字,数据缓冲区的引用,进行数据缓冲区操作的接口的名字,业务实体的引用。
JAVA的RTTI机制提供一些“盲操作”可供使用。
另外,有些信息可以放置在外部的文件存储当中。
这些存储信息的文件,可以称之为配置文件。
具体的代码实现请参见下文。
4.Framework模型的实现
为了便于代码的演示,有些代码体实际上解决了上面所描述的两个问题。
4.1获取前台视图传回的参数以及设置数据缓冲区
属性值前台回传的参数会被读取到一个数据缓冲区当中进行缓存,从而可以利用RTTI机制进行获取一个实体类的数据属性的名字川。
这里对编程的规范再次进行限制:
对于进行属性设置的函数必须是setter形式的函数,否则将不会进行调用。
这样,可以使用以下代码获取函数的入口。
Method[]m=c.getMethods();
Method[]methods=newMethod[m.length];
String[]propertiesName=newString[m.length];
String[]args=newString[m.length];
intcount=0;
obj=c.newlnstance();
bean=(Buffer)obj;
for(inti=0;i propertiesName[i]=m[i].tostring(); if(propertiesName[i].index0f("set")! =-1) } methods[count]=m[i]; args[count]=propertiesName[i]. substring(propertiesName[i].index0f("set")+popertiesName[il.index0f("(")); count++; } 得到了属性设置函数,便可以获取对应的属性。 接下来,就可以对缓冲区进行设置了。 调用Methoc类当中的invoke方法可以对缓冲区进行设置. 4.2获取数据缓冲区的引用及业务实体的代码实现 在实际的应用中,数据缓冲区以及业务实体必须生成实际的对象实体,并且有显式的应用。 否则,无法找到该内存块。 这些数据缓冲区和业务实体必须继承自指定的类。 笔者一向认为继承的作用是便于管理而不是扩展功能—扩展功能最好用复合。 这里暂时称呼这些基类为FrameActlonForm,和FrameAction。 这些基类当中可以指定一些基本的方法,当然也可以不指定. 只要实际程序中使用的ActionForm和Action继承自上面的基类,那么它们就会被Framework调用管理。 FrameAction当中的executeAction方法供Controlle: 调用,同时它管理和调用其他的业务方法。 4.3关于配置文件的一些讨论 我们似乎知道的只是ActionForm以及Action的名字,知道它们继承自特定的基类。 那么问题就演化成为: 如何根据一个名字来创建对应的实体。 这样看来,似乎只要再次使用Class.forName函数,问题就解决了。 为了给程序足够的信息创建对象,Framework使用配置文件。 当然,为了读取这些配置信息,需要一个专门的类进行处理。 这个类的作用就是专门负责读取配置信息。 4.4整合Framework模型 既然进行框架的整合,那么有必要提及BruceEckel在他的巨作《ThinkinginJava》当中提及的原则。 那就是使用innerclass对框架进行封装管理,也就是Factory设计模式。 所有的innerclass都应该继承自各自的外部基类,然后再在封装类当中进行定义体的实现。 下面是Controller的代码演示: packagecontrollers; importclasses; publicclassFrarneControllerextendsHttpServlet{ staticfinallongserialVersionUID=0; FrameActionaction=nul; FrameActionFormbean=null; FrameConfigurationconfig=null; Hashtablehtbl=null; PublicvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse) throwsIOException,ServletException{ doPost(request,response); } PublicvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse) ThrowsIOException,ServletException{ StringmappingName=null; Stringpath=null; if(request.getParameter("pathName)==null){ mappingName="/jsp/src.jsp"; getServletConfig().getServletContext().getRequestDispatcher(mappingName). forward(request,response); }else{ config=newFrameConfiguration(); try{ //GettheconfiguartioninformationfromtheXMLfile }catch(Exceptione){ e.printStackTrace(); System.exit(); } bean=getActionFormBean(request); action=getAction(); mappingName=action.executeAction(request,response,bean); getScrvletConfig().getServletContext().getRequestDispatcher(mappingName).forward(request,response); } } PrivateFrameActlonFormgetActionFormBean(HttpServletRequestrequest){ Objectobi=null; FrameActionFonnbean=null; Classc=Class.forName(htbl.get("actionFormType").tostriniq()); ……… returnbean ….. privateFrameActiongetAction(){ FrameActionaction=null Classc=null; c=Class.forName(htbl.get("actionType").toString()); ……. returnaction } } 从代码当中可以看出,Controlle: 根据视图层回传的索引信息读取了配置,并且生成了对应的Action-Form和Action实体。 对业务实体的业务过程也进行了启动。 基本上,所有后台所需要的流程都进行了整合。 需要注意的是,这里的编码采用的是“硬编码”,没有将 设计与实现进行隔离。 所以这样的代码最多只能存在于演示模型中。 实际上,至少也得采用一下Factory设计模式来对Framework进行封装。 另外,为了进行规整的操作,根据这个模型的特性,需要一个"hag设定表单提交的url以及后台所需要的索引信息到现在止,设计出的框架模型组件包括Controller,ActionForrn,Action,Configuration(负责读取XML配置信息),XML配置文件。 将前面四个类打包成jar文件,引人到所开发的项目当中即可。 5.JSP与servlet相结合的方法 JSP网站开发技术标准给出了两种使用JSP的方式。 这些方式都可以归纳为模式一和模式二。 这两种结构在JSP技术一开始应用时,就占有了绝对的统治地位。 在当今的开发中,我们比较偏向于使用模式二,但是模式一对小型的开发比较占有优势。 模式一: JSP+JavaBean 在模式一中,JSP页面独自响应请求并处理结果返回客户。 所有的数据通过Bean处理,JSP实现页面的表现。 模式一技术也实现了页面的表现和页面的商业逻辑相分离。 在最新引入JSP技术的时候。 模式一占有统治地位。 在用JSP处理显示和业务逻辑时,使用模式一比较简单。 JSP页面独自响应请求并经处理后吧结果返回客户端。 所有的数据通过JavaBean来处理,JS实现页面的显示,通过使用模式一,可以实现页面的显示和页面的内容(逻辑)分离 但是大量使用此模式可能带来一个副作用,那就是会导致在页面里面嵌入大量的Java控制代码。 当要处理的业务逻辑复杂时,这种情况变得非常糟糕。 大量的内嵌代码使得页面变得庞大,同时也非常复杂。 当页面的功能实现后交给美工或者页面内容设计人员进行包装时,问题就变得严重了。 所以大型的项目里,这种方法将会导致页面的维护困难。 模式二: JSP+Servlet+JavaBean 模式二,就是指JSP+Servlet+JavaBean技术。 在模式二中,结合了JSP和Servlet技术,模式二充分利用了JSP和Servlet两种技术原有的优点。 此模式遵循视图控制器(MVC)模式。 它的主要思想是使用一个或者多个Servlet作为控制器。 请求由前沿的Servlet(可能是多个Servlet构成的一个处理链)接收并处理后,会重新定向到JSP。 在Servlet作为控制器时,每个Servlet通常只实现很少一部分功能,多个Servlet控制器就可以结合起来完成复杂的任务。 这样的好处是Servlet的重要性,一个副作用就是可能会导致请求响应的时间加长。 在此模式里,JavaBean作为模型的角色,它充当JSP和Servlet通信的中间工具。 Servlet处理完后设置Bean的属性,JSP读取此Bean的属性,然后进行显示。 在实际的项目开发过程中,页面设计者可以方便地使用普通的HTML工具开发JSP页面,Servlet却更适合于后端开发者使用。 开发Servlets需要的工具是Java集成开发环境。 此模式更加明显地把显示和逻辑分离,使得代码比模式一的容易管理,适合大型项目的开发 6.两种模式的比较 从开发的观点看,模式二具有更清晰的页面表现、清楚的开发者角色划分,可以充分地利用开发小组中的界面设计人员。 这些优势在大型项目开发中表现得尤为突出。 使用这一模式,可以充分发挥每个开发者各自的特长;界面设计开发人员可以充分发挥自己的设计才能,来体现页面的表现形式;程序编写人员则可以充分发挥自己的商务处理逻辑思维,来实现项目中的业务处理。 在目前的大型项目中,模式二更多地被采用。 7.JSP和Servlet的选择 我们知道,所有的JSP都必须编译成Servlet,并且在Servlet容器中执行。 从技术角度来看,JSP和Servlet是一样的。 但JSP有很多关键因素胜过Servlet 1.JSP以显示为中心,它为Web显示开发人员提供了更加方便的开发模式 2.JSP可以把显示和内容分离,实现的方法就是借助JavaBean、Taglib,这样项目的显示和业务逻辑开发可以同时进行。 3.JSP可以帮助组织Web应用的物理状况。 4.JSP由容器自动编译。 Servlet曾经得到广泛的应用,但随着J2EE平台的不断完善,它的应用规模也在不断降低。 因为随着J2EE的出现,Servlet的业务处理能力不如EJB,它的页面表示能力不如JSP方便。 但是这不等于说Servlet已经没有什么用处了,在如今的J2EE应用开发中,它仍然大量用来处理小型的任务,或者用来作为MVC视图模式中的控制器。 具体地讲,它主要负责那些容器管理的任务组。 1.协调输出,但几乎不直接参与生成动态Web页面内容。 2.收集和验证用户输入,但几乎不进行实际处理。 3.处理及其简单的业务逻辑 4.处理JSP不好处理的后台服务或者其他有特殊要求的问题。 在构建Web站点时,如果Web功能不是非常稳定,那么使用Servlet就不是头等的选择。 因为Servlet比JSP更难于维护,它需要编译类,而修改JSP时只要修改它的源文件,容器会自动对发生改变的JSP进行重新编译,故使用Servlet会使维护变的困难,即使是一个很小的改动,Web页面设计人员可能也不能胜任。 相反,当JSP开发完成后,如果只是对页面的内容做很少的改动,那么可能不需要JSP程序员参与也能完成。 在特定的软件系统环境中,选择使用Servlet还是JSP通常不是绝对的。 最常见的情况是把两者结合起来使用,比如可以把Servlet作为视图控制器,让它处理请求;当Servlet处理完请求后,就把处理的结果转发给JSP,JSP处理显示的问题。 8.Framework模型的应用与验证 由于篇幅的限制,实际验证的过程就不再叙述了。 验证的结果是: 前台采用指定的标签,后台程序当中创建继承自ActionForm和Action的类以及进行了正确的配置之后,程序正常运行。 在建立这Framework模型的过程中,已经从理论上证明了这个模型的正确性了,虽然这个模型没有实际应用价值。 9.如何选择Web开发框架 开发框架的选择,始终是个仁者见仁、智者见智的事情。 尤其是Web层的开发框架,数量非常多,而且各有特色,如: Struts、WebWork、SpringMVC、Tapestry、JSF、WebPage3.0……。 下面先来看看为什么要使用Web开发框架 一: 使用框架的必然性 框架,即framework。 其实就是某种应用的半成品,把不同应用程序中有共性的一些东西抽取出来,做成一个半成品程序,这样的半成品就是所谓的程序框架。 软件系统发展到今天已经很复杂了,特别是服务器端软件,涉及到的知识,内容,问题太多。 在某些方面使用别人成熟的框架,就相当于让别人帮你完成一些基础工作,你只需要集中精力完成系统的业务逻辑设计。 这样每次开发就不用白手起家,而是可以在这个基础上开始搭建。 使用框架的最大好处: 减少重复开发工作量、缩短开发时间、降低开发成本。 同时还有其它的好处,如: 使程序设计更合理、程序运行更稳定等。 基于这些原因,基本上现在在开发中,都会选用某些合适的开发框架,来帮助快速高效的开发应用系统。 了解了使用框架的必然性,下面来看看如何选择,当然我们的话题集中在Web层的开发框架。 在谈这个问题之前,先来看看我们在Web开发中究竟需要做些什么工作: 二: Web层开发的工作 在J2EE开发中,分层是基本的思想,3层架构或者多层架构早已深入人心,在这里我们就把目光集中到Web层,看看到底Web层开发做了那些工作: 1.数据展示 Web层需要从逻辑层获取需要展示的数据,然后以合理的方式在页面进行展示。 2.人机交互 用户需要从界面上输入数据,在界面上进行按钮点击,进而触发事件,标准的事件驱动模型,然后跟后台进行数据交换,出现新的界面。 3.收集数据,调用逻辑层接口 Web层收到用户的事件请求,需要调用相应的逻辑层接口来进行处理,Web层是不会有任何逻辑处理的。 调用逻辑层接口,需要传递参数,这时需要收集用户在界面上输入的数据,然后进行组织,组织成为逻辑层接口需要的数据封装形式(通常都是ValueObject)。 4.根据逻辑层的数据来重新展示页面 逻辑层处理完了,需要返回数据或信息到界面上。 这个时候Web层需要根据返回的值选择合适的页面,然后展示这些数据或者信息。 从上面可以看出,Web层开发的主要工作集中在展示上,也就是图形用户界面。 这一部分是用户直观感受应用程序的窗口,也是用户要求最多的地方,其表现形式也是最丰富的。 三: Web层开发的步骤 下面再来总结一下Web层开发的大致步骤(也就是需要开发人员做的工作): 注意: 这里讨论的Web层开发,是不使用任何开发框架时候的开发。 1.写页面Html,到底有哪些数据需要在界面上表现 2.每个数据的具体表现形式,如: 有的需要表现成为下拉列表,有的需要表现成为单选按钮等。 3.界面表现形式的逻辑布局,所谓逻辑布局是指某些数据的表现形式应该放在前面,某些应该放在后面;某些放在上面,某些放在下面。 如: 某个请假申请的业务,有请假开始时间和结束时间,很明显开始时间的表现就应该排在结束时间的前面。 而美工是负责最后页面的美观,一般美工不能动界面的逻辑布局。 4.完成前面3步,页面的表现形式的大致模样就有了,下面需要来做功能性的开发。 第一个就是这些表现形式的值的来源,如: 下拉列表显示的值从什么地方
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于JSP Servlet的Web应用框架的设计与实现 基于 JSP Servlet Web 应用 框架 设计 实现