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数据库都有记录







评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值