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

<dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjrt</artifactId>
   <version>1.7.4</version>
  </dependency>
 <dependency>
   <groupId>org.aspectj</groupId>
   <artifactId>aspectjweaver</artifactId>
   <version>1.7.4</version>
 </dependency>
<dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>2.1_3</version>
 </dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>4.2.5.RELEASE</version>
</dependency> 

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

3:springServlet-mvc.xml

<!--proxy-target-class="true"强制使用cglib代理 如果为false则spring会自动选择-->
<aop:aspectj-autoproxy proxy-target-class="true"/> 

加上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注解方式实现全局日志管理方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

您可能感兴趣的文章:

  • spring中AOP 注解开发示例详解
  • Spring AOP 自定义注解的实现代码
  • 使用Spring的注解方式实现AOP实例
  • 关于spring中aop的注解实现方法实例详解
  • spring自定义注解实现拦截器的实现方法
  • springMVC自定义注解,用AOP来实现日志记录的方法
  • spring AOP自定义注解方式实现日志管理的实例讲解
(0)

相关推荐

  • Spring AOP 自定义注解的实现代码

    1.在Maven中加入以下以依赖: <!-- Spring AOP + AspectJ by shipengzhi --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>3.0.6.RELEASE</version> </dependency> <

  • spring中AOP 注解开发示例详解

    一.简介 AOP主要包含了通知.切点和连接点等术语,介绍如下: 通知(advice) 通知定义了切面是什么以及何时调用,何时调用包含以下几种 Before 在方法被调用之前调用通知 After 在方法完成之后调用通知,无论方法执行是否成功 After-returning 在方法成功执行之后调用通知 After-throwing 在方法抛出异常后调用通知 Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为 切点(PointCut) 通知定义了切面的什么和何时,切

  • spring自定义注解实现拦截器的实现方法

    类似用户权限的需求,有些操作需要登录,有些操作不需要,可以使用过滤器filter,但在此使用过滤器比较死板,如果用的话,就必须在配置文件里加上所有方法,而且 不好使用通配符.这里可以采用一种比较简单灵活的方式,是采用spring 的 methodInterceptor拦截器完成的,并且是基于注解的.大概是用法是这样的: @LoginRequired @RequestMapping(value = "/comment") public void comment(HttpServletRe

  • 使用Spring的注解方式实现AOP实例

    spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,aspectjweaver.jar,cglib-nodep.jar.然后我们写一个接口 package com.bird.service; public interface PersonServer { public void save(String name); public void update(S

  • springMVC自定义注解,用AOP来实现日志记录的方法

    需求背景 最近的一个项目,在项目基本完工的阶段,客户提出要将所有业务操作的日志记录到数据库中,并且要提取一些业务的关键信息(比如交易单号)体现在日志中. 为了保证工期,在查阅了资料以后,决定用AOP+自定义注解的方式来完成这个需求. 准备工作 自定义注解需要依赖的jar包有 aspectjrt-XXX.jar ,aspectjweaver-XXX.jar,XXX代表版本号. 自定义注解 在项目下单独建立了一个log包,来存放日志相关的内容 **.common.log.annotation //自

  • 关于spring中aop的注解实现方法实例详解

    前言 在之前的一篇文章中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了.话不多说,来一起看看详细的介绍: 注解方式实现aop我们主要分为如下几个步骤: 1.在切面类(为切点服务的类)前用@Aspect注释修饰,声明为一个切面类. 2.用@Pointcut注释声明一个切点,目的是为了告诉切面,谁是它的服务对象.(此注释修饰的方法的方法体为空,不需要写功能比如 public void say(){};就可以了,方法名可以被候命

  • spring AOP自定义注解方式实现日志管理的实例讲解

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

  • 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

  • 使用Aop的方式实现自动日志记录的方式详细介绍

    目录 34.使用Aop的方式实现自动日志记录 采用第一种方式: 1.第一步.定义一个注解: 2.第二步.编写一个切面 3.使用自定义注解 34.使用Aop的方式实现自动日志记录 自动日志记录的实现的两种方式: ①通过监听器去监听,当访问到具体的类方法,通过aop切面去获取访问的方法,然后将日志记录下来②通过拦截器,编写一个类去继承HandlerInterceptorAdapter,重写preHandle,postHandle,然后在里面进行日志记录,编写的类加到spring容器里 采用第一种方式

  • 详解SpringBoot AOP 拦截器(Aspect注解方式)

    常用用于实现拦截的有:Filter.HandlerInterceptor.MethodInterceptor 第一种Filter属于Servlet提供的,后两者是spring提供的,HandlerInterceptor属于Spring MVC项目提供的,用来拦截请求,在MethodInterceptor之前执行. 实现一个HandlerInterceptor可以实现接口HandlerInterceptor,也可以继承HandlerInterceptorAdapter类,两种方法一样.这个不在本文

  • Spring Aop之AspectJ注解配置实现日志管理的方法

    最近项目要做一个日志功能,我用Spring Aop的注解方式来实现. 创建日志注解 package com.wyj.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lan

  • SpringBoot使用AOP统一日志管理的方法详解

    目录 前言 实现 1.引入依赖 2.定义logback配置 3.编写切面类 4.测试 前言 请问今天您便秘了吗?程序员坐久了真的会便秘哦,如果偶然点进了这篇小干货,就麻烦您喝杯水然后去趟厕所一边用左手托起对准嘘嘘,一边用右手滑动手机看完本篇吧. 实现 本篇AOP统一日志管理写法来源于国外知名开源框架JHipster的AOP日志管理方式 1.引入依赖 <!-- spring aop --> <dependency> <groupId>org.springframework

  • SpringBoot中使用AOP打印接口日志的方法

    前言 AOP 是 Aspect Oriented Program (面向切面)的编程的缩写.他是和面向对象编程相对的一个概念.在面向对象的编程中,我们倾向于采用封装.继承.多态等概念,将一个个的功能在对象中来实现.但是,我们在实际情况中也发现,会有另外一种需求就是一类功能在很多对象的很多方法中都有需要.例如有一些对数据库访问的方法有事务管理的需求,有很多方法中要求打印日志.按照面向对象的方式,那么这些相同的功能要在很多地方来实现或者在很多地方来调用.这就非常繁琐并且和这些和业务不相关的需求耦合太

  • Spring AOP使用@Aspect注解 面向切面实现日志横切的操作

    引言: AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型. 利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率. 在Spring AOP中业务逻辑仅仅只关注业务本身,将日志记录,性能统计,安全控制,事务处理,异

  • java通过AOP实现全局日志打印详解

    目录 几个常用的切点注解,这次使用了@Before和@Around 切Controller打印请求的接口.参数.返回值以及耗时情况. 切Service打印日志,URL,请求方式,IP,类名,方法 总结 几个常用的切点注解,这次使用了@Before和@Around 1.@Before 前置增强(目标方法执行之前,执行注解标注的内容) 2.@AfterReturning 后置增强(目标方法正常执行完毕后,执行) 3.@Around 环绕增强(目标方法执行前后,分别执行一些代码) 4.@AfterTh

随机推荐