用SPRING AOP记录登录后操作日志

AOP作用:把分布在程序各处的’交叉事务”与业务逻辑分离开来,形成可重用的模块,减少重复代码,并让类着重于其主要的功能上。

下面这个例子模拟了多店铺商城各店铺在后台登录后,记录各个功能操作信息的日志。

环境:

struts2+spring2.5   , tomcat6

1.RedirectAction 类主要代码,

public String direct() throws Exception{
funcid = request.getParameter(”funcid”);
request.getSession().setAttribute(”funcid”, funcid);
shopid = (String)request.getSession().getAttribute(”shopid”);
memo = logService.getFuncInfo(shopid, funcid);
request.getSession().setAttribute(”operatormemo”, memo);
// TODO something
System.out.println(”…….execute end…”);
return “direct”;
}

以direct()方法为切入点(用spring的AOP配置元素配置),在执行完 direct()方法后记录日志,但是除了放到session里一些信息的代码外,没有任何与记录日志有关的代码

2. Service类主代码

public void saveLog(LogBean log) throws Exception {
System.out.println(”log : user:” + log.getUserid() + “,shop:”+ log.getShopid()
+”,ip:”+log.getIp()+”,funcid:”+log.getFunid()+”,memo:”+log.getOperatorMemo()
+”,time:”+log.getLogdate());

}

模拟保存日志,在控制台打印日志信息

3.AspectAdvice通知类,它只是个普通类,并没有任何接口和注解,通过spring的AOP配置元素把它转化为切面

public class AspectAdvice {

……………

public void after() throws Exception{
HttpServletRequest request = ServletActionContext.getRequest();
String userid = (String)request.getSession().getAttribute(”userid”);
String shopid = (String)request.getSession().getAttribute(”shopid”);
String operatormemo = (String)request.getSession().getAttribute(”operatormemo”);
String funcid = (String)request.getSession().getAttribute(”funcid”);
String ip = request.getRemoteAddr();

Timestamp time = new Timestamp(System.currentTimeMillis());

LogBean log = new LogBean();
log.setUserid(userid);
log.setShopid(shopid);
log.setFunid(funcid);
log.setIp(ip);
log.setOperatorMemo(operatormemo);
log.setLogdate(time);

logService.saveLog(log);
}

在advice类里声明了用于执行后通知的 after 方法

4.struts.xml

<struts>
<include file=”struts-default.xml”/>
<package name=”default” extends=”struts-default” namespace=”/”>
<action name=”*x” class=”index”  method=”{1}”>
<result name=”logged”>index.jsp</result>
<result name=”direct” type=”redirect”>destx.action?funcid=${funcid}</result>
<result name=”done”>done.jsp</result>
</action>
</package>
</struts>

5.spring aplicationContext.xml

<beans
xmlns=”http://www.springframework.org/schema/beans”
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xmlns:aop=”http://www.springframework.org/schema/aop”
xsi:schemaLocation=”http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd“>
<bean id=”logService” class=”com.aspect.services.impl.LogServiceImpl”></bean>
<bean id=”index” class=”com.aspect.services.actions.RedirectAction”>
<property name=”logService” ref=”logService”></property>
</bean>
<!–  声明通知类,其实就是一个普通类的声明  –>
<bean id=”aspect” class=”com.aspect.services.aop.AspectAdvice”>
<property name=”logService” ref=”logService”></property>
</bean>

<aop:config proxy-target-class=”true”<!–强制使用cglib –>
<aop:pointcut id=”pointcutx” expression=”execution(* *.direct(..))“/>  <!– 定义切点,把通知应用到所有的 direct方法 –>
<aop:aspect ref=”aspect“>
<aop:after pointcut-ref=”pointcutx” method=”after“/>  <!– 定义后通知引用切点 –>
</aop:aspect>
</aop:config>

</beans>

如果要使用aop配置元素,要在SPRING配置文件里加入aop命名空间(上面加下划线的红色部分),属性proxy-target-class=”true”,是强制使用cglib代理,因为这里的切入点方法direct()所在的类继承了ActionSupport类,如果不强制使用cglib代理,会抛出找不到代理方法的错误。

6.主要页面index.jsp

启动tomcat,输入 http://localhost:88/AspectTestWeb/loginx.action 进入index.jsp

index-jsp

点击各个链接可以在控制台看到输出结果:

index-jsp2

附:cglib代理和jdk动态代理

1 如果目标对象实现了接口,默认情况下会使用jdk的动态代理实现AOP

2 如果目标对象实现了接口、可以强制使用cglib实现aop
加入 cglib-nodep.jar
加入 <aop:aspectj-autoproxy proxy-target-class=”true”/>强制使用cglib

3 如果目标对象没有实现了接口,必须采用cglib库,spring会在jdk动态代理和cglib之间转换

jdk动态代理和cglib动态代理区别
* jdk动态代理只能对实现了接口的类生成代理,而不能针对没有实现接口的类代理
* cglib是针对类实现代理、主要是对指定的类生成一个子类,覆盖了其中的方法
因为是继承。所以该类或方法最好不要声明成final,导致无法继承父类生成代理类

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值