自定义注解
定义使用在方法上的注解:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
String value() default "";
String converseMark() default "defaultConverseMark";
/**
* 是否启用
*
* @return
*/
boolean enable() default true;
LogActionType type() default LogActionType.SELECT;
}
配置切面,只要添加了日志注解的接口都会被切到
/**
* @author lyp
*/
@Component
@Aspect
@Slf4j
public class LogAspectMongo {
private final LogServiceImpl logService;
ThreadLocal<Long> currentTime = new ThreadLocal<>();
public LogAspectMongo(LogServiceImpl logService) {
this.logService = logService;
}
/**
* 配置切入点
*/
@Pointcut("@annotation(com.ebaiyihui.log.annotation.Log)")
public void logPointcut() {
// 该方法无方法体,主要为了让同类中其他方法使用此切入点
}
/**
* 配置环绕通知,使用在方法logPointcut()上注册的切入点
*
* @param joinPoint join point for advice
*/
@Around("logPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
Object result;
currentTime.set(System.currentTimeMillis());
result = joinPoint.proceed();
String resParam = postHandle(result);
Log log = new Log("INFO",System.currentTimeMillis() - currentTime.get());
currentTime.remove();
HttpServletRequest httpServletRequest = RequestHolder.getHttpServletRequest();
logService.saveMongo(httpServletRequest,resParam,joinPoint,log);
return result;
}
/**
* 配置异常通知
*
* @param joinPoint join point for advice
* @param e exception
*/
@AfterThrowing(pointcut = "logPointcut()", throwing = "e")
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
log.info("========错误信息======>{}", ThrowableUtil.getStackTrace(e));
Log log = new Log("ERROR",System.currentTimeMillis() - currentTime.get());
currentTime.remove();
log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes());
HttpServletRequest request = RequestHolder.getHttpServletRequest();
String userViewId=request.getHeader("userId");
String appCode = request.getHeader("appCode");
String resParam = "接口异常";
logService.save(appCode,resParam,userViewId, StringUtil.getBrowser(request), IpAddressUtil.getIpAddr(request), (ProceedingJoinPoint)joinPoint, log);
}
private String postHandle(Object retVal) {
if(null == retVal){
return "";
}
return JSON.toJSONString(retVal);
}
}
/**
* @ClassName LogService
* @description: 记录操作日志
* @author: liyp
* @create: 2020-08-0711:54
**/
@Service
@Slf4j
public class LogServiceImpl {
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private Map<String, ResolveParameter> resolveParameterMap;
//异步线程池
public void saveMongo(HttpServletRequest httpServletRequest,String resParam, ProceedingJoinPoint joinPoint, Log adminLog) {
simpleExecutorService.execute(() -> {
try {
log.info("进入纪录日志service");
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
com.ebaiyihui.log.annotation.Log aopLog = method.getAnnotation(com.ebaiyihui.log.annotation.Log.class);
String logActionType = aopLog.type().getDisplay();
// 方法路径
String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
StringBuilder params = new StringBuilder("{");
//参数值
List<Object> argValues = new ArrayList<>(Arrays.asList(joinPoint.getArgs()));
String reqParam = JSON.toJSONString(joinPoint.getArgs());
log.info("reqParam = {}",reqParam);
//参数名称
for (Object argValue : argValues) {
params.append(argValue).append(" ");
}
log.info(" params = {}",params);
String converseMark = aopLog.converseMark();
// 描述
if (adminLog != null) {
adminLog.setDescription(aopLog.value());
}
adminLog.setAppCode(httpServletRequest.getHeader("appCode"));
adminLog.setRequestIp(IpAddressUtil.getIpAddr(httpServletRequest));
adminLog.setMethod(methodName);
adminLog.setUserId(httpServletRequest.getHeader("userId"));
// adminLog.setReqParams(params.toString() + " }");
adminLog.setReqParams(reqParam);
adminLog.setResParams(resParam);
adminLog.setBrowser(StringUtil.getBrowser(httpServletRequest));
adminLog.setLogActionType(logActionType);
adminLog.setResParams(resParam);
adminLog.setCreateTime(new Timestamp(System.currentTimeMillis()));
log.info("接口解析方法入参:{}",JSON.toJSONString(adminLog));
LogReqVo logReqVo = new LogReqVo();
logReqVo.setReqParam(reqParam);
logReqVo.setResParam(resParam);
LogResVo logResVo = new LogResVo();
ResolveParameter resolveParameter = resolveParameterMap.get(converseMark);
if (Objects.isNull(resolveParameter)){
DefaultResolveParameter defaultResolveParameter = new DefaultResolveParameter();
logResVo = defaultResolveParameter.resolveParas(logReqVo);
adminLog.setOperationDescription(logResVo.getOperationDescription());
log.info("默认接口解析返回值:{}",JSON.toJSONString(logResVo));
}else{
logResVo = resolveParameter.resolveParas(logReqVo);
adminLog.setOperationDescription(logResVo.getOperationDescription());
log.info("接口解析后返回值:{}",JSON.toJSONString(logResVo));
}
log.info("存入mongo参数:{}",JSON.toJSONString(adminLog));
mongoTemplate.save(adminLog);
}catch (Exception e){
e.printStackTrace();
}
});
}
}
给方法上添加注解:
@Log(value = "就诊卡-绑定就诊卡",converseMark = "hybindListCard",type = LogActionType.UPDATE)
public BaseResponse<List<CardDetailsInfoRespVO>> hybindListCard(@RequestBody RegisterCardReqVO reqVO) {
MdcUtil.setCallerUserMethod(reqVO.getChannelCode(), reqVO.getCredNo(), "航天中心医院绑定卡集合");
return cardService.hybindListCard(reqVO);
}
/**
* @ClassName RegisterOrBindCardParse
* @description: 注册或绑定就诊卡解析
* @author: liyp
* @create: 2020-10-2016:32
**/
@Component("registerOrBindCard")
@Slf4j
public class RegisterOrBindCardParse implements ResolveParameter {
@Override
public LogResVo resolveParas(LogReqVo logReqVo) {
String reqParam = "";
if(null != logReqVo){
reqParam = logReqVo.getReqParam();
StringBuilder stringBuilder = new StringBuilder(reqParam);
reqParam = stringBuilder.substring(1, stringBuilder.length() - 1).toString();
}
log.info("绑定就诊卡参数解析入参:{}",reqParam);
RegisterCardReqVO registerCardReqVO = JSON.parseObject(reqParam, RegisterCardReqVO.class);
LogResVo logResVo = new LogResVo();
logResVo.setOperationDescription("新增就诊卡:".concat(registerCardReqVO.getPatientName()));
log.info("logResVo = {}",JSON.toJSONString(logResVo));
return logResVo;
}