工做中常常調用外部接口, 須要進行詳細日誌記錄, 防止扯皮. 在調用失敗之後, 要及時通知警告. 下面是攔截器的實現, 使用方式參考: http://www.javashuo.com/article/p-wqblcmcg-r.htmlhtml
/** * 攔截有註解的方法. 方法調用前, 會 info 級別打印全部入參; 調用之後, 會打印返回結果. <br/> * 若是產生異常, 會 error 級別打印異常信息, 同時發送報警郵件, 異常不會被攔截, 會正常拋出. <br/> * 報警郵件送達規則符合 {@link EmailWarnUtil} 定義規則. * * @see * https://my.oschina.net/u/1169457/blog/1489113 * http://todayleave.blogspot.jp/2016/02/spring-methodinterceptor.html * http://blog.javaforge.net/post/76125490725/spring-aop-method-interceptor-annotation * */ @Slf4j @Component public class LogAndWarnInterceptor implements MethodInterceptor { @Autowired private JsonUtil jsonUtil; @Autowired private EmailWarnUtil emailWarnUtil; private ConcurrentHashMap<Method, List<String>> methodParameterNamesCache = new ConcurrentHashMap<>(); @Override public Object invoke(MethodInvocation invocation) throws Throwable { Method method = invocation.getMethod(); Object[] args = invocation.getArguments(); List<String> paramNames = getMethodParamNames(method); String className = invocation.getThis().getClass().getSimpleName(); String classMethodName = className + "." + method.getName(); long timestamp = System.currentTimeMillis(); log.info("before invoke method:{}, parameter names:{}, args:{}, timestamp:{}", classMethodName, paramNames, jsonUtil.toJsonString(args), timestamp); try { Object retVal = invocation.proceed(); log.info("after invoke method:{}, result:{}, invoke timestamp:{}, call duration:{}", classMethodName, jsonUtil.toJsonString(retVal), timestamp, System.currentTimeMillis() - timestamp); return retVal; } catch (Exception exception) { String errMessage = "exception!!! invoke method:" + classMethodName + ", parameter names:" + paramNames + ", args:" + jsonUtil.toJsonString(args) + ", invoke timestamp:" + timestamp; log.error(errMessage, exception); emailWarnUtil.muteWarn(NotifyEmailGroup.ERROR_WARN, errMessage, exception); throw exception; // throw new HttpException(HttpStatus.INTERNAL_SERVER_ERROR, "服務器調用後端服務錯誤, 請稍後重試."); } } /** * @see https://stackoverflow.com/questions/2237803/can-i-obtain-method-parameter-name-using-java-reflection * <b>Bozho's answer</b> * * @param method * @return */ private List<String> getMethodParamNames(Method method) { List<String> paramNames = methodParameterNamesCache.get(method); if (paramNames != null) { return paramNames; } Parameter[] parameters = method.getParameters(); paramNames = new ArrayList<>(); for (Parameter parameter : parameters) { paramNames.add(parameter.getName()); } methodParameterNamesCache.put(method, paramNames); return paramNames; } }
在用反射獲取方法簽名(方法入參名字)時, 須要在pom文件添加 -parameters
參數, 並且jdk8以上版本. 要否則獲取的參數名字將會是: arg0, rags1 這樣. 更改配置之後, 須要 mvn clean package
一下生效.java
<properties> <!-- PLUGIN VERSIONS --> <maven-compiler-plugin.version>3.1</maven-compiler-plugin.version> <!-- OTHER PROPERTIES --> <java.version>1.8</java.version> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <compilerArgument>-parameters</compilerArgument> <testCompilerArgument>-parameters</testCompilerArgument> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build>
2017-07-26 18:33:38 [XNIO-1 task-1] INFO c.y.o.c.global.LogAndWarnInterceptor - before invoke method:SmsService.send, parameter names:[mobile, templeId, params], args:["12222222222","string",{}], timestamp:1501065218633 2017-07-26 18:33:38 [XNIO-1 task-1] INFO c.y.o.c.global.LogAndWarnInterceptor - after invoke method:SmsService.send, result:, invoke timestamp:1501065218633, call duration:43
http://www.javashuo.com/article/p-wqblcmcg-r.html
https://stackoverflow.com/questions/2237803/can-i-obtain-method-parameter-name-using-java-reflectionspring