springboot 启动项目打印接口列表的实现

作者:enjoy嚣士 时间:2023-08-29 02:38:44 

springboot 启动项目打印接口列表

环境

  • springboot 2.3.2.RELEASE

修改配置文件


logging:
 level:
   org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: trace

结果:

springboot 启动项目打印接口列表的实现

Springboot项目添加接口入参统一打印

需求:要求接口被调用时要打印被调用方法名,以及入参情况,参数格式化时选择fastjson

注:使用fastjson序列化时脱敏,建议入参统一使用自定义的对象类型作为入参

如果不需要参数脱敏,直接使用增强中相关代码,并去除参数脱敏相关代码即可

新建注解,用于实现参数打印功能的增强


@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ParamInfo {
   /**
    * 取消统一打印参数
    * 默认为false统一打印
    * 如需自定义参数打印 请赋值为true
    */
   boolean unPrint() default false;
   /**
    * 需要脱敏的字段,如密码等
    */
   String[] fields() default {};
}

自定义序列化规则


/**
* 序列化过滤器:值替换
*
*/
public class ReplaceFieldFilter implements ValueFilter {
   /**
    * 需要进行替换的属性名和替换值
    * key:属性名
    * value:替换值
    */
   private Map<String, Object> fieldMap;
   public ReplaceFieldFilter() {
   }
   public ReplaceFieldFilter(Map<String, Object> fieldMap) {
       this.fieldMap = fieldMap;
   }
   @Override
   public Object process(Object o, String name, Object value) {
       if(!CollectionUtils.isEmpty(fieldMap)){
           Iterator<Map.Entry<String, Object>> iterator = fieldMap.entrySet().iterator();
           while (iterator.hasNext()){
               Map.Entry<String, Object> next = iterator.next();
               if(next.getKey().equalsIgnoreCase(name)){
                   return next.getValue();
               }
           }
       }
       return value;
   }
   public Map<String, Object> getFieldMap() {
       return fieldMap;
   }
   public void setFieldMap(Map<String, Object> fieldMap) {
       this.fieldMap = fieldMap;
   }
   /**
    * 传入需要脱敏的字段名,序列化时格式化为 * 号
    */
   public ReplaceFieldFilter(String... fields) {
       String str = "******";
       fieldMap = new HashMap<>(4);
       for (String field : fields) {
           fieldMap.put(field, str);
       }
   }
}

写参数打印增强,这里选择环绕增强


@Component
@Aspect
//表示增强的执行顺序,如果多个增强,数值小的先被执行
@Order(0)
public class ParamInfoAspect {
   private static final Logger LOGGER = LoggerFactory.getLogger(ParamInfoAspect.class);
   @Around("execution(* com.service.impl.*.*(..))")
   public Object printParam(ProceedingJoinPoint joinPoint) throws Throwable {
       long startTime = System.currentTimeMillis();
       String requestId = RandomStringUtils.randomAlphanumeric(16);
       Object returnValue = null;
       try {
           Object[] args = joinPoint.getArgs();
           // 获取方法对象
           MethodSignature signature = (MethodSignature) joinPoint.getSignature();
           Method method = signature.getMethod();
           //通过注解获取脱敏字段,之后初始化fieldMap,完成字段脱敏
           ParamInfo annotation = method.getAnnotation(ParamInfo.class);
           Map<String, Object> fieldMap = new HashMap<>(4);
           fieldMap.put("password", "******");
           if (annotation != null) {
               //获取需要脱敏的字段名数组
               String[] fields = annotation.fields();
               for (String field : fields) {
                   fieldMap.put(field, "******");
               }
           }
           String param;
           //参数整合,多字段入参整合为对象,单个对象入参格式不变
           if (args.length > 1 || (args.length == 1 && args[0].getClass() == String.class)) {
               Map<String, Object> paramMap = new LinkedHashMap<>();
               String[] parameterNames = signature.getParameterNames();
               for (int i = 0; i < parameterNames.length; i++) {
                   paramMap.put(parameterNames[i], args[i]);
               }
               param = "[" + JSON.toJSONString(paramMap, new ReplaceFieldFilter(fieldMap)) + "]";
           } else {
               param = JSON.toJSONString(args, new ReplaceFieldFilter(fieldMap));
           }
           String methodName = method.getName();
           LOGGER.info("method:[{}], parameter:{}, requestId:[{}]", methodName, param, requestId);
           returnValue = joinPoint.proceed();
           return returnValue;
       } catch (Exception e) {
           LOGGER.error("system is error:", e);
  //可在这里定义程序异常时的错误返回值
           returnValue = ErrorCode.SYSTEM_ERROR;
           return returnValue;
       } finally {
           LOGGER.info("request cost:{}ms, requestId:[{}]", System.currentTimeMillis() - startTime, requestId);
           LOGGER.info("returnValue:[{}], requestId:[{}]", returnValue, requestId);
       }
   }
}

来源:https://enjoy-day.blog.csdn.net/article/details/115071427

标签:springboot,打印,接口,列表
0
投稿

猜你喜欢

  • 如何正确使用Android线程详解

    2021-12-06 19:24:30
  • 浅谈java内存管理与内存溢出异常

    2022-04-22 15:03:18
  • 详解App保活实现原理

    2022-01-20 17:59:10
  • springcloud-gateway集成knife4j的示例详解

    2023-11-29 08:56:44
  • 理解Java多线程之并发编程

    2021-11-25 11:14:56
  • 聊聊Springboot2.x的session和cookie有效期

    2022-09-11 10:17:20
  • 详解C# 利用反射根据类名创建类的实例对象

    2023-12-20 12:42:41
  • Java包装类的概述与应用

    2022-03-14 07:50:43
  • C#中使用Cache框架快速实现Cache操作

    2023-01-21 22:35:27
  • SpringMVC Restful风格与中文乱码问题解决方案介绍

    2021-06-12 03:15:16
  • C#实现根据指定容器和控件名字获得控件的方法

    2023-09-26 12:23:03
  • Android 百度地图定位实现仿钉钉签到打卡功能的完整代码

    2022-09-05 17:32:46
  • 使用VS2010 C#开发ActiveX控件(下),完整代码打包下载

    2022-08-20 18:05:29
  • spring-cloud-stream结合kafka使用详解

    2022-05-19 14:32:50
  • 解决SpringCloud下spring-boot-maven-plugin插件的打包问题

    2022-03-10 14:35:59
  • 浅谈Ribbon、Feign和OpenFeign的区别

    2022-12-21 15:40:27
  • C#创建压缩文件的实现代码

    2022-07-28 23:55:04
  • 使用SSM+Layui+Bootstrap实现汽车维保系统的示例代码

    2023-11-28 18:30:04
  • Java实现聊天室界面

    2023-12-15 10:43:32
  • java Long类型转为String类型的两种方式及区别说明

    2022-11-12 18:03:38
  • asp之家 软件编程 m.aspxhome.com