springboot 启动项目打印接口列表的实现
程序员文章站
2022-03-07 23:21:13
目录springboot项目添加接口入参统一打印springboot 启动项目打印接口列表环境 springboot 2.3.2.release修改配置文件logging: level:...
springboot 启动项目打印接口列表
环境
- springboot 2.3.2.release
修改配置文件
logging: level: org.springframework.web.servlet.mvc.method.annotation.requestmappinghandlermapping: trace
结果:
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); } } }
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。