由于本项目使用的是spring boot,内部自动集成spring相关配置,这里就不在使用注入xml方式进行讨论,只针对于本项目。
AOP是面向切面编程思想,就本项目来说,目前作用最大的是,对接口出参和入参的数据进行打印并保存,这里就运用到了AOP
先声明AOP切点标识以及说明
然后定义Aspect这里找度娘一大把,核心是定义切面 @Pointcut("@annotation(com.epbox.lite.cloud.annotation.SysLog)")
有些什么抛异常执行 或者执行方法前执行或者 返回前执行,这里就不在说明,这里只说明环绕执行,包含了方法前和后
@Pointcut("@annotation(com.epbox.lite.cloud.annotation.SysLog)") public void webLog(){} @AfterReturning(returning = "ret", pointcut = "webLog()") public void doAfterReturning(JoinPoint joinPoint, Object ret){ } @AfterThrowing(pointcut = "webLog()") public void throwss(JoinPoint joinPoint){ } //环绕通知,环绕增强,相当于MethodInterceptor @Around("webLog()") public Object arround(ProceedingJoinPoint pjp) { Object returnObj = null; SystemLog systemLog = new SystemLog(); String id = null; Object oldObj = null; try{ ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //获取注解信息 SysLog sysLog = ((MethodSignature)pjp.getSignature()).getMethod().getAnnotation(SysLog.class); Integer accountId = AccountUtils.getAccountIdFromRequest(request); systemLog.setOperateBy(Long.valueOf(accountId)); if(sysLog.operateModule()!= null){ systemLog.setOperateModule(sysLog.operateModule().getCode()); } if(sysLog.actionType() != null){ systemLog.setActionType(Byte.valueOf(sysLog.actionType().getCode())); } if(sysLog.logType()!= null ){ systemLog.setLogType(Byte.valueOf(sysLog.logType().getCode())); } if(sysLog.desc() != null && sysLog.desc() != ""){ systemLog.setRemark(sysLog.desc()); } String remoteAddr = NetworkUtil.getIpAddress(request); systemLog.setIp(remoteAddr); systemLog.setPath(request.getRequestURI()); systemLog.setInputParams(JSON.toJSONString(pjp.getArgs())); String interfaceName = pjp.getSignature().getDeclaringTypeName(); String sipin = interfaceName.substring(interfaceName.lastIndexOf(".")); systemLog.setInterfaceName(interfaceName + "." + pjp.getSignature().getName()); systemLog.setActionType(Byte.valueOf(sysLog.actionType().getCode())); if(ActionEnum.ADD.equals(sysLog.actionType()) || ActionEnum.UPDATE.equals(sysLog.actionType())){ //insert or update Object obj = getParamObject(pjp); try{ id = PropertyUtils.getProperty(obj,"id").toString(); }catch (Exception e){ //ignore logger.error("==>获取id失败[exception:{}]",e); } if(id == null){ List<ChangeField> changeFields = DiffUtil.getInsertChangeItems(obj); String jsonStr = JSON.toJSONString(changeFields); systemLog.setChanges(jsonStr); systemLog.setObjectClass(obj.getClass().getSimpleName()); }else{ try { systemLog.setObjectId(String.valueOf(id)); Object oldObjTemp = DiffUtil.getObjectById(pjp.getTarget(),id); if(sipin.endsWith("Controller")){ ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)oldObjTemp; oldObj = rs.getBody().getResult(); }else { oldObj = oldObjTemp; } systemLog.setObjectClass(oldObj.getClass().getSimpleName()); } catch (Exception e) { //ignore logger.error("==>获取修改前的值失败[exception:{}]",e); } } }else if(ActionEnum.DELETE.equals(sysLog.actionType())){ //设置删除变更内容 try { if(getParamObject(pjp) != null){ id =getParamObject(pjp).toString(); } Object oldObjTemp = DiffUtil.getObjectById(pjp.getTarget(),id); if(sipin.endsWith("Controller")){ ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)oldObjTemp; oldObj = rs.getBody().getResult(); }else { oldObj = oldObjTemp; } ChangeField changeItem = DiffUtil.getDeleteChangeItem(oldObj); systemLog.setChanges(JSON.toJSONString(changeItem)); systemLog.setObjectId(pjp.getArgs()[0].toString()); systemLog.setObjectClass(oldObj.getClass().getSimpleName()); } catch (Exception e) { //ignore logger.error("==>设置删除变更内容失败[exception:{}]",e); } } //执行返回结果 boolean flag = false; try { returnObj = pjp.proceed(pjp.getArgs()); flag = true; } catch (Throwable throwable) { logger.error("==>执行方法异常[exception:{}]",throwable); } if(flag){ try { String jsonStr = JSON.toJSONString(returnObj); JSONObject object = JSON.parseObject(jsonStr); if(object != null && StringUtils.isNotBlank(object.getString("status"))){ if(Constant.FAIL.equals(object.getString("status"))) { systemLog.setOperateState(Byte.valueOf("0")); }else if(Constant.SUCCESS.equals(object.getString("status"))){ systemLog.setOperateState(Byte.valueOf("1")); } }else { systemLog.setOperateState(Byte.valueOf("1")); } } catch (Exception e) { //ignore logger.error("==>设置操作操作状态失败[exception:{}]",e); } if(ActionEnum.ADD.equals(sysLog.actionType())){ //new id Object newId = null; try { if(sipin.endsWith("Controller")){ ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)returnObj; newId = PropertyUtils.getProperty(rs.getBody().getResult(),"id"); }else { newId = PropertyUtils.getProperty(returnObj,"id"); } systemLog.setObjectId(String.valueOf(newId.toString())); } catch (Exception e) { //ignore logger.error("==>设置新增id失败[exception:{}]",e); } }else if(ActionEnum.UPDATE.equals(sysLog.actionType())){ Object newObj = null; try { Object newObjTemp = DiffUtil.getObjectById(pjp.getTarget(),id); if(sipin.endsWith("Controller")){ ResponseEntity<ResultBody> rs = (ResponseEntity<ResultBody>)newObjTemp; newObj = rs.getBody().getResult(); }else { newObj = newObjTemp; } List<ChangeField> changeItems = DiffUtil.getChangeItems(oldObj,newObj); systemLog.setChanges(JSON.toJSONString(changeItems)); } catch (Exception e) { //ignore logger.error("==>设置变更内容失败[exception:{}]",e); } } }else { systemLog.setOperateState(Byte.valueOf("0")); } systemLogService.create(systemLog); }catch (Exception e){ logger.error("==>系统日志错诶:{}",e); } return returnObj; }
/** * 获取参数 * @param pjp * @return */ private Object getParamObject(ProceedingJoinPoint pjp) { int paraLen = pjp.getArgs().length; Object obj = null; if(paraLen>0){ for(Object o:pjp.getArgs()){ obj = o; Class clazz = o.getClass(); if(clazz.equals(HttpServletRequest.class) || clazz.equals(HttpServletResponse.class)){ obj = null; continue; } return obj; } } return obj; }
在使用方面,只需要在使用的切点加入 下图所示即可