項目應用:使用自定義註解完成對controller的aop控制

在項目進行過程中,需要使用aop對api傳入或者傳出數據進行日誌記錄。考慮實際應用,放棄了使用攔截器,轉而使用aop的前置通知和返回通知中加入日誌記錄操作。

在spring中,controller會被JDK自動代理。當使用自定義標籤時controller已經實例化不會在通過aop,因此需要走cglib代理。

xml配置:

<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:task="http://www.springframework.org/schema/task"
<span style="color:#FF6666;">    <!-- 啓動對@AspectJ註解的支持 -->  
    <aop:aspectj-autoproxy/>  
    
    <!--通知spring使用cglib而不是jdk的來生成代理方法 AOP可以攔截到Controller--> 
    <aop:aspectj-autoproxy proxy-target-class="true" />  </span><span style="color:#FF6666;">       xmlns:aop="http://www.springframework.org/schema/aop"</span>
       xsi:schemaLocation="http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/task
        http://www.springframework.org/schema/task/spring-task.xsd
<span style="color:#FF6666;">        http://www.springframework.org/schema/aop   
        http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

    <!-- 啓動對@AspectJ註解的支持 -->  
    <aop:aspectj-autoproxy/>  
    
    <!--通知spring使用cglib而不是jdk的來生成代理方法 AOP可以攔截到Controller-->  
    <aop:aspectj-autoproxy proxy-target-class="true" />  

</span>

自定義標籤:

package com.xiaoma.universe.video.aspect;

import java.lang.annotation.*;

@Target({ElementType.PARAMETER, ElementType.METHOD})  
@Retention(RetentionPolicy.RUNTIME)  
@Documented  
public @interface ControllerLog {
    
    String description() default "";//自定義標籤屬性

}

實現aspect:

package com.xiaoma.universe.video.aspect;  

import java.lang.reflect.Method;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
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;

@Aspect  
@Component  
public  class LogAspect {  

	//本地異常日誌記錄對象  
	private  static  final Logger logger = LoggerFactory.getLogger(LogAspect.class);  
	
	//Controller層切點  
	@Pointcut("@annotation(com.xiaoma.universe.video.aspect.ControllerLog)")
	public  void controllerAspect() {  
	}  

	/** 
	 * 前置通知 用於攔截Controller層記錄用戶的操作 
	 * 
	 * @param joinPoint 切點 
	 */  
	@Before("controllerAspect()")  
	public  void doBefore(JoinPoint joinPoint) {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
		System.out.println("請求"+request.getCharacterEncoding());
	}  


	/** 
	 * 獲取註解中對方法的描述信息 用於Controller層註解 
	 * 
	 * @param joinPoint 切點 
	 * @return 方法描述 
	 * @throws Exception 
	 */  
	public  static String getControllerMethodDescription(JoinPoint joinPoint)  throws Exception {  
 		Class<?> clazz = joinPoint.getTarget().getClass();
		String name = joinPoint.getSignature().getName();
		Object[] parameterTypes = joinPoint.getArgs();
		for (Method method : clazz.getDeclaredMethods()) {
			if (method.getName().equals(name) && method.getParameterTypes().length == parameterTypes.length) {
				ControllerLog methodLog = method.getAnnotation(ControllerLog. class);
				if (methodLog != null) {
					return methodLog.description();
				}
				break;
			}
		}
		return "";		 
	}  
}  
在controller中使用:

	@RequestMapping( method=RequestMethod.GET)
	@ResponseBody
	@ControllerLog(description="123")
	public JSONObject list(HttpServletRequest request, HttpServletResponse response ,VideoCourses videoCourses, BaseModel model ,@TokenUser UserInfo user,String channel,String queryType)
	{
            return null;
        }


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章