java环绕通知实现日志记录

编程入门 行业动态 更新时间:2024-10-10 13:22:20

java环绕<a href=https://www.elefans.com/category/jswz/34/1771097.html style=通知实现日志记录"/>

java环绕通知实现日志记录

 第一步:定义接收的实体类

@Data
public class InterfaceLogDTO implements Serializable {/*** 日志ID*/@Id@Column(name = "log_id")private String logId;/*** 接口名称*/@Column(name = "service_name")private String serviceName;/*** 传输类型(RECEIVE:接收,SEND:发送)*/@Column(name = "type")private String type;/*** 状态(0:成功,!0:失败)*/@Column(name = "status")private String status;/*** 返回状态信息*/@Column(name = "message")private String message;/*** 操作用户*/@Column(name = "user_code")private String userCode;/*** 完成时间*/@Column(name = "finish_date")private Date finishDate;/*** 目标系统*/@Column(name = "target_sys")private String targetSys;/*** 请求地址*/@Column(name = "url")private String url;/*** 传输内容*/@Column(name = "service_info")private String serviceInfo;/*** 返回信息*/@Column(name = "return_info")private String returnInfo;/*** 报错信息*/@Column(name = "error_info")private String errorInfo;/*** 创建时间开始*/@Column(name = "creationDateBegin")private Date creationDateBegin;/*** 创建时间结束*/@Column(name = "creationDateEnd")private Date creationDateEnd;/*** 操作的页面名称*/@Column(name = "operate_page_name")private String operatePageName;/*** 访问操作页面的路径*/@Column(name = "operate_page_path")private String operatePagePath;
}

 第二步:定义所需要自己设置的字段(以下只是根据我的业务所设置的)


@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiLog {/*** 传输类型(RECEIVE:接收,SEND:发送)*/String type() default "RECEIVE";/*** 目标系统*/String targetSys() default "";String throwing() default "";

 第三步:获取日志记录所需字段的代码


@Aspect
@Slf4j
@Component
public class ApiLogAop {@AutowiredApiLogMapper apiLogMapper;@Value("${insertReturnInfo.enable}")private boolean insertReturnInfo;String logId = null;/*** 环绕通知* 1.在目标接口调用的过程中,记录其接口名称,传输类型(手动指定,默认receive),状态,返回状态信息,操作用户,目标系统(需手动指定),* 访问地址,传输内容,返回信息,报错信息,创建时间开始,创建时间结束。* @param pjp* @return* @throws Throwable*/@Around(value = "@annotation(cn.goldwind.ercp.ltc.service.sysConfig.ApiLog)")public Object apiLog(ProceedingJoinPoint pjp) throws Throwable {Object obj = null;//自定义的接收entiryInterfaceLogDTO interfaceLogDTO = new InterfaceLogDTO();// 设置请求参数(抽取方法定义在了下面)setServiceInfo(pjp, interfaceLogDTO);//创建开始时间interfaceLogDTO.setCreationDateBegin(new Date());// 获取注解信息MethodSignature signature = (MethodSignature) pjp.getSignature();ApiLog annotation = signature.getMethod().getAnnotation(ApiLog.class);if (null != annotation) {// 设置日志基础信息interfaceLogDTO.setLogId(UUIDKit.getUUID());//主键idinterfaceLogDTO.setServiceName(pjp.getSignature().getName());//接口名称interfaceLogDTO.setType(annotation.type());//传输类型interfaceLogDTO.setUserCode(request.getRemoteUser());//操作用户interfaceLogDTO.setTargetSys(annotation.targetSys());//目标系统interfaceLogDTO.setUrl(request.getRequestURL().toString());//访问地址//获取request对象ServletRequestAttributes attributes = (ServletRequestAttributes)                     RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();//获取session中的内容String pageRouter = request.getHeader("pageRouter");String pageRouterCH = request.getHeader("pageRouterCH");String realIp = getRealIp(request);//解码---统一编码后进行相关字段的存储if(null!=pageRouter && !pageRouter.isEmpty() && null!=pageRouterCH && !pageRouterCH.isEmpty()){//操作页面名称interfaceLogDTO.setOperatePageName(java.URLDecoder.decode(pageRouterCH,"UTF-8"));//访问的操作页面路径interfaceLogDTO.setOperatePagePath(realIp+java.URLDecoder.decode(pageRouter,"UTF-8"));}logId = interfaceLogDTO.getLogId();}try {// 具体业务方法obj = pjp.proceed();// 记录返回参数(抽取方法定义在了下面)setReturnInfo(obj, interfaceLogDTO,annotation.type());// 执行获取返回状态方法(抽取方法定义在了下面)executeCallback(obj, interfaceLogDTO);} catch (Exception e) {String errorMsg = e.getMessage();interfaceLogDTO.setErrorInfo(errorMsg);interfaceLogDTO.setStatus("1");interfaceLogDTO.setMessage(CommonConstants.ERROR_MESSAGE);throw new RuntimeException(e);} finally {try {interfaceLogDTO.setCreationDateEnd(new Date());// 保存日志操作apiLogMapper.createInterfaceLog(interfaceLogDTO);} catch (Exception e) {String errorMsg = e.getMessage();log.error(interfaceLogDTO.getServiceName() + "保存日志报错{}" + errorMsg);}}return obj;}public void setReturnInfo(Object obj, InterfaceLogDTO interfaceLogDTO,String type) {if (!ObjectUtils.isEmpty(obj)) {try {// 获取返回参数String paramJson = JSON.toJSONString(obj);JSONObject stakeholdersJson = JSONObject.parseObject(paramJson);//配置文件中设置开关,并且根据是否是查询操作以及响应是否成功,来判断是否需要存入响应数据信息if (!(CommonConstants.SUCCESS_MESSAGE.equals(stakeholdersJson.getString("message")) || "success".equals(stakeholdersJson.getString("message")))&& insertReturnInfo && !"select".equals(type)) {interfaceLogDTO.setReturnInfo(paramJson);}//第二个思路简单粗暴直接使用配置文件中的开关判断是否需要存入响应数据/*if (insertReturnInfo) {interfaceLogDTO.setReturnInfo(paramJson);}*/} catch (Exception e) {String errorMsg = e.getMessage();interfaceLogDTO.setServiceInfo("请求参数解析报错{}" + errorMsg);}}}// 执行获取返回状态方法public void executeCallback(Object obj, InterfaceLogDTO interfaceLogDTO) {try {String paramJson = JSON.toJSONString(obj);JSONObject stakeholdersJson = JSONObject.parseObject(paramJson);interfaceLogDTO.setStatus(stakeholdersJson.getString("code"));interfaceLogDTO.setMessage(stakeholdersJson.getString("message"));interfaceLogDTO.setErrorInfo(stakeholdersJson.getString("message"));if (CommonConstants.SUCCESS_MESSAGE.equals(stakeholdersJson.getString("message")) || "success".equals(stakeholdersJson.getString("message"))) {interfaceLogDTO.setFinishDate(new Date());}} catch (Exception e) {String errorMsg = e.getMessage();interfaceLogDTO.setErrorInfo("返回状态解析报错=>" + errorMsg);interfaceLogDTO.setStatus("1");interfaceLogDTO.setMessage(CommonConstants.ERROR_MESSAGE);}}public void setServiceInfo(ProceedingJoinPoint pjp, InterfaceLogDTO interfaceLogDTO) {try {// 获取请求参数Object[] args = pjp.getArgs();if (!ObjectUtils.isEmpty(args)) {String paramJson = JSON.toJSONString(args);interfaceLogDTO.setServiceInfo(paramJson);}} catch (Exception e) {String errorMsg = e.getMessage();interfaceLogDTO.setServiceInfo("请求参数解析报错{}" + errorMsg);}}/*** 异常通知,记录未被捕获的异常* @param joinPoint* @param throwing*/@AfterThrowing(value = "@annotation(cn.goldwind.ercp.ltc.service.sysConfig.ApiLog)", throwing = "throwing")public void error(JoinPoint joinPoint, Throwable throwing) {String errlogContent = "";try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {//将报错信息写入error字段throwing.printStackTrace(new PrintStream(byteArrayOutputStream));errlogContent = byteArrayOutputStream.toString();} catch (IOException e) {e.printStackTrace();}apiLogMapper.updateApiLog(logId, errlogContent);}}

第四步:把需要用到日志的接口注入进去就ok(举例)

@ApiLog( type="insert",targetSys = "test")//定义的日志记录
public ReturnEntity inputCrmAll() //要记录的接口

更多推荐

java环绕通知实现日志记录

本文发布于:2024-02-07 03:04:31,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1753164.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:通知   日志   java

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!