软件体系架构模式在J2EE中的应用.docx
- 文档编号:28019237
- 上传时间:2023-07-07
- 格式:DOCX
- 页数:16
- 大小:109.10KB
软件体系架构模式在J2EE中的应用.docx
《软件体系架构模式在J2EE中的应用.docx》由会员分享,可在线阅读,更多相关《软件体系架构模式在J2EE中的应用.docx(16页珍藏版)》请在冰豆网上搜索。
软件体系架构模式在J2EE中的应用
软件体系架构模式在J2EE中的应用
本文介绍了软件体系架构产生的背景和架构模式的基本理论.重点介绍管道与过滤器体系架构模式的结构,实现,优缺点等,然后以J2EE的ServletFilter为例进行剖析它是怎样应用该架构模式的,最后简单阐述了在其它J2ee应用中(Jboss和Axis)的实践.
1软件体系架构
1.1软件体系架构产生背景
在经历60年代的软件危机之后,使人们开始重视软件工程的研究。
来自不同应用领域的软件专家总结了大量的有价值的知识.当初,人们把软件设计的重点放在数据结构和算法的选择上,如Knuth提出了数据结构+算法=程序.但是随着软件系统规模越来越大、越来越复杂,使软件系统的架构越来越重要。
软件危机的程度日益加剧,现有的软件工程方法对此显得力不从心。
对于大规模的复杂软件系统来说,软件体系架构比起对程序的算法和数据结构的选择已经变得明显重要得多。
在此种背景下,人们认识到软件体系架构的重要性,并认为对软件体系架构系统、深入的研究将会成为提高软件生产效率和解决软件危机的最有希望的途径.这时对软件体系架构的研究如雨后春笋般,出现了百家争鸣的现象,如Rational公司提出了"以架构为中心"的统一软件开发过程(RUP).
1.2软件体系架构模式
软件设计的一个核心问题是能否使用重复的体系架构,即能否达到体系架构级的软件重用。
也就是说,能否在不同的软件系统中,使用同一体系架构。
基于这个目的,许多学者们开始研究和实践软件体系架构的模式问题。
在
层(Layers)、管道和过滤器(PipesandFilters)、黑板(Blackboard)、代理者(Broker)、模型-视图-控制器(Model-View-Controller)、表示-抽象-控制(Presentation-Abstraction-Control)、微核(Microkernel)、映像(Reflection)。
2J2EE体系架构
目前,J2EE技术已经成为企业级应用的首选平台,基于J2EE技术构建的软件系统越来越多.J2EE代表着先进的软件体系架构思想,许多软件体系架构模式在J2ee中均被广泛应用,从本文起陆续介绍各架构模式在J2EE中的应用.
3管道与过滤器
3.1概述
管道和过滤器(PipesandFilters)体系架构模式是为处理数据流的系统提供的一种模式。
它是由过滤器和管道组成的.每个处理步骤都被封装在一个过滤器组件中,数据通过相邻过滤器之间的管道进行传输。
每个过滤器可以单独修改,功能单一,并且它们之间的顺序可以进行配置。
下图是管道/过滤器模式的示意图。
一个典型的管道/过滤器体系结构的例子是以Unixshell编写的程序。
Unix既提供一种符号,以连接各组成部分(Unix的进程),又提供某种进程运行时机制以实现管道。
另一个著名的例子是传统的编译器。
传统的编译器一直被认为是一种管道系统,在该系统中,一个阶段(包括词法分析、语法分析、语义分析和代码生成)的输出是另一个阶段的输入。
3.2问题
假如你正在开发一个必须处理或转换输入数据流的系统。
把这样的系统作为单个组件实现是不容易的,这有几个原因:
系统必须由几个开发人员同时进行协作开发,整个系统任务自然就被分解为几个处理阶段,而且需求很容易变动。
因此你就要通过替换或重新排序处理步骤来为将来的灵活性作规划。
通过加入这样的灵活性,采用现有处理组件构建是可以办到的。
系统的设计尤其是处理步骤的内部连接,必须考虑以下因素:
∙未来系统的升级通过替换某些处理步骤,或重组步骤.
∙不同的语境中小的处理步骤要比大的组件更易于重用。
∙不相连的处理步骤不可共享信息。
∙存在不同的输入数据源,
∙可以用多种方式输出或存放最终结果。
3.3解决方案与结构
管道和过滤器体系架构模式把系统任务分成为几个独立的处理步骤。
这些步骤采用通过系统的数据流连接.一个步骤的输出是下一个步骤的输入。
每个处理步骤由一个过滤器组件实现,它处理或者转化数据,并且系统的输入可以是多种数据源.
这种体系架构模式具有许多特性,如下:
∙过滤器是独立运行的部件.也就是除了输入和输出外,每个过滤器不受任何其他过滤器运行的影响.在设计上,过滤器之间不共享任何状态信息.
∙独立性还表现在它对其处理的上游和下游连接的过滤器是"无知"的.它的设计和使用不对与其连接的任何过滤器施加限制,唯一关心的是其输入数据的,然后进行加工处理,最后产生数据输出.
3.4非软件描述
基于各种流体工作的系统,普遍都采用由输送管道连接起来的处理结构.例如我们冬天见到的供暖系统中,处理器包括加热器,过滤器,调节阀,流量表等,每个处理器都有流体的入口和出口,它们通过各种管道连接在一起形成了整个系统.这样的结构在城市的自来水系统也可以看到.见下图:
3.5优点与缺点
3.5.1优点
∙通过使用过滤器交换增加了灵活性
∙通过重组增加了灵活性
∙过滤器组件的重用
∙流水线的快速原型
∙并行处理提高效率
3.5.2缺点
∙共享状态信息或者昂贵或者不灵活
∙数据转换额外开销。
∙错误处理
4Servlet2.3Filter
4.1ServletFilter概述
凡是开发过J2EE的webapplication的人员都知道,经常需要处理以下几种情况:
∙访问特定资源(Web页、JSP页、servlet)时的身份认证
∙应用程序级的访问资源的审核和记录
∙应用程序范围内对资源的加密访问,它建立在定制的加密方案基础上
∙对被访问资源的及时转换,包括从servlet和JSP的动态输出
在servlet2.3之前这些功能处理是很难实现的,但是JavaServlet2.3规范新增了不少激动人心的功能,其中之一便是过滤器(Filter),其实这就是我们所说的管道和过滤器体系架构在J2EE中的应用实践.通过使用该模式使得WebApplication开发者能够在请求到达Web资源之前截取请求,在处理请求之后修改应答。
其结构图如下:
一个执行过滤器的Java类必须实现javax.servlet.Filter接口。
这一接口含有三个方法:
∙init(FilterConfig):
这是容器所调用的初始化方法。
它保证了在第一次doFilter()调用前由容器调用。
它能获取在web.xml文件中指定的filter初始化参数。
∙doFilter(ServletRequest,ServletResponse,FilterChain):
这是一个完成过滤行为的方法。
它同样是上一个过滤器调用的方法。
引入的FilterChain对象提供了后续过滤器所要调用的信息。
∙destroy():
容器在销毁过滤器实例前,doFilter()中的所有活动都被该实例终止后,调用该方法。
4.2Filter链介绍
所有过滤器都服从调用的过滤器链,并通过定义明确的接口得到执行。
WebApplication可以指定许多过滤器来完成相关的工作.那么它们就组成一个过滤器链来完成相应的工作.其结构如下图:
4.3例子
4.3.1简单filter
在PetStore1.3.1中的就存在两个Filter过滤器.其中一个过滤器,完成字符集的编码的转化,如大家经常遇到的汉字编码问题,你只需配置为GBK即可.它从Web.xml之中读取这些参数的配置信息,然后进行编码的转化.另一个是安全校验Fliter,它负责进行安全检查哪些页面可以进行,哪些不可.它们组成一个Filter链,结构图和实现代码如下(完整代码参见附件):
publicclassEncodingFilterimplementsFilter{
privateFilterConfigconfig=null;
//defaulttoASCII
privateStringtargetEncoding="ASCII";
publicvoidinit(FilterConfigconfig)throwsServletException{
this.targetEncoding=config.getInitParameter("encoding");
}
//在过滤器中实现字符集编码转化
publicvoiddoFilter(ServletRequestsrequest,ServletResponsesresponse,FilterChainchain)
throwsIOException,ServletException{
HttpServletRequestrequest=(HttpServletRequest)srequest;
request.setCharacterEncoding(targetEncoding);
//moveontothenext
chain.doFilter(srequest,sresponse);
}
publicvoiddestroy(){
……………..
}
}
publicclassSignOnFilterimplementsFilter{
publicvoidinit(FilterConfigconfig)throwsServletException{
this.config=config;
URLprotectedResourcesURL=null;
try{
protectedResourcesURL=config.getServletContext().getResource("/WEB-INF/signon-config.xml");
...............
}catch(.MalformedURLExceptionex){
System.out.println("SignonFilter:
malformedURLexception:
"+ex);
}
}
publicvoiddestroy(){
config=null;
}
publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)
throwsIOException,ServletException{
........
}
}
容器通过Web应用程序中的配置描述符web.xml文件解析过滤器配置信息。
有两个新的标记与过滤器相关:
您能随意地包含一个
--EncodingFilterDeclarationStart-->
--EncodingFilterDeclarationEnd-->
--SignonFilterDeclarationStart-->
--SignonFilterDeclarationEnd-->
--EncodingFilterMappingStart-->
--EncodingFilterMappingEnd-->
--SignonFilterMappingStart-->
--SignonFilterMappingEnd-->
4.3.2复杂的filter
上面是petstore的例子,演示了通过Fliter修改字符编码和安全认证的功能.下面提供一个示例演示通过修改返回数据(通过过滤器把response的字符串变成大写).
publicclassUCaseResponseextendsHttpServletResponseWrapper{
publicUCaseResponse(HttpServletResponseresponse){
super(response);
}
publicPrintWritergetWriter()throwsIOException{
returnnewUCaseWriter(super.getWriter());
}
}
publicclassUCaseWriterextendsPrintWriter{
publicUCaseWriter(Writerout){
super(out);
}
publicvoidwrite(intc){
super.write(Character.toUpperCase((char)c));
}
publicvoidwrite(charbuf[],intoff,intlen){
for(inti=0;i write(buf[off+i]); } } publicvoidwrite(Strings,intoff,intlen){ for(inti=0;i write(s.charAt(off+i)); } } } publicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainfilterChain){ try{ filterChain.doFilter(request,newUCaseResponse((HttpServletResponse)(response))); }catch(Exceptionsx){ filterConfig.getServletContext().log(sx.getMessage()); } 该示例使用HttpServletResponseWrapper技术,它是对HttpServletResponse的包装,其实就是装饰(decorate)设计模式的应用.这个例子能够工作的关键是UCaseResponse和UCaseWriter类,它实现了对每个要输出的字符都转成了大写后再写入实际的输出流的功能。 4.4体系架构的实现 实现一个管道和过滤器一般要注意以下几个方面: ∙把系统任务分成一系列处理阶段。 根据管道和过滤器的设计方案,必须把系统处理的任务分割成相应独立的任务,如日志,数据转化,安全认证等.这样每个阶段仅依赖其前一阶段的输出。 通过数据流将所有阶段相连起来。 并且你可以进行替换每个步骤,或者可以调整它们之间的顺序,以产生新的结果. 如petstore中的编码转化Filter和安全Filter,分成两个独立的处理阶段. ∙定义沿每个管道传输的数据格式。 我们知道每个过滤器,定义一个统一格式以获得最大的灵活性,因为它使过滤器的重组变得容易。 如: 每个过滤器的方法是doFilter(ServletRequestrequest,ServletResponseresponse,FilterChainfilterChain)它们的参数是必须相同的. ∙决定如何实现每个管道连接 Filter过滤器的连接是推得方式来实现的.前一个过滤器主动的调用filterChain.doFilter(request,response);来实现转向下一个过滤器. ∙设计和实现过滤器 设计每个Filter具有独立的功能,如编码转化,安全校验,等功能.并且每个Fliter都应该在实现javax.servlet.Filter接口. ∙建立处理流水线 过滤器的部署是在Web.xml中进行配置,描述过滤器的实现类以及它们的map关系,来确定它们的顺序. 5其他应用实例 5.1JBOSS 如果大家对EJB了解,应该知道客户调用EJB实际上并不是直接引用EJB实例(ejbinstance).它通过容器来截获客户端的请求,然后按照EJB描述符做些许多相应的工作如,安全校验,事务的处理,线程并发处理等.这样就可以使开发人员仅关心自己的业务逻辑,而不需对复杂的基础服务进行实现.使开发人员从繁琐的工作中解脱出来.集中精力处理自己的业务逻辑,它的结构图如下: 笔者有幸阅读了JBOSS的源码,分析了Jboss的EJB容器的实现.EJB的容器通过许多拦截器(Inteceptor)来实现,每个拦截器处理一定的功能,一个处理结束后转发给下一个拦截器,最后一个拦截器才把真正调用EJB的实例.其中它的EntityBean容器的拦截器的结构如下: 我们看其中的log拦截器 publicclassLogInterceptorextendsAbstractInterceptor{ publicObjectinvoke(Invocationinvocation) throwsException { booleantrace=log.isTraceEnabled(); //Logcalldetails if(callLogging) { ......进行log的处理 } //处理结束,把请求转发给下一个拦截器 returngetNext().invoke(invocation); } 这些拦截器配置在standardjboss.xml文件中,如下: 这就是Jboss容器架构最巧妙的地方,最初这个架构就是由天才少年RickardOberg提出的.其实这个架构就应用我们讨论的管道和过滤器模式,其实每个拦截器就是一个过滤器,使用该模式给Jboss带来了如下的好处: ∙使系统的架构更容易理解,因为每个过滤器完成单一的功能 ∙使系统更加模块化,有利于系统的模块重用和扩展,如果系统想增加某种功能只需增加一个实现Interceptor接口的拦截器,然后配置在standardjboss.xml文件中即可 ∙使系统的容易进行错误处理,如果在一个拦截器中发现错误(error)或者异常(exception),只需返回即可. 5.2AXIS 无独有偶,同样在Axis上也应用了管道和过滤器模式.Aixs是apache开源的webservice实现服务器.简单的说,axis就是处理Message,它首先截获客户端的请求,然后转发到真正的实现业务逻辑上处理客户端的请求,在这之前经过一系列的handler处理.它的结构很像EJB容器.其实就是管道和过滤器模式
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 软件 体系 架构 模式 J2EE 中的 应用
![提示](https://static.bdocx.com/images/bang_tan.gif)