自定义注解@Log 插入操作日志

news/2024/4/17 8:42:32

一,注解描述

// 作用位置,参数 方法
@Target({ElementType.PARAMETER, ElementType.METHOD})
// 作用范围 运行时
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log {/*** 模块*/public String title() default "";/*** 模块*/public String operType() default "";/*** 功能*/public BusinessType businessType() default BusinessType.OTHER;/*** 操作人类别*/public OperatorType operatorType() default OperatorType.MANAGE;/*** 是否保存请求的参数*/public boolean isSaveRequestData() default true;/*** 是否保存响应的参数*/public boolean isSaveResponseData() default true;
}
1,功能类型 
/*** 业务操作类型*/
public enum BusinessType {/*** 其它*/OTHER,/*** 新增*/INSERT,/*** 修改*/UPDATE,/*** 删除*/DELETE,/*** 授权*/ASSGIN,/*** 导出*/EXPORT,/*** 导入*/IMPORT,/*** 强退*/FORCE,/*** 更新状态*/STATUS,/*** 清空数据*/CLEAN,
}
 2,操作人类型
/*** 操作人类型*/
public enum OperatorType {/*** 其它*/OTHER,/*** 后台用户*/MANAGE,/*** 手机端用户*/MOBILE}

 二,日志切点

/*** 日志切点** @author jkwl* @date 2024-03-07*/
@Aspect
@Component
public class LogAspect {private static final Logger log = LoggerFactory.getLogger(LogAspect.class);@Autowiredprivate OperLogService operLogService;@Autowiredprivate UserInfoService userInfoService;/*** 处理完请求后执行** @param joinPoint 切点*/@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) {handleLog(joinPoint, controllerLog, null, jsonResult);}/*** 处理完请求后执行** @param joinPoint 切点*/@AfterThrowing(pointcut = "@annotation(controllerLog)", throwing = "e")public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) {handleLog(joinPoint, controllerLog, e, null);}
}
    /*** 新增操作日志数据** @param joinPoint     切点* @param controllerLog Log日志注解* @param e             异常* @param jsonResult    返回值*/protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) {try {// 获取request请求ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();assert attributes != null;HttpServletRequest request = attributes.getRequest();// *========数据库日志=========*//OperLog operLog = new OperLog();// 状态operLog.setStatus(BusinessStatus.SUCCESS.ordinal());// 请求的地址operLog.setOperIp(IpUtil.getIpAddress(request));// 请求URLoperLog.setOperUrl(request.getRequestURI());// 操作人员UserDetail user = userInfoService.getUserInfo(request);operLog.setOperName(user.getName());// 异常情况if (e != null) {operLog.setStatus(BusinessStatus.FAIL.ordinal());operLog.setErrorMsg(e.getMessage());}// 设置方法名称// 获取类名String className = joinPoint.getTarget().getClass().getName();// 获取方法名String methodName = joinPoint.getSignature().getName();// 设置类名 方法名operLog.setMethod(className + "." + methodName + "()");// 设置请求方式operLog.setRequestMethod(request.getMethod());// 处理设置注解上的参数getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);// 设置时间operLog.setOperTime(LocalDateTime.now());// 保存数据库operLogService.save(operLog);} catch (Exception exp) {// 记录本地异常日志log.error("==前置通知异常==");log.error("异常信息:{}", exp.getMessage());exp.printStackTrace();}}
    /*** 获取注解中对方法的描述信息 用于Controller层注解** @param joinPoint  切点* @param log        日志注解* @param operLog    操作日志对象* @param jsonResult 返回值* @throws Exception 异常*/public void getControllerMethodDescription(JoinPoint joinPoint, Log log, OperLog operLog, Object jsonResult) throws Exception {// 设置action动作operLog.setBusinessType(log.businessType().name());// 设置标题operLog.setTitle(log.title());// 设置操作类型operLog.setOperType(log.operType());// 设置操作人类别operLog.setOperatorType(log.operatorType().name());// 是否需要保存request,参数和值if (log.isSaveRequestData()) {// 获取参数的信息,传入到数据库中。setRequestValue(joinPoint, operLog);}// 是否需要保存response,参数和值if (log.isSaveResponseData() && !StringUtils.isEmpty(jsonResult)) {ErrorInfo errorInfo = JSON.parseObject(JSON.toJSONString(jsonResult), ErrorInfo.class);// 运单if (DataSourceEnum.ORDER.getName().equals(log.title())) {Order order = JSONObject.parseObject(errorInfo.getData().toString(), Order.class);operLog.setVehicleNo(order.getVehicleNo());// 运单装卸货确认if ("装卸货确认".equals(log.operType())) {operLog.setOperType(order.getType() == 1 ? "卸货确认" : "装货确认");}}// 车辆if (DataSourceEnum.VEHICLE.getName().equals(log.title())) {Vehicle vehicle = JSONObject.parseObject(errorInfo.getData().toString(), Vehicle.class);operLog.setVehicleNo(vehicle.getVehicleNo());// 车辆拉黑或拉白if ("拉黑或拉白".equals(log.operType())) {operLog.setOperType(vehicle.getIsLocked() == 1 ? "拉黑" : "拉白");}}String jsonString = JSON.toJSONString(jsonResult);operLog.setJsonResult(jsonString);}}
    /*** 获取请求的参数,放到log中** @param joinPoint 切点* @param operLog   操作日志* @throws Exception 异常*/private void setRequestValue(JoinPoint joinPoint, OperLog operLog) throws Exception {// 获取请求方法String requestMethod = operLog.getRequestMethod();// 新增或修改时if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) {String params = argsArrayToString(joinPoint.getArgs());// 设置请求参数operLog.setOperParam(params);}}
    /*** 参数拼装*/private String argsArrayToString(Object[] paramsArray) {String params = "";if (paramsArray != null && paramsArray.length > 0) {for (Object o : paramsArray) {if (!StringUtils.isEmpty(o) && !isFilterObject(o)) {try {Object jsonObj = JSON.toJSON(o);params += jsonObj.toString() + " ";} catch (Exception e) {}}}}return params.trim();}
    /*** 判断是否需要过滤的对象。** @param o 对象信息。* @return 如果是需要过滤的对象,则返回true;否则返回false。*/@SuppressWarnings("rawtypes")public boolean isFilterObject(final Object o) {Class<?> clazz = o.getClass();if (clazz.isArray()) {return clazz.getComponentType().isAssignableFrom(MultipartFile.class);} else if (Collection.class.isAssignableFrom(clazz)) {Collection collection = (Collection) o;for (Object value : collection) {return value instanceof MultipartFile;}} else if (Map.class.isAssignableFrom(clazz)) {Map map = (Map) o;for (Object value : map.entrySet()) {Map.Entry entry = (Map.Entry) value;return entry.getValue() instanceof MultipartFile;}}return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse|| o instanceof BindingResult;}

例:

    @Log(title = "运单", operType = "修改", businessType = BusinessType.UPDATE)@PostMapping("/updateOrder")public ErrorInfo updateOrder(HttpServletRequest request, OrderDto orderDto) {return orderService.updateOrder(userInfo, orderDto);}


https://www.xjx100.cn/news/3365571.html

相关文章

搜维尔科技:借助 ARVR 的力量缩小现代制造业的技能差距

借助ARVR的力量缩小现代制造业的技能差距 搜维尔科技&#xff1a;Senseglove案例-扩展机器人技术及其VR应用

mybatis批量新增数据

数据量大的时候如果在循环中执行单条新增操作&#xff0c;是非常慢的。那么如何在mybatis中实现批量新增数据呢&#xff1f; 方法 insert 标签的 foreach 属性可以用于批量插入数据。您可以使用 foreach 属性遍历一个集合&#xff0c;并为集合中的每个元素生成一条插入语句。…

朵米3.5客服系统源码2023正式版

源码简介 朵米客服系统是一款全功能的客户服务解决方案&#xff0c;提供多渠道支持&#xff08;如在线聊天、邮件、电话等&#xff09;&#xff0c;帮助企业建立与客户的实时互动。该系统具有智能分流功能&#xff0c;可以快速将客户请求分配给适当的客服人员&#xff0c;提高…

tomcat 知多少

Tomcat的缺省端口&#xff1a; 默认端口为8080&#xff0c;可以通过在tomcat安装包conf目录下&#xff0c;service.xml中的Connector元素的port属性来修改端口。 tomcat 常见 Connector 运行模式(优化)&#xff1a; 这三种模式的不同之处如下&#xff1a; BIO &#xff1a; 一…

练气第六天

问:ANR怎么分析&#xff1f; ANR问题&#xff0c;这其实是一个非常综合性的问题&#xff0c;因为anr会涉及CPU负载&#xff0c;内存空间大小&#xff0c;线程锁&#xff0c;GC回收&#xff0c;这里面每个点&#xff0c;都是非常考验我们基本功的。 分析ANR问题&#xff0c;需…

AtCoder Beginner Contest 347 (B,C,D,E)

B - Substring (atcoder.jp) 问题陈述 您将得到一个由小写英文字母组成的字符串 S 。 S 有多少不同的非空子字符串? 子字符串是一个连续子序列。例如&#xff0c; xxx 是 yxxx 的子字符串&#xff0c;但不是 xxyxx 的子字符串。 解析&#xff1a; 对于数据范围不超过100&…

华清远见STM32MP157开发板助力嵌入式大赛ST赛道MPU应用方向项目开发

第七届&#xff08;2024&#xff09;全国大学生嵌入式芯片与系统设计竞赛&#xff08;以下简称“大赛”&#xff09;已经拉开帷幕&#xff0c;大赛的报名热潮正席卷而来。嵌入式大赛截止今年已连续举办了七届&#xff0c;为教育部认可的全国普通高校大学生国家级A类赛事&#x…

加速科技高性能数模混合信号测试设备ST2500EX精彩亮相SEMICON China 2024

芯片是现代信息技术发展的重要支柱&#xff0c;半导体设备则是芯片产业发展的重要基石。近年来&#xff0c;半导体设备领域开启了国产自研的黄金浪潮&#xff0c;其中&#xff0c;测试机作为芯片测试中至关重要的核心设备之一&#xff0c;国产自研率较低&#xff0c;一直是国内…