使用aop切面編寫日志模塊


我們先自定義一個注解(一個有關自定義注解的LJ文章 https://www.cnblogs.com/guomie/p/10824973.html

/**
*
* 自定義日志注解
* Retention(RetentionPolicy.RUNTIME) 生命周期永遠不會被丟棄
* Target(ElementType.METHOD) 作用於方法上
* Documented
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation {

   // 描述
   String actiondese() default "";

   //類型
   public enum Logtype {ADD,UPDATE,DEL,SET,LOGIN,LOGOUT,MESSAGE};

   Logtype actionvalue() default Logtype.ADD;
}

我們編寫一個切面類

@Aspect
@Component
public class LogAop {
@Autowired
private RedisService redisService;

@Autowired
private LogService logService;

// 切點
// @Pointcut("execution(* com.monitoring.controller..*.*(..))")
@Pointcut("@annotation(com.annotations.LogAnnotation)")
private void controllerAspect() {}

//增強
@Around("controllerAspect()")
public Object log(ProceedingJoinPoint pjp )throws Throwable{

    //先運行目標方法
Object object = pjp.proceed();

//獲取request
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();

// 攔截當前方法的對象
Object target = pjp.getTarget();
// 獲取正在攔截方法名稱
String methodName = pjp.getSignature().getName();
// 獲取方法的參數
Object[] args = pjp.getArgs();
// 獲取請求的路徑
// String requestURI = request.getRequestURI();

// 攔截的放參數類型
Signature sig = pjp.getSignature();
MethodSignature msig = null;
if (!(sig instanceof MethodSignature)) {
throw new IllegalArgumentException("該注解只能用於方法");
}
msig = (MethodSignature) sig;
Class[] parameterTypes = msig.getMethod().getParameterTypes();

Method method = null;
String actionType = "07";
String actionDesc = "";
try {

// 獲取當前方法
method = target.getClass().getMethod(methodName, parameterTypes);

} catch (NoSuchMethodException | SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}


if (null != method) {

// 獲取方法上的注解
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
if(null == annotation) {
return object;
}
// 獲取注解上的信息
actionDesc = annotation.actiondese();
// 獲取類型
Logtype actionvalue = annotation.actionvalue();

switch (actionvalue) {
case ADD:
actionType = "00";
break;
case UPDATE:
actionType = "01";
break;
case DEL:
actionType = "02";
break;
case SET:
actionType = "03";
break;
case LOGIN:
actionType = "04";
break;
case LOGOUT:
actionType = "05";
break;
case MESSAGE:
actionType = "06";
break;
default:
actionType = "07";
break;
}
}

// 獲取訪問真實IP
String internetIp = request.getHeader("x-forwarded-for");
if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
internetIp = request.getHeader("Proxy-Client-IP");
}
if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
internetIp = request.getHeader("WL-Proxy-Client-IP");
}
if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
internetIp = request.getRemoteAddr();
if (internetIp.equals("127.0.0.1") || internetIp.equals("0:0:0:0:0:0:0:1")) {
// 根據網卡取本機配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
internetIp = inet.getHostAddress();
}

}
//對於通過多個代理的情況,第一個IP為客戶端真實IP,多個IP按照','分割
if (internetIp != null && internetIp.length() > 15) { // "***.***.***.***".length() = 15
if (internetIp.indexOf(",") > 0) {
internetIp = internetIp.substring(0, internetIp.indexOf(","));
}
}

// 創建日志對象用於保存
BsUserLog4j log = new BsUserLog4j();
BsUserInfo user = JsonUtils.jsonToPojo(redisService.get(args[0].toString()), BsUserInfo.class) ;

//用戶登出
if(actionType == "04") {
//刪除緩存中的token值
redisService.del(args[0].toString());
System.out.println("已刪除緩存中token值");
}
//設置時間
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String actionTime=sdf.format(new Date());

// 設置log信息並保存數據庫
log.setLogId(new BigDecimal(IDUtils.genId()));
log.setUsername(user.getUsername());
log.setActionType(actionType);
log.setActionTime(actionTime);
log.setActionDesc(actionDesc);
log.setInternetIp(internetIp);

//添加日志到數據庫
logService.addLog(log);
System.out.println("添加日志: " + log.toString());

//最后返回目標方法
return object;
}
}

在配置里里面配置有關aop的配置

<beans   xmlns:aop="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" <beans>

<!-- 自動為@aspectJ切面bean創建代理,true表示使用CGLib來創建 -->
<aop:aspectj-autoproxy proxy-target-class="true" />

controller層代碼

@LogAnnotation(actiondese="用戶登錄",actionvalue=Logtype.LOGIN)
@RequestMapping("/loginTest")
@ResponseBody
public CarResult loginTest(HttpServletResponse response,HttpServletRequest request, String name,String pas,String phoneNumer){}

 其中還會遇到一些問題 

1. error at ::0 formal unbound in pointcut 

當出現這個錯誤的時候 表示你的通知方法得帶上參數 比如

 

但是 request 不能通過參數傳遞進來 只能通過下面方式來獲取

RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes =  (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();

2.目標方法不執行

  這時候我們需要先執行目標方法,然后再講目標方法通過返回值返回出去


免責聲明!

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



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