1. 程式人生 > >spring aop實現(使用者操作記錄,一場記錄)

spring aop實現(使用者操作記錄,一場記錄)

第一步定義兩個註解:

Java程式碼 複製程式碼
package com.annotation;

import java.lang.annotation.*;

/**
*自定義註解 攔截Controller
*/

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemControllerLog {

String description() default "";  

}

package com.annotation;

import java.lang.annotation.*;

/**
*自定義註解 攔截service
*/

@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemServiceLog {

String description() default "";  

}
第二步建立一個切點類:

Java程式碼 複製程式碼
package com.annotation;

import com.model.Log;
import com.model.User;
import com.service.LogService;
import com.util.DateUtil;
import com.util.JSONUtil;
import com.util.SpringContextHolder;
import com.util.WebConstants;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
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 javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**

  • 切點類

  • @author tiangai

  • @since 2014-08-05 Pm 20:35

  • @version 1.0
    */
    @Aspect
    @Component
    public class SystemLogAspect {
    //注入Service用於把日誌儲存資料庫
    @Resource
    private LogService logService;
    //本地異常日誌記錄物件
    private static final Logger logger = LoggerFactory.getLogger(SystemLogAspect.class);

    //Service層切點
    @Pointcut("@annotation(com.annotation.SystemServiceLog)")
    public void serviceAspect() {
    }

    //Controller層切點
    @Pointcut("@annotation(com.annotation.SystemControllerLog)")
    public void controllerAspect() {
    }

    /**

    • 前置通知 用於攔截Controller層記錄使用者的操作

    • @param joinPoint 切點
      */
      @Before(“controllerAspect()”)
      public void doBefore(JoinPoint joinPoint) {

      HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
      HttpSession session = request.getSession();
      //讀取session中的使用者
      User user = (User) session.getAttribute(WebConstants.CURRENT_USER);
      //請求的IP
      String ip = request.getRemoteAddr();
      try {
      //控制檯輸出=//
      System.out.println("=前置通知開始=");
      System.out.println(“請求方法:” + (joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
      System.out.println(“方法描述:” + getControllerMethodDescription(joinPoint));
      System.out.println(“請求人:” + user.getName());
      System.out.println(“請求IP:” + ip);
      //資料庫日誌=//
      Log log = SpringContextHolder.getBean(“logxx”);
      log.setDescription(getControllerMethodDescription(joinPoint));
      log.setMethod((joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
      log.setType(“0”);
      log.setRequestIp(ip);
      log.setExceptionCode(null);
      log.setExceptionDetail(null);
      log.setParams(null);
      log.setCreateBy(user);
      log.setCreateDate(DateUtil.getCurrentDate());
      //儲存資料庫
      logService.add(log);
      System.out.println("=前置通知結束=");
      } catch (Exception e) {
      //記錄本地異常日誌
      logger.error(“前置通知異常”);
      logger.error(“異常資訊:{}”, e.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中的使用者
      User user = (User) session.getAttribute(WebConstants.CURRENT_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 += JSONUtil.toJsonString(joinPoint.getArgs()[i]) + “;”;
      }
      }
      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(“請求人:” + user.getName());
      System.out.println(“請求IP:” + ip);
      System.out.println(“請求引數:” + params);
      /
      ==資料庫日誌=/
      Log log = SpringContextHolder.getBean(“logxx”);
      log.setDescription(getServiceMthodDescription(joinPoint));
      log.setExceptionCode(e.getClass().getName());
      log.setType(“1”);
      log.setExceptionDetail(e.getMessage());
      log.setMethod((joinPoint.getTarget().getClass().getName() + “.” + joinPoint.getSignature().getName() + “()”));
      log.setParams(params);
      log.setCreateBy(user);
      log.setCreateDate(DateUtil.getCurrentDate());
      log.setRequestIp(ip);
      //儲存資料庫
      logService.add(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);

    }

    /**

    • 獲取註解中對方法的描述資訊 用於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(SystemServiceLog.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(SystemControllerLog.class).description();
      break;
      }
      }
      }
      return description;
      }
      }
      第三步把Controller的代理權交給cglib

在例項化ApplicationContext的時候需要加上

Xml程式碼 複製程式碼

aop:aspectj-autoproxy/
在呼叫Controller的時候AOP發揮作用所以在SpringMVC的配置檔案里加上

Xml程式碼 複製程式碼