springboot 啟動(dòng)項(xiàng)目打印接口列表的實(shí)現(xiàn)
springboot 啟動(dòng)項(xiàng)目打印接口列表
環(huán)境
- springboot 2.3.2.RELEASE
修改配置文件
logging: level: org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: trace
結(jié)果:
Springboot項(xiàng)目添加接口入?yún)⒔y(tǒng)一打印
需求:要求接口被調(diào)用時(shí)要打印被調(diào)用方法名,以及入?yún)⑶闆r,參數(shù)格式化時(shí)選擇fastjson
注:使用fastjson序列化時(shí)脫敏,建議入?yún)⒔y(tǒng)一使用自定義的對象類型作為入?yún)?/p>
如果不需要參數(shù)脫敏,直接使用增強(qiáng)中相關(guān)代碼,并去除參數(shù)脫敏相關(guān)代碼即可
新建注解,用于實(shí)現(xiàn)參數(shù)打印功能的增強(qiáng)
@Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface ParamInfo { /** * 取消統(tǒng)一打印參數(shù) * 默認(rèn)為false統(tǒng)一打印 * 如需自定義參數(shù)打印 請賦值為true */ boolean unPrint() default false; /** * 需要脫敏的字段,如密碼等 */ String[] fields() default {}; }
自定義序列化規(guī)則
/** * 序列化過濾器:值替換 * */ public class ReplaceFieldFilter implements ValueFilter { /** * 需要進(jìn)行替換的屬性名和替換值 * 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; } /** * 傳入需要脫敏的字段名,序列化時(shí)格式化為 * 號 */ public ReplaceFieldFilter(String... fields) { String str = "******"; fieldMap = new HashMap<>(4); for (String field : fields) { fieldMap.put(field, str); } } }
寫參數(shù)打印增強(qiáng),這里選擇環(huán)繞增強(qiáng)
@Component @Aspect //表示增強(qiáng)的執(zhí)行順序,如果多個(gè)增強(qiáng),數(shù)值小的先被執(zhí)行 @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) { //獲取需要脫敏的字段名數(shù)組 String[] fields = annotation.fields(); for (String field : fields) { fieldMap.put(field, "******"); } } String param; //參數(shù)整合,多字段入?yún)⒄蠟閷ο螅瑔蝹€(gè)對象入?yún)⒏袷讲蛔? 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); //可在這里定義程序異常時(shí)的錯(cuò)誤返回值 returnValue = ErrorCode.SYSTEM_ERROR; return returnValue; } finally { LOGGER.info("request cost:{}ms, requestId:[{}]", System.currentTimeMillis() - startTime, requestId); LOGGER.info("returnValue:[{}], requestId:[{}]", returnValue, requestId); } } }
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- IntelliJ IDEA下SpringBoot如何指定某一個(gè)配置文件啟動(dòng)項(xiàng)目
- 詳解SpringBoot啟動(dòng)項(xiàng)目后執(zhí)行方法的幾種方式
- springboot+dubbo啟動(dòng)項(xiàng)目時(shí)報(bào)錯(cuò) zookeeper not connected的問題及解決方案
- IDEA下SpringBoot指定配置文件啟動(dòng)項(xiàng)目的全過程
- SpringBoot實(shí)現(xiàn)啟動(dòng)項(xiàng)目后立即執(zhí)行的方法總結(jié)
- java?-jar命令及SpringBoot通過java?-jav啟動(dòng)項(xiàng)目的過程
- idea沒有services窗口、沒有springboot啟動(dòng)項(xiàng)問題
相關(guān)文章
淺談Java實(shí)現(xiàn)分布式事務(wù)的三種方案
現(xiàn)在互聯(lián)網(wǎng)下,分布式和微服務(wù)橫行,難免會(huì)遇到分布式下的事務(wù)問題,當(dāng)然微服務(wù)下可能沒有分布式事務(wù),但是很多場景是需要分布式事務(wù)的。下面就來介紹下什么是分布式事務(wù)和分布式事務(wù)的解決方案2021-06-06Spring Boot將項(xiàng)目打包成war包的操作方法
這篇文章主要介紹了Spring Boot將項(xiàng)目打包成war包的操作方法,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-09-09Java 文創(chuàng)商城系統(tǒng)的實(shí)現(xiàn)流程
讀萬卷書不如行萬里路,只學(xué)書上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用java+SSM+mysql+maven+tomcat實(shí)現(xiàn)一個(gè)文創(chuàng)商城系統(tǒng),大家可以在過程中查缺補(bǔ)漏,提升水平2021-11-11最新log4j2遠(yuǎn)程代碼執(zhí)行漏洞(附解決方法)
Apache?Log4j2?遠(yuǎn)程代碼執(zhí)行漏洞攻擊代碼,該漏洞利用無需特殊配置,經(jīng)多方驗(yàn)證,Apache?Struts2、Apache?Solr、Apache?Druid、Apache?Flink等均受影響,本文就介紹一下解決方法2021-12-12spring?java?動(dòng)態(tài)獲取consul?K/V的方法
這篇文章主要介紹了spring?java?動(dòng)態(tài)獲取consul?K/V的相關(guān)資料,主要包括springConsul配置kv路徑以及自動(dòng)注入consulKV到服務(wù)中,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10ruoyi-springboot框架新增模塊調(diào)接口報(bào)404的解決方案
這篇文章主要介紹了ruoyi-springboot框架新增模塊調(diào)接口報(bào)404的解決方案,文中通過代碼示例給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下2024-03-03