热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

aop注解方式实现全局日志管理方法

下面小编就为大家分享一篇aop注解方式实现全局日志管理方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

1:日志实体类

public class SysLog {
 /** */
 private Integer id;
 /** 日志描述*/
 private String description;
 /** 执行的方法*/
 private String method;
 /** 日志类型 0:操作日志;1:异常日志*/
 private Integer logType;
 /** 客户端请求的ip地址*/
 private String requestIp;
 /** 异常代码*/
 private String exceptionCode;
 /** 异常详细信息*/
 private String exceptionDetail;
 /** 请求参数*/
 private String params;
 /** 操作人*/
 private String createBy;
 /** 操作时间*/
 private String createDate;
 public Integer getId() {
  return id;
 }
 public void setId(Integer id) {
  this.id = id;
 }
 public String getDescription() {
  return description;
 }
 public void setDescription(String description) {
  this.description = description;
 }
 public String getMethod() {
  return method;
 }
 public void setMethod(String method) {
  this.method = method;
 }
 public Integer getLogType() {
  return logType;
 }
 public void setLogType(Integer logType) {
  this.logType = logType;
 }
 public String getRequestIp() {
  return requestIp;
 }
 public void setRequestIp(String requestIp) {
  this.requestIp = requestIp;
 }
 public String getExceptionCode() {
  return exceptionCode;
 }
 public void setExceptionCode(String exceptionCode) {
  this.exceptiOnCode= exceptionCode;
 }
 public String getExceptionDetail() {
  return exceptionDetail;
 }
 public void setExceptionDetail(String exceptionDetail) {
  this.exceptiOnDetail= exceptionDetail;
 }
 public String getParams() {
  return params;
 }
 public void setParams(String params) {
  this.params = params;
 }
 public String getCreateBy() {
  return createBy;
 }
 public void setCreateBy(String createBy) {
  this.createBy = createBy;
 }
 public String getCreateDate() {
  return createDate;
 }
 public void setCreateDate(String createDate) {
  this.createDate = createDate;
 }
}

2:maven需要的jar

 
   org.aspectj 
   aspectjrt 
   1.7.4 
   
  
   org.aspectj 
   aspectjweaver 
   1.7.4 
  
 
   cglib 
   cglib 
   2.1_3 
 

  org.springframework
  spring-aop
  4.2.5.RELEASE
 

这里要求项目使用的是jdk1.7

3:springServlet-mvc.xml

 
 

加上proxy-target-class="true"是为了可以拦截controller里面的方法

4:定义切面,我这里主要写前置通知和异常通知

下面开始自定义注解

import java.lang.annotation.*;
@Target({ElementType.PARAMETER, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
@Documented 
public @interface Log {
	/** 要执行的操作类型比如:add操作 **/ 
	 public String operationType() default ""; 
	 /** 要执行的具体操作比如:添加用户 **/ 
	 public String operationName() default "";
}

切面类

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
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.gtcity.user.model.SysLog;
import com.gtcity.user.model.SysUser;
import com.gtcity.user.service.SysLogService;
/**
 * @author panliang
 * @version 创建时间:2017-3-31 
 * @desc 切点类 
 *
 */
@Aspect
@Component
public class SystemLogAspect {
	//注入Service用于把日志保存数据库 
	@Resource 
	private SysLogService systemLogService;
	private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect. class); 
	
	//Controller层切点 
	//第一个*代表所有的返回值类型
	//第二个*代表所有的类
	//第三个*代表类所有方法
	//最后一个..代表所有的参数。
	 @Pointcut("execution (* com.gtcity.web.controller..*.*(..))") 
	 public void controllerAspect() { 
	 } 
	 
	 /**
	 * 
	 * @author: panliang
	 * @time:2017-3-31 下午2:22:16
	 * @param joinPoint 切点
	 * @describtion:前置通知 用于拦截Controller层记录用户的操作 
	 */
	 @Before("controllerAspect()")
	 public void doBefore(JoinPoint joinPoint) {
		/* System.out.println("==========执行controller前置通知===============");
		 if(logger.isInfoEnabled()){
			 logger.info("before " + joinPoint);
		 }*/
		 
		 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 
   HttpSession session = request.getSession(); 
   //读取session中的用户 
   SysUser user = (SysUser) session.getAttribute("user"); 
   if(user==null){
  	 user=new SysUser();
  	 user.setUserName("非注册用户");
   }
   //请求的IP 
   String ip = request.getRemoteAddr();
   try { 
    
    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 operatiOnType= "";
    String operatiOnName= "";
    for (Method method : methods) { 
     if (method.getName().equals(methodName)) { 
      Class[] clazzs = method.getParameterTypes(); 
      if (clazzs.length == arguments.length) { 
       operatiOnType= method.getAnnotation(Log.class).operationType();
       operatiOnName= method.getAnnotation(Log.class).operationName();
       break; 
      } 
     } 
    }
    //*========控制台输出=========*// 
    System.out.println("=====controller前置通知开始====="); 
    System.out.println("请求方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType); 
    System.out.println("方法描述:" + operationName); 
    System.out.println("请求人:" + user.getUserName()); 
    System.out.println("请求IP:" + ip); 
    //*========数据库日志=========*// 
    SysLog log = new SysLog(); 
    log.setDescription(operationName); 
    log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType); 
    log.setLogType(0); 
    log.setRequestIp(ip); 
    log.setExceptionCode(null); 
    log.setExceptionDetail( null); 
    log.setParams( null); 
    log.setCreateBy(user.getUserName());
    log.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 
    log.setRequestIp(ip);
    //保存数据库 
    systemLogService.insert(log); 
    System.out.println("=====controller前置通知结束====="); 
   } catch (Exception e) { 
    //记录本地异常日志 
    logger.error("==前置通知异常=="); 
    logger.error("异常信息:{}", e.getMessage()); 
   } 
		 
		 
	 } 
	 
	 
 
  /**
	 * 
	 * @author: panliang
	 * @time:2017-3-31 下午2:24:36
	 * @param joinPoint 切点 
	 * @describtion:异常通知 用于拦截记录异常日志 
	 */
  @AfterThrowing(pointcut = "controllerAspect()", throwing="e") 
  public void doAfterThrowing(JoinPoint joinPoint, Throwable e) { 
 	 
 	 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 
   HttpSession session = request.getSession(); 
   //读取session中的用户 
   SysUser user = (SysUser) session.getAttribute("user"); 
   if(user==null){
   	 user=new SysUser();
   	 user.setUserName("非注册用户");
   }
   //请求的IP 
   String ip = request.getRemoteAddr();
   
   String params = ""; 
   if (joinPoint.getArgs() != null && joinPoint.getArgs().length > 0) { 
   
  	 params=Arrays.toString(joinPoint.getArgs());
   } 
   try { 
    
    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 operatiOnType= "";
    String operatiOnName= "";
    for (Method method : methods) { 
     if (method.getName().equals(methodName)) { 
      Class[] clazzs = method.getParameterTypes(); 
      if (clazzs.length == arguments.length) { 
       operatiOnType= method.getAnnotation(Log.class).operationType();
       operatiOnName= method.getAnnotation(Log.class).operationName();
       break; 
      } 
     } 
    }
    /*========控制台输出=========*/ 
    System.out.println("=====异常通知开始====="); 
    System.out.println("异常代码:" + e.getClass().getName()); 
    System.out.println("异常信息:" + e.getMessage()); 
    System.out.println("异常方法:" + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")+"."+operationType); 
    System.out.println("方法描述:" + operationName); 
    System.out.println("请求人:" + user.getUserName()); 
    System.out.println("请求IP:" + ip); 
    System.out.println("请求参数:" + params); 
    //==========数据库日志========= 
    SysLog log = new SysLog();
    log.setDescription(operationName); 
    log.setExceptionCode(e.getClass().getName()); 
    log.setLogType(1); 
    log.setExceptionDetail(e.getMessage()); 
    log.setMethod((joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName() + "()")); 
    log.setParams(params); 
    log.setCreateBy(user.getUserName()); 
    log.setCreateDate(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); 
    log.setRequestIp(ip); 
    //保存数据库 
    systemLogService.insert(log); 
    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); 
 
  } 
	 
}

5:在controller里面

/**
	 * 根据用户名去找密码 判断用户名和密码是否正确
	 * @author panliang
	 * @param request
	 * @param response
	 * @throws IOException 
	 */
	@RequestMapping("/skipPage.do")
	@Log(operatiOnType="select操作:",operatiOnName="用户登录")//注意:这个不加的话,这个方法的日志记录不会被插入
	public ModelAndView skipPage(HttpServletRequest request,HttpServletResponse response) throws IOException{
		
		ModelAndView result=null;
		String username = request.getParameter("email");
		String password = request.getParameter("password");
		int flag = sysUserService.login(request, username, password);
		if(flag==1){//登录成功
			result=new ModelAndView("redirect:/login/dispacher_main.do");
		}else if(flag==2){//用户名不存在		
			result=new ModelAndView("redirect:/login/login.do?errorCode=1");			
		} else{//密码不正确	
			result=new ModelAndView("redirect:/login/login.do?errorCode=2");			
		}
		return result;
	}

对于想要了解其他三种通知的可以参考这篇博文:点击打开链接

这样用户在访问后台时,不管是正常访问还是出现bug数据库都有记录

以上这篇aop注解方式实现全局日志管理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


推荐阅读
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • ZSI.generate.Wsdl2PythonError: unsupported local simpleType restriction ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Webmin远程命令执行漏洞复现及防护方法
    本文介绍了Webmin远程命令执行漏洞CVE-2019-15107的漏洞详情和复现方法,同时提供了防护方法。漏洞存在于Webmin的找回密码页面中,攻击者无需权限即可注入命令并执行任意系统命令。文章还提供了相关参考链接和搭建靶场的步骤。此外,还指出了参考链接中的数据包不准确的问题,并解释了漏洞触发的条件。最后,给出了防护方法以避免受到该漏洞的攻击。 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 如何在服务器主机上实现文件共享的方法和工具
    本文介绍了在服务器主机上实现文件共享的方法和工具,包括Linux主机和Windows主机的文件传输方式,Web运维和FTP/SFTP客户端运维两种方式,以及使用WinSCP工具将文件上传至Linux云服务器的操作方法。此外,还介绍了在迁移过程中需要安装迁移Agent并输入目的端服务器所在华为云的AK/SK,以及主机迁移服务会收集的源端服务器信息。 ... [详细]
  • flowable工作流 流程变量_信也科技工作流平台的技术实践
    1背景随着公司业务发展及内部业务流程诉求的增长,目前信息化系统不能够很好满足期望,主要体现如下:目前OA流程引擎无法满足企业特定业务流程需求,且移动端体 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • 本文介绍了一种处理AJAX操作授权过期的全局方式,以解决Asp.net MVC中Session过期异常的问题。同时还介绍了基于WebImage的图片上传工具类。详细内容请参考链接:https://www.cnblogs.com/starluck/p/8284949.html ... [详细]
  • 本文介绍了ASP.NET Core MVC的入门及基础使用教程,根据微软的文档学习,建议阅读英文文档以便更好理解,微软的工具化使用方便且开发速度快。通过vs2017新建项目,可以创建一个基础的ASP.NET网站,也可以实现动态网站开发。ASP.NET MVC框架及其工具简化了开发过程,包括建立业务的数据模型和控制器等步骤。 ... [详细]
  • 使用J2SE模拟MVC模式开发桌面应用程序的工程包的介绍
    以我开发过的一个娱乐管理系统为例:下图为我系统的业务逻辑的MVC流程:下图为以Eclipse开发中各包的说明:转载于:https:blog ... [详细]
  • 本文讨论了在shiro java配置中加入Shiro listener后启动失败的问题。作者引入了一系列jar包,并在web.xml中配置了相关内容,但启动后却无法正常运行。文章提供了具体引入的jar包和web.xml的配置内容,并指出可能的错误原因。该问题可能与jar包版本不兼容、web.xml配置错误等有关。 ... [详细]
author-avatar
手机用户2502887521
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有