springboot項目中使用注解的方式實現
首先:編寫一個對於操作方法進行日志記錄的注解
package com.springtest.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogAnnonation {
/**
* 操作類型,方便記錄
* @return String
*/
String value() default "";
}
然后,注解的切面配置
這里采用了兩中切面通知:
分別是返回通知和異常通知,注解中的參數方便在返回通知或者異常通知中處理操作類型(方法做了什么操作)
返回通知是方法正常執行時候會進入的通知方法,可以通過對方法返回值的信息判斷方法執行結果是或否成功
異常通知是方法執行產生異常進入的方法
@Aspect @Component public class LogInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(OperationLogInterceptor.class); /** * 定義切入點為 帶有 LogAnnonation 注解的 */ @Pointcut("@annotation(com.trendytech.tapp.annotation.LogAnnonation)") private void param() { } /** * 返回通知(正常返回) */ @AfterReturning(value = "param()", returning = "result") public void afterReturning(JoinPoint joinPoint, ResponseData result) throws Throwable { String operationResult = "失敗"; if (result.getCode() == ResponseCode.SUCCESS) { operationResult = "成功"; } dealDifferentLogs(joinPoint, operationResult); } /** * 異常通知(失敗操作) */ @AfterThrowing(value = "param()", throwing = "exception") public void afterThrowing(JoinPoint joinPoint, Exception exception) throws Throwable { dealDifferentLogs(joinPoint, "失敗"); LOGGER.error("OperationLogInterceptor afterThrowing exception catch ...", exception); } }
如何使用
舉個栗子:
只需要在操作的方法上面加上方法的注解和注解攜帶的參數值即可
@OperationLog("MODIFY_VIRTUAL") @RequestMapping(value = "/{id}", method = RequestMethod.PUT) public ResponseData<VirtualVo> modifyVirtualServer(@PathVariable("id") String id, @RequestBody VirtualVo virtualServer) { return virtualServerService.modify(id, virtualServer); }
備注:使用這種方式手機日志還需要支持一個方法,從注解中取得注解value從而判斷這個方法的操作類型是什么,方法如下
獲取注解定義的參數----就是上面代碼中的
@OperationLog("MODIFY_VIRTUAL")
/** * 獲取自定義注解的參數 * * @param joinPoint joinPoint * @return LogAnnotation 注解 * @throws ClassNotFoundException ClassNotFoundException */ public LogAnnotation getAnnotationParam(JoinPoint joinPoint) throws ClassNotFoundException { String targetName = joinPoint.getTarget().getClass().getName(); String methodName = joinPoint.getSignature().getName(); Class targetClass = Class.forName(targetName); Method[] methods = targetClass.getMethods(); for (Method method : methods) { if (method.getName().equals(methodName)) { return method.getAnnotation(OperationLog.class); } } return null; }
獲取注解方法中某個參數的值
/** * 通過反射機制 獲取被切參數名以及參數值 * * @param joinPoint joinPoint * @return 參數集合 * @throws NotFoundException NotFoundException * @throws ClassNotFoundException ClassNotFoundException */ public static Map<String, Object> getMethodParams(JoinPoint joinPoint) throws NotFoundException, ClassNotFoundException { //參數名稱 String[] paramName = ((CodeSignature) joinPoint.getSignature()).getParameterNames(); //參數值 Object[] paramValue = joinPoint.getArgs(); Map<String, Object> map = new HashMap<>(); for (int i = 0; i < paramName.length; i++) { try { map.put(paramName[i], paramValue[i]); } catch (Exception e) { LOGGER.error("get method params error!", e); } } return map; }
備注:使用方法為
getMethodParams(joinPoint).get(id); 獲取方法中的id參數的值
個人總結 如果不正確或者不理解之處歡迎留言指出