import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import JAVAx.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 統一日志處理切面
*/
@Aspect
@Component
@Order(1)//定義Spring容器加載bean的順序
public class WebLogAspect {
//定義切點表達式,指定通知功能被應用的范圍
@Pointcut("execution(public * com.xxmfl.mp.sichao.controller.*.*(..))")
public void webLog() {
}
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
}
/**value切入點位置
* returning 自定義的變量,標識目標方法的返回值,自定義變量名必須和通知方法的形參一樣
* 特點:在目標方法之后執行的,能夠獲取到目標方法的返回值,可以根據這個返回值做不同的處理
*/
@AfterReturning(value = "webLog()", returning = "ret")
public void doAfterReturning(Object ret) throws Throwable {
}
//通知包裹了目標方法,在目標方法調用之前和之后執行自定義的行為
//ProceedingJoinPoint切入點可以獲取切入點方法上的名字、參數、注解和對象
@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable
{
long startTime = System.currentTimeMillis();
//獲取當前請求對象
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
//前面是前置通知,后面是后置通知
Object result = joinPoint.proceed();
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
long endTime = System.currentTimeMillis();
System.out.println(request.getMethod()); //請求方式
System.out.println(getParameter(method, joinPoint.getArgs())); //請求參數
System.out.println(result);//返回結果
System.out.println((int) (endTime - startTime)); //響應時間
System.out.println(request.getRequestURL().toString());//請求路徑
//存入數據庫記錄
return result;
}
/**
* 根據方法和傳入的參數獲取請求參數
*/
private Object getParameter(Method method, Object[] args)
{
List<Object> argList = new ArrayList<>();
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
//將RequestBody注解修飾的參數作為請求參數
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
if (requestBody != null) {
argList.add(args[i]);
}
//將RequestParam注解修飾的參數作為請求參數
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
if (requestParam != null) {
Map<String, Object> map = new HashMap<>();
String key = parameters[i].getName();
if (!StringUtils.isEmpty(requestParam.value())) {
key = requestParam.value();
}
map.put(key, args[i]);
argList.add(map);
}
}
if (argList.size() == 0) {
return null;
} else if (argList.size() == 1) {
return argList.get(0);
} else {
return argList;
}
}
}