Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录

目的:

需要对一些事物的操作进行日志记录,如果在service内进行记录,大量的代码重复,并且维护比较麻烦。所以采用AOP的方式对service进行拦截。使用自定义注解的目的则是判断是否需要记录日志和传递额外的信息。

方式

本次解决方案十分感谢博主-跳刀的兔子的博文 本文绝大部分参考与本文,略有不同,所以做一些整理,博主的文章更详细一些。

1.首先新建自定义注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented  
@Inherited
public @interface LogWrite {
    /**
     *@param 模块名字 
     */
    String modelName() default "";
    
    /**
     *@param 操作类型 
     */
    String option();
}
  • 其中@Target注解用于描述该注解的范围,我们需要注解的方法,所以值为METHOD,相关含义如下表:

取值 含义

CONSTRUCTOR 描述构造器

FIELD 描述域

LOCAL_VARIABLE 用于描述局部变量

METHOD 用于描述方法

PACKAGE 用于描述包

PARAMETER 用于描述参数

TYPE 用于描述类或接口

  • @Retention 用于描述注解的生命周期(即:被描述的注解在什么范围内有效),其取值有:

取值 含义

SOURCE 在源文件中有效(即源文件保留)

CLASS 在 class 文件中有效(即 class 保留)

RUNTIME 在运行时有效(即运行时保留)

  • @Documented 在默认的情况下javadoc命令不会将我们的annotation生成再doc中去的,所以使用该标记就是告诉jdk让它也将annotation生成到doc中去
  • @Inherited 比如有一个类A,在他上面有一个标记annotation,那么A的子类B是否不用再次标记annotation就可以继承得到呢,答案是肯定的

2.利用AOP方式拦截

  • 配置AOP,我使用的是利用注解的方式来配置AOP,方法有很多,就不详细说了。
  • 使用的是@Around 环绕通知,因为需要记录该方法是否被执行成功了。
  • 实现@Around方法中,记录日志: 获取拦截的方法,判断该方法是否含有自定义注解,如果没有的则不进行记录,否则,按照自己的方式进行记录。 我主要记录的是操作的方法,所属模块,以及所有参数所构成的Json字符串。
@Aspect
@Component
public class SnapshotLogWriteService {
	private LogService logService;
	public LogService getLogService() {
		return logService;
	}

	//自动注入日志记录service
	@Autowired
	public void setLogService(LogService logService) {
		this.logService = logService;
	}
	//环绕通知方法
	@Around("execution(* unkeltao.service.*.*(..))")
	public Object doWriteLog(ProceedingJoinPoint pjp) throws Throwable {
		System.err.println("拦截方法,进入日志记录");
		// 拦截的实体类
		Object target = pjp.getTarget();
		// 拦截的方法名称
		String methodName = pjp.getSignature().getName();
		// 拦截的方法参数
		Object[] args = pjp.getArgs();

		// 拦截的放参数类型
		Class[] parameterTypes = ((MethodSignature) pjp.getSignature())
				.getMethod().getParameterTypes();

		Object object = null;

		//需要转换成Json的HashMap
		Map<String, Object> maps = new HashMap<String, Object>();
		Map<String, Object> parammaps = new HashMap<String, Object>();
		// 获得被拦截的方法
		Method method = target.getClass().getMethod(methodName, parameterTypes);
		if (null != method) {
			// 判断是否包含自定义的注解
			if (method.isAnnotationPresent(MyAnnotation.class)) {
				// 获取自定义注解实体
				MyAnnotation myAnnotation = method
						.getAnnotation(MyAnnotation.class);
				//日志类实体类
				OptionLog log = new OptionLog();

				log.setUserid(myAnnotation.userid());
				log.setModelname(myAnnotation.modelName());
				log.setOp(myAnnotation.option());
				maps.put("方法名", method.getName());
				parammaps.put("方法名", method.getName());
                //循环获得所有参数对象
				for(int i=0; i<args.length; i++){
					if (null != args[i]) {
						parammaps.put("args["+i+"]", args[i]);
					}
					else {
						parammaps.put("args["+i+"]", "空参数");
					}
				}
				maps.put("参数", parammaps);
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
				maps.put("操作时间", sdf.format(new Date()));
				// 获取服务运行结果
				try {
					object = pjp.proceed();// 执行该方法
					maps.put("状态", "成功");
					log.setStatus(1);
				} catch (Exception e) {
					System.err.println(e.getMessage());
					maps.put("状态", "失败");
					log.setStatus(0);
					log.setComments(e.getMessage());
				}
				//将参数转化为Json字符串
				log.setJs(new JSONObject(maps).toJSONString());
				log.setOptime(new Date());
				System.err.println(new JSONObject(maps).toJSONString());  

				//记录相关日志
				if (null != logService) {
					try {
						if(1 == logService.Save(log)){
							System.err.println("日志记录成功");
						}
						else{
							System.err.println("日志记录失败");
						}

					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				else{
					System.err.println("自动注入失败,日志未记录");
				}

			} else { // 没有包含该注解则不进行其他处理
				object = pjp.proceed();// 执行该方法
			}

		} else { // 不需要拦截,直接运行
			object = pjp.proceed(); // 执行该方法
		}
		return object;
	}
}

记录结果

最终的Json效果图

原文地址: http://www.UnkelTao.com/blog/2014/07/22/spring-plus-springmvc-plus-mybatis-aop/

时间: 2024-10-15 03:27:33

Spring+SpringMVC+Mybatis 利用AOP自定义注解实现可配置日志快照记录的相关文章

Spring+SpringMvc+Mybatis框架集成搭建教程二(依赖配置及框架整合)

依赖导入以及框架整合 (1).打开项目的pom.xml文件,声明依赖 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_

Spring+SpringMvc+Mybatis框架集成搭建教程

一.背景 最近有很多同学由于没有过SSM(Spring+SpringMvc+Mybatis , 以下简称SSM)框架的搭建的经历,所以在自己搭建SSM框架集成的时候,出现了这样或者那样的问题,很是苦恼,网络上又没有很详细的讲解以及搭建的教程.闲来无事,我就利用空闲时间来写这样一个教程和搭建步骤,来帮助那些有问题的小伙伴,让你从此SSM搭建不再有问题. 二.教程目录 1.Spring+SpringMvc+Mybatis框架集成搭建教程一(项目创建) 2.Spring+SpringMvc+Mybat

(转)利用Spring AOP自定义注解解决日志和签名校验

一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: boolean isValid = accountService.validSignature(appid, signature, client_signature); if (!isValid) return ErrorUtil.buildError(ErrorUtil.ERR_CODE_COM

利用Spring AOP自定义注解解决日志和签名校验

转载:http://www.cnblogs.com/shipengzhi/articles/2716004.html 一.需解决的问题 部分API有签名参数(signature),Passport首先对签名进行校验,校验通过才会执行实现方法. 第一种实现方式(Origin):在需要签名校验的接口里写校验的代码,例如: boolean isValid = accountService.validSignature(appid, signature, client_signature); if (!

Spring+SpringMVC+MyBatis深入学习及搭建(十六)——SpringMVC注解开发(高级篇)

转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7085268.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇) 本文主要内容: (1)SpringMVC校验 (2)数据回显 (3)异常处理器 (4)图片上传 (5)Json数据交互 (6)支持RESTful 1.SpringMVC校验 1.1校验理解 项目中,通常使用较多的是前端的校验,比如页面中js校验.对于安全要求较高的

Spring+SpringMVC+MyBatis深入学习及搭建(十五)——SpringMVC注解开发(基础篇)

转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7065294.html 前面讲到:Spring+SpringMVC+MyBatis深入学习及搭建(十四)--SpringMVC和MyBatis整合 1.商品修改功能开发 1.1需求 操作流程: (1)进入商品查询列表页面: (2)点击修改,进入商品修改页面,页面中显示了要修改的商品(从数据库查询),  要修改的商品从数据库查询,根据商品id(主键)查询商品信息: (3)在商品修改页面,修改商品信息,修改后,

spring AOP + 自定义注解实现权限控制小例子

今天看了一下黑马程序员的视频,上面讲到一个使用spring AOP + 自定义注解的方式来实现权限控制的一个小例子,个人觉得还是可以借鉴,整理出来与大家分享. 需求:service层有一些方法,这些方法需要不同的权限才能访问. 实现方案:自定义一个PrivilegeInfo的注解,使用这个注解为service层中的方法进行权限配置,在aop中根据PrivilegeInfo注解的值,判断用户是否拥有访问目标方法的权限,有则访问目标方法,没有则给出提示. 关键技术:自定义注解及注解解析,spring

spring AOP自定义注解方式实现日志管理

转:spring AOP自定义注解方式实现日志管理 今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在applicationContext-mvc.xml中要添加的 <mvc:annotation-driven />     <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->     <conte

spring AOP自定义注解 实现日志管理

今天继续实现AOP,到这里我个人认为是最灵活,可扩展的方式了,就拿日志管理来说,用Spring AOP 自定义注解形式实现日志管理.废话不多说,直接开始!!! 关于配置我还是的再说一遍. 在applicationContext-mvc.xml中要添加的 <mvc:annotation-driven />     <!-- 激活组件扫描功能,在包com.gcx及其子包下面自动扫描通过注解配置的组件 -->     <context:component-scan base-pac