SpringMVC利用AOP實現自定義注解記錄日志


一.XML配置

SpringMVC如果要使用AOP注解,必須將放在spring-servlet.xml(配置MVC的XML)中
<!-- 啟用CGliB -->
<aop:aspectj-autoproxy proxy-target-class="true" />

二.自定義注解
@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SystemLogAnnotation {

  public String controller() default "";
  public String method() default "";

}

1. @Documented – 表示使用該注解的元素應被javadoc或類似工具文檔化,它應用於類型聲明,類型聲明的注解會影響客戶端對注解元素的使用。如果一個類型聲明添加了Documented注解,那么它的注解會成為被注解元素的公共API的一部分。

2. @Target – 表示支持注解的程序元素的種類,一些可能的值有TYPE, METHOD, CONSTRUCTOR, FIELD等等。如果Target元注解不存在,那么該注解就可以使用在任何程序元素之上。

3. @Inherited – 表示一個注解類型會被自動繼承,如果用戶在類聲明的時候查詢注解類型,同時類聲明中也沒有這個類型的注解,那么注解類型會自動查詢該類的父類,這個過程將會不停地重復,直到該類型的注解被找到為止,或是到達類結構的頂層(Object)。

4. @Retention – 表示注解類型保留時間的長短,它接收RetentionPolicy參數,可能的值有SOURCE(源文件中起作用), CLASS, 以及RUNTIME(保留到運行時起作用)。

三.建切面類
@Before – 目標方法執行前執行
@After – 目標方法執行后執行
@AfterReturning – 目標方法返回后執行,如果發生異常不執行
@AfterThrowing – 異常時執行
@Around – 在執行上面其他操作的同時也執行這個方法

這里記錄日志,選用@AfterReturning(pointcut切入點,指定目錄下所有方法)
@AfterReturning(pointcut="execution(* com.web.webapp.controller.*.*.*(..))")
public void afterManage(JoinPoint point) {
  SystemLogAnnotation systemlogAnnotation = null;
  try{
  systemlogAnnotation = this.getLogAnnotation(point);
  if (systemlogAnnotation == null) {
    return;
  }
  //請求參數
  Map<String, Object> map = getRequestParameterJson(request);
  String argsJson = JSON.toJSONString(map);
  //記錄日志(controller,method,description,url,args等等)
  OperationLog OperationLog = new OperationLog();
  OperationLog.setController(systemlogAnnotation.controller());
  OperationLog.setMethod(systemlogAnnotation.method());
  OperationLog.setRequestParameters(argsJson);
  //保存
  save(OperationLog)
  }catch(Exception e){
    logger.error("日志異常" , e);
  }
}

/**
*是否存在注解,如果存在就獲取
*/
private SystemLogAnnotation getLogAnnotation(JoinPoint joinPoint) throws Exception {
  SystemLogAnnotation obj = null;
  String targetName = joinPoint.getTarget().getClass().getName();
  String methodName = joinPoint.getSignature().getName();
  Object[] arguments = joinPoint.getArgs();
  Class targetClass = Class.forName(targetName);
  Method[] method = targetClass.getMethods();
  for (Method m : method) {
    if (m.getName().equals(methodName)) {
      Class[] tmpCs = m.getParameterTypes();
      if (tmpCs.length == arguments.length) {
        obj = m.getAnnotation(SystemLogAnnotation.class);
        break;
      }
    }
  }
  return obj;
}

/**
*對值過於長的參數進行過濾(視情況而定)
*/
private Map<String, Object> getRequestParameterJson(HttpServletRequest request) {
  Map<String, Object> map = new ConcurrentHashMap<String, Object>();
  map.putAll(request.getParameterMap());
  Iterator<String> keyIt = map.keySet().iterator();
  while (keyIt.hasNext()) {
    String key = keyIt.next();
    String[] value = (String[]) map.get(key);
    if (value != null) {
      String valueStr = Arrays.toString(value);
      if (valueStr.length() > 500) {
        keyIt.remove();
        map.remove(key);
      }
    }
  }
  return map;
}

四.測試類
@Controller
public class Controller {
  private static final Logger log = LoggerFactory.getLogger(Controller.class);
  @RequestMapping("/hello")
  //自定義注解,當方法上寫這個注解時,就會進入切面類中
  @SystemLogAnnotation(controller="testController",method="testMethod")
  public String sayHello() {
    log.info("HelloController sayHello:{}","hello world!");
    return "hello";
  }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM