博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring aop实现日志收集
阅读量:7126 次
发布时间:2019-06-28

本文共 12261 字,大约阅读时间需要 40 分钟。

概述

使用spring aop 来实现日志的统一收集功能

详细

代码下载:

使用spring aop 来实现日志的统一收集功能。

spring aop 配置

首先,我们定义2种注解,一种是给service用的,一种是给Controller用的。

给service使用的aop扫描
给Controller使用的aop扫描

 

java实现

实现思路,先定义两个注解类,一个给service类用的,一个给从controller类用的,然后使用切面类,对这两个注解进行绑定监控。结果就是,当使用注解绑定某个service类或者controller类的某个方法时,这个切面类就能监控到,并且能获取到这个service方法的相关输入,输出参数等。这样,就能实现了aop日志了。

给controller使用的注解类
package com.demodashi.aop.annotation;import java.lang.annotation.*;        /**   *自定义注解 拦截Controller   */        @Target({ElementType.PARAMETER, ElementType.METHOD})    @Retention(RetentionPolicy.RUNTIME)    @Documented    public  @interface ControllerLogAnnotation {        String description()  default "";    }
给service使用的注解类
package com.demodashi.aop.annotation;import java.lang.annotation.*;        /**   *自定义注解 拦截service   */        @Target({ElementType.PARAMETER, ElementType.METHOD})    @Retention(RetentionPolicy.RUNTIME)    @Documented    public  @interface ServiceLogAnnotation {            String description()  default "";    }
日志切面类
package com.demodashi.aop;import java.lang.reflect.Method;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import org.aspectj.lang.JoinPoint;import org.aspectj.lang.annotation.AfterReturning;import org.aspectj.lang.annotation.AfterThrowing;import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;import org.aspectj.lang.annotation.Pointcut;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Component;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import com.alibaba.fastjson.JSONObject;import com.demodashi.aop.annotation.ControllerLogAnnotation;import com.demodashi.aop.annotation.ServiceLogAnnotation;import com.demodashi.base.UserVO;/** * 切点类    * @author xgchen * */@Aspect    @Component    public  class SystemLogAspect {        	public SystemLogAspect(){	}	    //本地异常日志记录对象        private  static  final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);            //Service层切点        @Pointcut("@annotation(com.demodashi.aop.annotation.ServiceLogAnnotation)")        public  void serviceAspect() {    }        //Controller层切点        @Pointcut("@annotation(com.demodashi.aop.annotation.ControllerLogAnnotation)")        public  void controllerAspect() {        }        /**       * 前置通知 用于拦截Controller层记录用户的操作       *       * @param joinPoint 切点       */    @Before("controllerAspect()")	public  void doBefore4control(JoinPoint joinPoint) {        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();            HttpSession session = request.getSession();            //读取session中的用户            UserVO user = (UserVO) session.getAttribute("USER");        //请求的IP            String ip = request.getRemoteAddr();             try {                //*========控制台输出=========*//                System.out.println("=====control 前置通知开始=====");            System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));                System.out.println("方法描述:" + getControllerMethodDescription(joinPoint));                System.out.println("请求人ID:" + user.getId());            System.out.println("请求人NAME:" + user.getName());            System.out.println("请求IP:" + ip);                System.out.println("=====前置通知结束=====");            }  catch (Exception e) {            //记录本地异常日志                logger.error("==前置通知异常==");            logger.error("异常信息:{}", e.getMessage());            }    }        @Before("serviceAspect()")    public  void doBefore4service(JoinPoint joinPoint) {    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();            HttpSession session = request.getSession();            //读取session中的用户            UserVO user = (UserVO) session.getAttribute("USER");            //获取请求ip            String ip = request.getRemoteAddr();        //获取用户请求方法的参数并序列化为JSON格式字符串            String params = "";             if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {                 for ( int i = 0; i < joinPoint.getArgs().length; i++) {                    params += JSONObject.toJSON(joinPoint.getArgs()[i]).toString() + ";";            }          }        try {                /*========控制台输出=========*/            	System.out.println("=====service 前置通知开始=====");            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));                System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));                System.out.println("请求人ID:" + user.getId());            System.out.println("请求人NAME:" + user.getName());            System.out.println("请求IP:" + ip);            System.out.println("请求参数:" + params);                    }  catch (Exception ex) {                //记录本地异常日志                logger.error("==异常通知异常==");                logger.error("异常信息:{}", ex.getMessage());            }        }        @AfterReturning(pointcut="serviceAspect()", returning="returnValue")    public  void after4service(JoinPoint joinPoint, Object returnValue) {    	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();            HttpSession session = request.getSession();            //读取session中的用户            UserVO user = (UserVO) session.getAttribute("USER");            //获取请求ip            String ip = request.getRemoteAddr();        //获取用户请求方法的参数并序列化为JSON格式字符串            String params = "";         if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {                 for ( int i = 0; i < joinPoint.getArgs().length; i++) {                    params += JSONObject.toJSON(joinPoint.getArgs()[i]).toString() + ";";            }          }        try {                /*========控制台输出=========*/            	System.out.println("=====service 后置通知开始=====");            System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));                System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));                System.out.println("请求人ID:" + user.getId());            System.out.println("请求人NAME:" + user.getName());            System.out.println("请求IP:" + ip);            System.out.println("请求参数:" + params);            System.out.println("返回值为:" + JSONObject.toJSON(returnValue).toString());        }  catch (Exception ex) {                //记录本地异常日志                logger.error("==异常通知异常==");                logger.error("异常信息:{}", ex.getMessage());            }    }        /**       * 异常通知 用于拦截service层记录异常日志       *       * @param joinPoint       * @param e       */        @AfterThrowing(pointcut = "serviceAspect()", throwing = "e")    	public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {        	HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();            HttpSession session = request.getSession();            //读取session中的用户            UserVO user = (UserVO) session.getAttribute("USER");         //获取请求ip            String ip = request.getRemoteAddr();            //获取用户请求方法的参数并序列化为JSON格式字符串            String params = "";             if (joinPoint.getArgs() !=  null && joinPoint.getArgs().length > 0) {                 for ( int i = 0; i < joinPoint.getArgs().length; i++) {                	 params += JSONObject.toJSON(joinPoint.getArgs()[i]).toString() + ";";            }          }        try {                /*========控制台输出=========*/                System.out.println("=====异常通知开始=====");            System.out.println("异常代码:" + e.getClass().getName());                System.out.println("异常信息:" + e.getMessage());                System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()"));                System.out.println("方法描述:" + getServiceMthodDescription(joinPoint));                System.out.println("请求人ID:" + user.getId());            System.out.println("请求人NAME:" + user.getName());            System.out.println("请求IP:" + ip);            System.out.println("请求参数:" + params);                        System.out.println("=====异常通知结束=====");            }  catch (Exception ex) {                //记录本地异常日志                logger.error("==异常通知异常==");                logger.error("异常信息:{}", ex.getMessage());            }             /*==========记录本地异常日志==========*/            logger.error("异常方法:{}异常代码:{}异常信息:{}参数:{}", joinPoint.getTarget().getClass().getName() + joinPoint.getSignature().getName(), e.getClass().getName(), e.getMessage(), params);            }                /**       * 获取注解中对方法的描述信息 用于service层注解       *       * @param joinPoint 切点       * @return 方法描述       * @throws Exception       */         public  static String getServiceMthodDescription(JoinPoint joinPoint)             throws Exception {            String targetName = joinPoint.getTarget().getClass().getName();            String methodName = joinPoint.getSignature().getName();            Object[] arguments = joinPoint.getArgs();            Class targetClass = Class.forName(targetName);            Method[] methods = targetClass.getMethods();            String description = "";             for (Method method : methods) {                 if (method.getName().equals(methodName)) {                    Class[] clazzs = method.getParameterTypes();                     if (clazzs.length == arguments.length) {                        description = method.getAnnotation(ServiceLogAnnotation. class).description();                         break;                    }                }            }             return description;        }            /**       * 获取注解中对方法的描述信息 用于Controller层注解       *       * @param joinPoint 切点       * @return 方法描述       * @throws Exception       */         public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {            String targetName = joinPoint.getTarget().getClass().getName();            String methodName = joinPoint.getSignature().getName();            Object[] arguments = joinPoint.getArgs();            Class targetClass = Class.forName(targetName);            Method[] methods = targetClass.getMethods();            String description = "";             for (Method method : methods) {                 if (method.getName().equals(methodName)) {                    Class[] clazzs = method.getParameterTypes();                     if (clazzs.length == arguments.length) {                        description = method.getAnnotation(ControllerLogAnnotation. class).description();                         break;                    }                }            }             return description;        }    }
aop使用

就是将注解绑定到具体的service方法上面,或者control方法,如下所示:

@ServiceLogAnnotation(description = "修改密码")@Overridepublic UserVO changePassword(UserVO vo, String newPassword) {	vo.setPassword(newPassword);	return vo;}
@ResponseBody@RequestMapping("/editPassword.do")@ControllerLogAnnotation(description = "接受修改密码的请求")public Map changePassword(ModelMap modelMap, HttpServletRequest request,		HttpServletResponse response) throws IOException {	String message = null;	String result = null;	Object vo = request.getSession().getAttribute("USER");	if (vo == null) {		message = "操作失败:对象不能为空!";	} else if (StringUtils.isBlank(request.getParameter("newPassword"))) {		message = "新登陆密码不能为空!";	}	if (message == null) {		try {			userApplication.changePassword((UserVO)vo, request.getParameter("newPassword"));			message = "修改成功!";			result = ConstantBean.SUCCESS;		} catch (Exception e) {			message = e.getMessage();			result = ConstantBean.SYSERR;		}	} else {		result = ConstantBean.SYSERR;	}		return toMap("data", message, "result", result);}

运行起来

首把demo导入到eclipse后,运行的界面如下:

image.png

用户名 1001 密码 123

登陆后,修改密码,则看到eclipse控制台打印如下信息:

image.png

这样一个aop收集日志的功能了,这样的方式比直接把log写在具体的方法上要强多了,收集起来的log,可以直接写在本地,也可以接入elk方案。

接入elk方案可以参考本网站中的:《ELK + kafka 日志方案》

 

代码下载:

注:本文著作权归作者,由demo大师发表,拒绝转载,转载需要作者授权

 

你可能感兴趣的文章
京东金融大数据竞赛猪脸识别(4)-方法选取
查看>>
LVS DR配置和keepalived+LVS
查看>>
Format a Sentence-格式化输出句子
查看>>
crontab详解
查看>>
object- and mysql-based session-handler
查看>>
Lantek软件的单机版与网路版安装步骤
查看>>
ELK的安装配置使用
查看>>
C语言设计模式-单例模式
查看>>
Windows 下查看进程号
查看>>
Python格式化日期
查看>>
Skype for Business Server 2015-07-边缘服务器-1-安装-先决条件
查看>>
Excel导数据进mysql
查看>>
Android上传文件到Web服务器,PHP接收文件
查看>>
C#下简单的函数指针使用实例
查看>>
Ex2010学习(四),TMG发布Exchange 2010 OWA
查看>>
Android SDK 离线包下载(2014年8月7日更新)
查看>>
初探druid 数据源加密,简单的密码加密。
查看>>
中文Webfont(附神器推荐)
查看>>
数据中心分解实验(一)------ 7 5 2
查看>>
ganglia部署错误配置-03.docx
查看>>