日志实体
@Data
public class ServiceLog implements Serializable {
/**
* 创建时间
*/
private String createTime;
/**
* 方法名
*/
private String method;
/**
* 参数
*/
private String params;
/**
* 日志描述
*/
private String description;
/**
* 方法运行时间
*/
private Long runTime;
/**
* 方法返回值
*/
private String response;
}
注解类:
@Documented
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceInvoker {
/**
* 方法描述,可使用占位符获取参数:{{tel}}
*/
String service() default "";
}
aop类:
@Slf4j
@Aspect
@Component
public class ServiceInvokerLog {
/**
* 环绕增强,相当于MethodInterceptor
*/
@Around(value = "@annotation(com.htsc.kh.extend.annotation.ServiceInvoker)")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result = null;
long time = System.currentTimeMillis();
try {
result = joinPoint.proceed();
time = System.currentTimeMillis() - time;
return result;
} finally {
try {
//方法执行完成后增加日志
addOperationLog(joinPoint, result, time);
} catch (Exception e) {
throw e;
}
}
}
private void addOperationLog(JoinPoint joinPoint, Object res, long time) {
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
ServiceLog operationLog = new ServiceLog();
operationLog.setRunTime(time);
operationLog.setResponse(JSON.toJSONString(res));
operationLog.setParams(JSON.toJSONString(joinPoint.getArgs()));
operationLog.setCreateTime(Util.formatDetailDate2(new Date()));
operationLog.setMethod(signature.getDeclaringTypeName() + "." + signature.getName());
ServiceInvoker annotation = signature.getMethod().getAnnotation(ServiceInvoker.class);
if (annotation != null) {
operationLog.setDescription(getDetail(((MethodSignature) joinPoint.getSignature()).getParameterNames(), joinPoint.getArgs(), annotation));
}
//TODO 这里保存日志
log.warn("【"+operationLog+"】");
}
/**
* 对当前登录用户和占位符处理
*
* @param argNames 方法参数名称数组
* @param args 方法参数数组
* @param annotation 注解信息
* @return 返回处理后的描述
*/
private String getDetail(String[] argNames, Object[] args, ServiceInvoker annotation) {
Map<Object, Object> map = new HashMap<>(4);
for (int i = 0; i < argNames.length; i++) {
map.put(argNames[i], args[i]);
}
String detail = annotation.service();
try {
detail = "'" + "MethodName" + "'===>" + annotation.service();
for (Map.Entry<Object, Object> entry : map.entrySet()) {
Object k = entry.getKey();
Object v = entry.getValue();
detail = detail.replace("{{" + k + "}}", JSON.toJSONString(v));
}
} catch (Exception e) {
throw e;
}
return detail;
}
}
实现效果:
2019-09-24 16:03:40,093 [ WARN] c.h.k.e.annotation.ServiceInvokerLog - 【ServiceLog(createTime=2020-09-24 16:03:40, method=com.hanwe.aop.InvokerService.register, params=[{"cId":"*******************","clientIp":"127.0.0.1"}], description='MethodName'===>register, runTime=39, response={"code":-500,"message":"'cid' field is illegal"})】
提示:如果是类中方法中的方法,需要单独把这个子方法拿出来建一个通用的类来管理他们。