J2EE项目实训 Spring框架技术——第6章 AOP 和 Spring AOP技术(第2部分)_第1页
J2EE项目实训 Spring框架技术——第6章 AOP 和 Spring AOP技术(第2部分)_第2页
J2EE项目实训 Spring框架技术——第6章 AOP 和 Spring AOP技术(第2部分)_第3页
J2EE项目实训 Spring框架技术——第6章 AOP 和 Spring AOP技术(第2部分)_第4页
J2EE项目实训 Spring框架技术——第6章 AOP 和 Spring AOP技术(第2部分)_第5页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、杨教授工作室 精心创作的优秀程序员 职业提升必读系列资料第6章 aop 和 spring aop技术(第2/3部分)1.1.1 aop思想在j2ee web 过滤器组件中的应用1、j2ee web 过滤器组件技术(1)j2ee web技术中的过滤器(filter)组件过滤器是一种j2ee web 组件,它拦截用户通过浏览器发出的请求和响应,以便查看、提取或以某种方式操作正在客户机和服务器之间交换的http数据。过滤器提供一种面向对象的模块化机制,用以将公共任务封装到可插入的组件中,这些组件通过一个配置文件来声明,并动态地处理。(2)过滤器组件技术的主要作用l 访问日志记录对于到达系统的所有请求

2、,过滤器收集诸如浏览器类型、请求的url和请求的时间请求的用户相关的信息,并可以对它们进行日志记录。 l 对非法的请求进行阻止等安全验证过滤器处理身份验证令牌的管理,并适当地限制安全资源的访问,提示用户进行身份验证和/或将他们指引到第三方进行身份验证。将安全逻辑放在过滤器中,而不是放在servlet 组件中,这样达到“安全逻辑”和“业务逻辑”两者相互分离。 l 会话处理使用过滤器来管理会话session可以让系统的控制层组件servlet的开发者集中精力考虑页面内容的显示和对业务层组件的委托调用,而不需要再考虑会话管理的细节。(3)应用过滤器技术同样也能够实现分离“技术问题实现”和“业务问题实

3、现”过滤器技术同样也能够实现aop所倡导的分离“技术问题实现”和“业务问题实现”,因此在web 开发中可以将日志记录、安全验证和会话处理等有关系统中的“技术问题实现”放在过滤器组件中,这样在业务层中将不需要再重复地编程这些功能实现。但过滤器技术只适用于web表示层中的url地址的拦截,而无法实现对业务层或者持久层等系统底层的组件中的方法进行拦截,因此再应用方面有一定的限制;而aop不仅可以实现对url地址的拦截(通过监控控制层如servlet组件或者struts系统中的 action类中的方法),也可以实现对业务层或者持久层等系统底层的组件中的方法进行拦截。2、利用过滤器组件技术实现web方式

4、的用户访问验证示例某个web bbs论坛系统中的访问安全的要求是所有用户都必须登陆,只有登陆成功后才可以看到该用户的角色和权限相对应的视图和资源文件。因此一个重要的问题就是,开发人员如何防止一个视图或者部分的视图被一个未被授权的用户直接访问。本web bbs论坛系统在此方面的访问安全原则为:对于系统中受保护的资源的访问必须通过另一个表现层的应用资源进行(本系统为一个servlet 类型的pageforwardaction控制器组件);对于这些受限制的资源不允许通过浏览器直接调用。(1)在项目中添加一个过滤器组件以实现对web系统进行保护该过滤器组件类名称为checkuserloginfilte

5、r,包名称为com.px1987.webbbs.filter,并且实现javax.servlet.filter接口。请见下面的图6.1所示的设置项目的要求。图6.1 添加过滤器组件的对话框(2)编程该过滤器组件类checkuserloginfilter在过滤器组件中对所有进入的uri进行解析,并取得当时session中的userinfo信息,然后通过rbac(roled-based access control)的机制,将此链接需要的权限与用户拥有的权限进行比较,然后进行相应的处理。具体实现的细节过程请参考下面的【例6-4】中的代码示例,并请注意其中的黑体部分的代码。【例6-4】 过滤器组件类

6、checkuserloginfilter的代码示例package com.px1987.webbbs.filter;import java.io.ioexception;import javax.servlet.*;import javax.servlet.http.*;import com.px1987.webbbs.model.*;public class checkuserloginfilter implements filter public checkuserloginfilter()public void destroy()public void dofilter(servletr

7、equest request,servletresponse response, filterchain chain) throws ioexception, servletexceptionstring targetpage=null;requestdispatcher onerequestdispatcher=null;boolean targetqueryparam;httpservletrequest httprequest = (httpservletrequest)request;httpsession session = httprequest.getsession();obje

8、ct userinfoobject=session.getattribute(oneuserinfovo);string actionstring=request.getparameter(action);if(actionstring=null) /识别用户是否是直接在浏览器中输入url地址进入targetpage=/errordeal/shownologinerror.jsp;onerequestdispatcher=request.getrequestdispatcher(targetpage);onerequestdispatcher.forward(request, response

9、);return; /跳转到错误显示页中提示用户的非法访问状态targetqueryparam=actionstring.equals(showuserlogout)|actionstring.equals(showupdateuserinfo)|actionstring.equals(doshowonlineuserinfo);targetqueryparam=targetqueryparam|actionstring.equals(dosendbbsinfo)|actionstring.equals(doreplybbsinfo);targetqueryparam=targetqueryp

10、aram|actionstring.equals(doupdateonebbsinfo);if(targetqueryparam) /识别用户是否对敏感资源进行访问 if(userinfoobject=null) /识别当前用户是否已经登陆过系统/如果没有登陆过系统,则同样也跳转到错误显示页中提示用户的非法访问状态targetpage=/errordeal/shownologinerror.jsp;onerequestdispatcher=request.getrequestdispatcher(targetpage);onerequestdispatcher.forward(request,

11、 response);return;elsechain.dofilter(request,response); /在结束时,应该跳转到下一个资源中return;elsechain.dofilter(request,response); /在结束时,应该跳转到下一个资源中return;public void init(filterconfig arg0) throws servletexception采用过滤器组件类在代码编程实现方面还是比较简单的,并且对系统的侵入性也不强。当然这里所需要拦截的url地址也就是rbac(roled-based access control)中的资源。但其缺点或者

12、是限制则是所有对数据的操作必须通过url来实现,这在采用同一个url(浏览器看来)进行处理多项任务时将面临如何区分“开放资源”和“禁用资源”。在本例中是通过进一步识别同一个url中的不同的查询参数字符串的内容来区分的,因此在此点上,将会导致代码比较复杂。请见上面的【例6-4】中的黑体部分的代码。(3)在web.xml中部署该过滤器组件类checkuserloginfilter在部署该过滤器组件类checkuserloginfilter时,利用设置系统中各个需要监控的url地址。每当用户对这些url地址所对应的资源进行请求访问时,容器将自动地加载本过滤器组件类checkuserloginfilt

13、er。【例6-5】 web.xml文件中部署checkuserloginfilter的标签示例checkuserloginfilter com.px1987.webbbs.filter.checkuserloginfilter checkuserloginfilter /bbsinfomanage/sendbbsinfo.jsp checkuserloginfilter /bbsinfomanage/updateonebbsinfo.jsp checkuserloginfilter /bbsinfomanage/replyonebbsinfo.jsp checkuserloginfilter

14、/usermanage/updateuserinfo.jsp checkuserloginfilter /usermanage/updateadmininfo.jsp checkuserloginfilter /pageforwordaction checkuserloginfilter /bbsmanageraction 3、测试该过滤器组件类checkuserloginfilter的有效性(1)直接对受保护的资源进行请求在浏览器中输入:8080/webbbs/usermanage/updateuserinfo.jsp后,过滤器组件类checkuserlogin

15、filter将提示出下面的图6.2所示的错误提示。图6.2 直接对受保护的资源进行请求时将被禁止(2)点击页面全局导航条上的“修改”用户信息的超链接,由于本次请求时,访问者还没有进行系统登陆,过滤器组件类checkuserloginfilter同样也将提示出前面的图6.2中所示的未登陆的错误提示。(3)访问者然后以前台某个用户的身份进行登录请求,并在登陆表单中输入合法的信息。请见下面的图6.3中所示的状态。图6.3访问者然后以前台某个用户的身份进行登录请求(4)登陆成功后,然后再点击全局导航条上的“修改”用户信息的超链接。过滤器组件类checkuserloginfilter识别用户的目前身份为

16、已经成功登陆,将允许该登录者进行本人的信息修改操作。请见下面的图6.4中所示的状态。图6.4 访问者登陆成功后将被允许进行访问操作1.1.2 aop与代理模式在应用方面的不同在传统的应用系统的开发中,为了能够达到分离“技术问题实现”和“业务问题实现”的目标,一般采用gof设计模式中的代理模式来编程实现。下面通过一个在某系统中的业务层组件实现日志记录的功能为例,说明代理模式和aop技术在实现上的不同。 1、常规的日志记录的实现方法(1)某系统的用户信息管理的业务层组件的接口usermanagerinterface的定义【例6-6】 usermanagerinterface接口的定义示例packa

17、ge com.px1987.webbbs.model;public interface usermanageinterface public boolean douserlogin(string username, string userpassword); public boolean douserlogout(string username); (2)为接口usermanagerinterface提供一个实现类usermanageimplement【例6-7】 实现类usermanageimplement的代码示例package com.px1987.webbbs.model;import

18、 java.util.logging.*;public class usermanageimplement implements usermanageinterface private logger logger = logger.getlogger(this.getclass().getname(); public usermanageimplement() public boolean douserlogin(string username, string userpassword)logger.log(level.info, douserlogin方法开始执行.); system.out

19、.println(username= + username +正在登录系统!); /代表业务实现logger.log(level.info, douserlogin方法已经结束.);return true;public boolean douserlogout(string username)logger.log(level.info, douserlogout方法开始执行.); system.out.println(username= + username + 正在注销!); /代表业务实现logger.log(level.info, douserlogout方法已经结束.);return

20、true;在该实现类中的两个业务方法中实现日志记录的功能,本示例为了简化之目的,没有将具体的业务功能的实现代码附录出,而以打印输出信息作为代表。2、常规的日志记录的实现方法的缺点(1)没有遵守面向对象设计中的“单一职责”的原则在常规的实现方法中,使得logger日志记录的功能的实现直接介入到了业务功能实现类usermanageimplement中,而日志这个功能应该不属于业务功能实现类usermanageimplement 所必须应该考虑实现的(或者说本不属于它应该承担的职责),这将使得usermanageimplement类的职责成为双重职责,这是与面向对象设计中的“单一职责”的原则不相吻合

21、。(2)实现日志记录的功能代码重复地遍布在各个方法中在本示例中目前还只是两个业务方法,如果在整个应用系统的各个模块中都需要应用日志这个功能,那将会使日志功能代码遍布在应用系统的各个模块中。3、解决此问题的基本思路将主应用功能模块(也就是前面所描述的核心关注点,在本示例中为业务功能类usermanageimplement)和日志功能(也就是前面所描述的横切关注点)相互分离。4、可以采用代理模式和spring aop技术来解决此问题(1)方法之一是采用静态代理技术所谓的静态代理类是由开发者编程创建或由特定工具自动生成源代码,然后再对其编译。在程序运行前,该代理类的.class文件就已经存在了。采用

22、静态代理技术时,开发者可以以下面的两种方式来具体实现。1) 针对每个具体类分别编写代理类;2) 针对一个接口编写一个代理类;(2)方法二是采用动态代理技术所谓的动态代理类是指在程序运行时,运用反射机制动态创建出。但该动态代理类需要实现invocationhandler接口,然后借用jdk反射包中的proxy类为各种接口动态生成相应的代理类。(3)方法三是采用spring 框架中的aop技术,但使用around类型的advice来具体实现。5、采用静态代理技术的具体实现示例(1)修改前面的【例6-7】中的usermanagerinterface接口的实现类为下面的【例6-8】中所示的代码【例6-

23、8】 对usermanageimplement类进行修改后的结果示例package com.px1987.webbbs.model;public class usermanageimplement implements usermanageinterface public boolean douserlogin(string username, string userpassword) system.out.println(username= + username +正在登录系统!);return true; public boolean douserlogout(string usernam

24、e) system.out.println(username= + username +正在注销!);return true; 因此,应用代理模式后,原来的业务功能类将不再包含有其它横切关注点的功能实现代码,因此分离了两者各自的功能实现。(2)为该实现类usermanageimplement提供一个代理类在代理模式中主要包括代理对象本身和被代理对象,它们要实现相同的接口。根据代理模式的实现规则,开发者在该代理类中实现日志功能(横切关注点的功能),同时也对原来的方法(被代理类中的方法)进行调用。应用代理模式,开发者可以把业务功能处理放在被代理对象类的方法中(也就是业务类本身),而把一些与业务无关

25、的其它事情(横切关注点的功能)放在代理类的方法中。请见下面的【例6-9】中所示的代码,并请注意其中的黑体部分的代码是对被代理类中的业务方法进行调用。【例6-9】 usermanageimplement类的代理类usermanageproxy的代码示例package com.px1987.webbbs.model;import java.util.logging.*; public class usermanageproxy implements usermanageinterface private logger logger = logger.getlogger(this.getclass(

26、).getname(); private usermanageinterface oneusermanage; public usermanageproxy (usermanageinterface oneusermanage) this.oneusermanage = oneusermanage; public boolean douserlogin(string username, string userpassword) logger.log(level.info, douserlogin方法开始执行.); oneusermanage.douserlogin(username, user

27、password);logger.log(level.info, douserlogin方法已经结束.);return true; public boolean douserlogout(string username)logger.log(level.info, douserlogout方法开始执行.); oneusermanage.douserlogout(username);logger.log(level.info, douserlogout方法已经结束.);return true;代理模式在应用系统的开发中大量地被应用,其中的代理类主要完成为被代理类进行预处理消息、过滤消息、把消息转

28、发给被代理类,以及事后处理消息等。代理类与被代理类之间通常会存在关联关系,一个代理类的对象与一个被代理类的对象关联,代理类本身一般不真正实现应用系统本身的功能服务,而是通过调用被代理类对象中的相关方法来实现,来向客户提供特定的服务。当然,有关代理模式的更详细的编程实现的规则请读者参考本书的第十一章“与spring框架相关的设计模式”中的相关的内容。(3)在项目中提供一个j2se的应用程序的测试类【例6-10】 testusermanageimplement测试类的代码示例package com.px1987.webbbs.test;import com.px1987.webbbs.model.

29、*;public class testusermanageimplementpublic testusermanageimplement ()usermanageinterface oneusermanage = new usermanageproxy(new usermanageimplement(); oneusermanage.douserlogin(张三,12345678);public static void main(string args)new testusermanageimplement();在客户端程序中应该是获得代理类的对象实例,通过代理类的对象实例实现对目标类中的方法

30、进行调用。(4)执行该测试客户端testusermanageimplement类其执行的结果请见如下的图6.5所示的结果状态。图6.5 testusermanageimplement类的执行结果(5)对上面的静态代理技术的应用实现的说明l 同样也能够达到核心关注点和横切关注点相互分离的目的代理对象usermanageproxy将代理真正的usermanageimplement类来执行douserlogin()方法,并在该douserlogin()方法的前和后加上日志记录的功能实现。这使得usermanageimplement类的开发者在具体编程实现时不必关心日志的功能实现的细节,而只需要专心于

31、它的的主业务的功能实现,从而也达到了核心关注点和横切关注点相互分离的目的。l 静态代理在程序规模稍大时就必定无法胜任但由于代理对象需要实现业务类的接口,因此一般只服务于一种接口类型的对象。而且如果要代理的目标类比较多时(比如还需要为bbsmanageimplement 类中的方法进行代理),开发者势必要为每个业务功能类提供对应的代理类的定义和编程实现,缺少一定的灵活性。可以应用jdk中的动态代理技术来简化代理类的编程实现,从而为不同的类进行代理。因为java语言在jdk 1.3版之后增加了有关动态代理功能的api类,这样开发者就不必为特定对象与其中的方法编写特定的代理程序。使用动态代理,可以使

32、得一个动态代理类能够服务于各个不同的被代理类的对象。6、与动态代理技术相关的api(1)invocationhandler接口java.lang.reflect 包中的proxy类和invocationhandler 接口提供了生成动态代理类的能力。其中在invocationhandler接口中仅定义了一个方法object invoke(object proxy, method method, object args)。在实际使用时,第一个参数proxy一般是指代理类对象本身,而其中的method是被代理类中的目标方法,args为该目标方法的参数数组。(2)proxy动态代理类1) prote

33、cted proxy(invocationhandler h):proxy类的构造方法2) static class getproxyclass (classloader loader, class interfaces):获得一个代理类,其中loader是类装载器,interfaces是真实类所拥有的全部接口的数组。3) static object newproxyinstance(classloader loader, class interfaces, invocationhandler h):返回代理类的一个实例,返回后的代理类可以当作被代理类使用。7、采用动态代理技术的具体实现示例(

34、1)应用动态代理技术的主要优点动态代理类的字节码(*.class文件)在程序运行时由java反射机制动态生成,无需程序员手工编写它的源程序代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为java 反射机制可以生成任意类型的动态代理类。(2)新增加一个webbbsloghandler类,请见下面的图6.6中所示的状态图6.6 webbbsloghandler类的创建对话框(3)编程实现webbbsloghandler动态代理类【例6-11】webbbsloghandler动态代理类的代码示例package com.px1987.webbbs.model;import jav

35、a.lang.reflect.*;import java.util.logging.*;public class webbbsloghandler implements invocationhandler private logger logger = logger.getlogger(this.getclass().getname(); private object delegate; public object bind(object delegate) this.delegate = delegate; /获得被代理的类return proxy.newproxyinstance(dele

36、gate.getclass().getclassloader(), delegate.getclass().getinterfaces(), this); public object invoke(object proxy, method method, object args) throws throwable object result = null; try logger.log(level.info, 方法开始执行. + method); result = method.invoke(delegate, args); /利用反射技术动态地访问被代理类中的方法logger.log(level.info, 方法已经结束. + method); catch (exception e) logge

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论