`
m635674608
  • 浏览: 5044696 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

spring Aop 之用户操作日志以及异常处理日志记录

 
阅读更多

使用Aop做操作日志,异常处理,并记录日志。

方法1:try{}catch(){记录日志}

方法2:通过filter,或者strtus2拦截器(目前项目是struts2)

方法3:hirbernate的拦截器记录日志

方法4:通过jvm agent 代理

方法5:自定义类加载器应该也可以

虽然说各有个的好处吧,但是我个人还是喜欢Aop,当然Aop有多种实现。目前项目上用的是Spring Aop的 Aspect 。

我觉得使用Aop会更加的解耦合,更加的从其他的业务代码中分离出来。和上一篇做方法缓存差不多,上代码。

 

首先定义个注解,用于记录该方法的描述

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {
	String remark() default "";
}

 

   Action类

    

public class Sev {
	@MethodLog(remark="增加用户信息")
	public String addUser(int type,int parentid){
		return "";
	}
}

 

  Aop 类

   

 

package com.zhang.shine.cache;

import java.lang.reflect.Method;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MethodLogAspectJ {

	@Pointcut("@annotation(com.zhang.shine.cache.MethodLog)")
	public void methodCachePointcut() {
	}

	@Around("methodCachePointcut()")
	public Object methodCacheHold(ProceedingJoinPoint joinPoint)
			throws Throwable {
		System.out.println("aop start ");
		String methodRemark = getMthodRemark(joinPoint);
		Object result = null;
		try {
			// 记录操作日志...谁..在什么时间..做了什么事情..
			result = joinPoint.proceed();
		} catch (Exception e) {
			// 异常处理记录日志..log.error(e);
			throw e;
		}

		System.out.print(methodRemark);
		System.out.println("aop end ");
		return result;
	}

	// 获取方法的中文备注____用于记录用户的操作日志描述
	public static String getMthodRemark(ProceedingJoinPoint joinPoint)
			throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();

		Class targetClass = Class.forName(targetName);
		Method[] method = targetClass.getMethods();
		String methode = "";
		for (Method m : method) {
			if (m.getName().equals(methodName)) {
				Class[] tmpCs = m.getParameterTypes();
				if (tmpCs.length == arguments.length) {
					MethodLog methodCache = m.getAnnotation(MethodLog.class);
					methode = methodCache.remark();
					break;
				}
			}
		}
		return methode;
	}

}

   <aop:config>节点中proxy-target-class="true"不为true时。

当登录的时候会报这个异常java.lang.NoSuchMethodException: $Proxy54.login(),

是因为代理Action类的时候,如果Proxy-targer-class=false,默认是用jdk动态代理。

所以代理不了Action类。

分享到:
评论
16 楼 小桔子 2015-01-20  
小桔子 写道
我不是很懂啊。原来是一个ssh的权限框架、struts 与service中都有注解。我现在需要在原来的基础上添加一个用户操作管理。查了好多。。都说spring 的aop能实现。这个什么切点啊切面的扰得头疼。我有很多疑惑!

1.像你博客中的这样,我写了两个类,配置了注解 系统启动起来之后就能自动扫描这几个文件么?。如果是struts中的比如action的注解。我看到配置文件中有定义扫描文件路径,那么系统启动的时候能自动扫描注解,那我们这个aop要怎么写,系统才能扫描到这个有注解的类?还是不用定义。。。直接就可以啊!!!


2.这个日志管理怎么作用到action中的方法。比如我想监控用户访问了哪些action以及action的方法,每次访问我拦截到,插入数据库。我要在注解中写她的作用地方么?

@Pointcut("@annotation(com.zhang.shine.cache.MethodLog)")

@Around("methodCachePointcut()") 

//你这里是申明aop作用到action的地方么?如果是,那每个方法都要这么写么?
  @MethodLog(remark="增加用户信息") 
    public String addUser(int type,int parentid){ 
        return ""; 
    } 

谢谢。。。
15 楼 小桔子 2015-01-20  
我不是很懂啊。原来是一个ssh的权限框架、struts 与service中都有注解。我现在需要在原来的基础上添加一个用户操作管理。查了好多。。都说spring 的aop能实现。这个什么切点啊切面的扰得头疼。我有很多疑惑!

1.像你博客中的这样,我写了两个类,配置了注解 系统启动起来之后就能自动扫描这几个文件么?。如果是struts中的比如action的注解。我看到配置文件中有定义扫描文件路径,那么系统启动的时候能自动扫描注解,那我们这个aop要怎么写,系统才能扫描到这个有注解的类?还是不用定义。。。直接就可以啊!!!


2.这个日志管理怎么作用到action中的方法。比如我想监控用户访问了哪些action以及action的方法,每次访问我拦截到,插入数据库。我要在注解中写她的作用地方么?

@Pointcut("@annotation(com.zhang.shine.cache.MethodLog)")

@Around("methodCachePointcut()") 

//你这里是申明aop作用到action的地方么?如果是,那每个方法都要这么写么?
  @MethodLog(remark="增加用户信息") 
    public String addUser(int type,int parentid){ 
        return ""; 
    } 
14 楼 小桔子 2015-01-20  
我如果加上这个<aop:config>节点中proxy-target-class="true"。。我原理的框架不能用啊!
m635674608 写道
小桔子 写道
配置文件中需要怎么配置?。。我现有的框架是这种。。spring中这么写的
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />

<!-- 自动扫描dao和service包(自动注入) -->
<context:component-scan base-package="com.szcatic.dao,com.szcatic.service" />


我的日志是设计到控制层的,比如用strtus的话,就把在控制层加切面
13 楼 m635674608 2015-01-19  
小桔子 写道
配置文件中需要怎么配置?。。我现有的框架是这种。。spring中这么写的
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />

<!-- 自动扫描dao和service包(自动注入) -->
<context:component-scan base-package="com.szcatic.dao,com.szcatic.service" />


我的日志是设计到控制层的,比如用strtus的话,就把在控制层加切面
12 楼 小桔子 2015-01-19  
配置文件中需要怎么配置?。。我现有的框架是这种。。spring中这么写的
<!-- 引入属性文件 -->
<context:property-placeholder location="classpath:config.properties" />

<!-- 自动扫描dao和service包(自动注入) -->
<context:component-scan base-package="com.szcatic.dao,com.szcatic.service" />

11 楼 m635674608 2014-09-01  
yokoboy 写道
谢谢,很有用!

不用谢
10 楼 yokoboy 2014-09-01  
谢谢,很有用!
9 楼 m635674608 2013-11-26  
sangxue2587 写道
spring mvc 如何使用改注解呢??

加在方法上面不就可以了吗
8 楼 sangxue2587 2013-11-26  
spring mvc 如何使用改注解呢??
7 楼 sangxue2587 2013-11-26  
xml中怎么配置的呢,我是才开始接触aop的?
6 楼 yjian84 2013-08-14  
xiongpan0807 写道
xiongpan0807 写道
有一事不解,aop的方式,你如何获得当前操作的是哪个用户呢.求教

诶,刚刚范二了,写这里与和我同样范二的人分享吧,ServletActionContext.getRequest().getSession()


你用的是struts2 吧

aop 中直接切你的log 类,就不用那么麻烦了。

@Around("execution(* com.cms.controller.*.*.*(..)) && @annotation(sysLog)")
	public Object recordSysLog(ProceedingJoinPoint point,SysLog sysLog) throws Throwable{
		System.out.println(sysLog);
		System.out.println(request.getRequestURL());
		OperatorLog o = new OperatorLog();
		o.setContent(sysLog.value());
		o.setId(UUIDUtils.getUUID());
		Calendar c = 	Calendar.getInstance();
		o.setCreateTime(new Timestamp(c.getTimeInMillis()));
		o.setIp(IPUtils.getIpByHostName(request.getRemoteHost()));
		o.setMethod(point.getSignature().getName());
		o.setOperatorId("333");
		o.setOperatorName("zhangsan");
		o.setUrl(request.getRequestURI());
		sysLogService.insert(o);
		PageInfo<OperatorLog> p = new PageInfo<OperatorLog>();
		
		 sysLogService.pageQuery(p, null);
		
		List<OperatorLog> op = p.getResult();
		for(OperatorLog ops:op){
			System.out.println(ops.getContent());
			System.out.println(ops.getIp());
			System.out.println(ops.getMethod());
			System.out.println(ops.getCreateTime());
		}
		
		
		
		System.out.println("lfkdjj================================================================");
		return point.proceed();
	}
5 楼 yjian84 2013-08-14  
xiongpan0807 写道
有一事不解,aop的方式,你如何获得当前操作的是哪个用户呢.求教

web.xml 中配置
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
aop 中:
@Autowired
private HttpServletRequest request;

HttpSession session = request.getSession();

session 获得当前用户。
4 楼 xiongpan0807 2013-08-14  
xiongpan0807 写道
有一事不解,aop的方式,你如何获得当前操作的是哪个用户呢.求教

诶,刚刚范二了,写这里与和我同样范二的人分享吧,ServletActionContext.getRequest().getSession()
3 楼 xiongpan0807 2013-08-14  
有一事不解,aop的方式,你如何获得当前操作的是哪个用户呢.求教
2 楼 m635674608 2013-07-26  
yjian84 写道
我不得不来评论你写的这段代码,思路是正确的,但是有个问题被忽略了。
你的:
for (Method m : method) {  
         [b]   if (m.getName().equals(methodName)) { [/b] 
                Class[] tmpCs = m.getParameterTypes();  
                [b]if (tmpCs.length == arguments.length) [/b]{  
                    MethodLog methodCache = m.getAnnotation(MethodLog.class);  
                    methode = methodCache.remark();  
                    break;  
                }  
            }  
        }  

这个只是判断方法名和参数列表的个数是否相同,并不能准确的判断出这个方法就一定是当前执行的方法。
eg: @SysLog(value="分页查询用户信息")
       :a:public PageInfo<User> findPageUser(PageInfo<User> page,Map<String,Object>       filter);
	b:public PageInfo<User> findPageUser(PageInfo<User> page,String id);
	c:public PageInfo<User> findPageUser(PageInfo<User> page,int id);
	d:public PageInfo<User> findPageUser(PageInfo<User> page,long id);


如果照你上面的写法的话,我要是请求 b ,c,d 任何一个方法都是满足你的条件的,此时 methodCache  是null ,下面就会报错了。

Overloading :重载,(参数个数和参数类型 有关) 这个很重要

对于:当前执行的方法获得,我采用的是下面的方式:


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SysLog {
	String value();
}


        [b]        Signature signature = proJoinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature)signature;
		Method m = methodSignature.getMethod();[/b]
		System.out.println(m.getAnnotation(SysLog.class));
		SysLog a = m.getAnnotation(SysLog.class);
		if(a!=null){
			System.out.println(a.value());
		}


然后记录下a.value() 的值用来当做用户的操作日志。













呵呵。。我还没注意看。。
但是在我的项目中,把所有的异常都抛到Action中来处理了。。
所有没有出现过你这种问题。。
我写这个,只是提供这种AOp处理日志的思路而已。。具体怎么实现,看具体业务来
1 楼 yjian84 2013-07-24  
我不得不来评论你写的这段代码,思路是正确的,但是有个问题被忽略了。
你的:
for (Method m : method) {  
         [b]   if (m.getName().equals(methodName)) { [/b] 
                Class[] tmpCs = m.getParameterTypes();  
                [b]if (tmpCs.length == arguments.length) [/b]{  
                    MethodLog methodCache = m.getAnnotation(MethodLog.class);  
                    methode = methodCache.remark();  
                    break;  
                }  
            }  
        }  

这个只是判断方法名和参数列表的个数是否相同,并不能准确的判断出这个方法就一定是当前执行的方法。
eg: @SysLog(value="分页查询用户信息")
       :a:public PageInfo<User> findPageUser(PageInfo<User> page,Map<String,Object>       filter);
	b:public PageInfo<User> findPageUser(PageInfo<User> page,String id);
	c:public PageInfo<User> findPageUser(PageInfo<User> page,int id);
	d:public PageInfo<User> findPageUser(PageInfo<User> page,long id);


如果照你上面的写法的话,我要是请求 b ,c,d 任何一个方法都是满足你的条件的,此时 methodCache  是null ,下面就会报错了。

Overloading :重载,(参数个数和参数类型 有关) 这个很重要

对于:当前执行的方法获得,我采用的是下面的方式:


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SysLog {
	String value();
}


        [b]        Signature signature = proJoinPoint.getSignature();
		MethodSignature methodSignature = (MethodSignature)signature;
		Method m = methodSignature.getMethod();[/b]
		System.out.println(m.getAnnotation(SysLog.class));
		SysLog a = m.getAnnotation(SysLog.class);
		if(a!=null){
			System.out.println(a.value());
		}


然后记录下a.value() 的值用来当做用户的操作日志。












相关推荐

    使用Spring AOP对异常进行统一处理

    2.需要记录异常日志时没有记录,或者异常在不同的地方重复记录,使得排错调试不方便 3.处理日志时,需要在每一个try-catch块包含一些处理代码,有时候异常处理的代码比正常执行代码还多,污染正常执行代码。 4.同样...

    spring aop 自定义注解保存操作日志到mysql数据库 源码

    4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑实现 (需要知道原理的请看spring aop源码,此处不做赘述) 3、...

    spring aop 操作日志

    本资源用来展示如何使用 spring aop 进行日志记录,例子里面通过aop的配置,把产生的日志存放到当前项目的根目录下,而且对方法执行过程中的参数进行了记录,对于aop如何记录日志不清楚的同学可以看看。

    Spring aop 记录操作日志 Aspect 源码

    总之,Spring AOP提供了一种优雅的方式来实现记录操作日志的需求,通过自定义Aspect和注解,我们可以灵活地控制哪些方法需要记录日志,以及记录什么样的日志信息。这个过程既提高了代码的可维护性,也使得日志管理...

    spring aop 切面添加日志

    通过这个项目,我们可以学习到如何在Spring AOP中实现日志记录,这不仅可以帮助我们调试和监控应用程序,还可以为未来的维护提供宝贵的线索。同时,这也是理解和实践面向切面编程的一个很好的起点。

    spring AOP 切面日志 分层打日志

    在大型系统中,日志通常需要按层次结构进行,例如:数据库操作、业务逻辑处理、用户交互等。通过调整切入点表达式,我们可以精确地控制在哪些类或方法上应用日志记录。例如,我们可以为DAO层、Service层和Controller...

    Spring之AOP在鉴权和日志记录中的应用

    **Spring AOP在鉴权和日志记录中的应用** **一、引言** Spring AOP(Aspect Oriented Programming,面向切面编程)是Spring框架的一个重要特性,它为开发者提供了在不修改源代码的情况下,对应用程序进行功能增强...

    spring boot aop 统一处理日志

    在Spring Boot应用中,AOP(面向切面编程)是一种强大的工具,用于实现代码的解耦和模块化,尤其适用于处理横切关注点,如日志记录、事务管理、安全控制等。本教程将深入探讨如何利用Spring Boot的AOP特性来实现日志...

    Spring AOP 日志管理 实例

    Spring AOP 日志管理 实例LoggingThrowsAdvice.java

    spring.net结合三层AOP异常日志记录功能

    在异常情况下,可以定义一个切面来捕获并处理异常,同时记录日志。 4. **异常日志记录**:日志记录是系统故障排查的重要手段。我们可以创建一个自定义的日志类,实现IAdvice接口,这样Spring.NET就能在发生异常时...

    spring aop jar 包

    Spring AOP(Aspect Oriented Programming,面向切面...总的来说,Spring AOP通过提供面向切面的编程能力,极大地提高了代码的可复用性和可维护性,降低了系统复杂度,特别是在处理共性问题如日志、事务、安全等方面。

    spring aop实现接口参数变更前后对比和日志记录

    spring aop实现接口参数变更前后对比和日志记录完整代码,拿到项目代码,只需要做数据库连接的修改即可运行起来使用,代码案例详细,真是可靠,代码原文地址:...

    利用spring AOP记录用户操作日志的方法示例

    Spring AOP 记录用户操作日志的方法示例 Spring AOP(Aspect-Oriented Programming)是一种面向方面编程技术,可以帮助开发者实现跨越多个对象和类的功能。在本文中,我们将介绍如何使用 Spring AOP 来记录用户操作...

    JAVA 中Spring aop 实现日志记载

    在实际开发中,Spring AOP的日志记载不仅限于打印方法名和返回值,还可以记录参数、执行时间、异常信息等,帮助开发者更好地监控和调试系统。 综上所述,Spring AOP提供了一种优雅的方式,让我们能够轻松地在不...

    SpringAOP日志管理

    采用SpringAOP拦截Controller,Service实现操作日志管理,统一处理异常,登陆日志管理,是SpringAOP的应用实践。通过SpringAOP的处理,可以方便移植日志管理功能,是个不错的学习demo

    spring aop实现日志功能

    标题"spring aop实现日志功能"涉及到的是如何利用Spring AOP来记录和跟踪应用程序中的操作,这对于调试、性能分析和故障排查至关重要。下面我们将详细探讨如何通过Spring AOP来实现日志功能。 首先,理解AOP的基本...

    swagger和spring Aop日志结合

    另一方面,Spring AOP(面向切面编程)则是Spring框架的一个核心特性,用于实现跨切面的关注点,如日志记录。本篇文章将深入探讨如何将Swagger与Spring AOP结合起来,以实现优雅的日志记录功能。 首先,让我们了解...

    Spring AOP完整例子

    总结一下,Spring AOP提供了一种优雅的方式来处理系统的横切关注点,如日志记录、事务管理或性能监控。通过定义切点、创建切面和配置通知,我们可以实现代码的解耦,提高可维护性和复用性。这个例子提供了学习Spring...

    spring aop日志拦截

    在Spring MVC框架中,AOP(面向切面编程)是一种强大的工具,用于实现日志拦截,特别是对于controller层的操作。AOP允许我们定义横切关注点,这些关注点可以是如日志记录、事务管理、权限检查等通用功能,它们在程序...

Global site tag (gtag.js) - Google Analytics