我是靠谱客的博主 清新爆米花,最近开发中收集的这篇文章主要介绍JAVA调用方法统一打印日志和try/catch 实现思路1.1. 创建一个接口(用来获取函数真实的调用路径和方法)1.2. 创建一个函数接口(继承SerializedLambdaFunction)2. 创建获取枚举属性的接口3. 创建异常信息枚举类 (实现EnumMessage接口)4. 编写FunctionUtils工具类5. 使用方式(以调用Service为例),觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
需求:
避免编写重复的代码,如何把下面的两个需求抽取成公共逻辑;
1. 调用其他方法时打印被调用方法的路径、入参、以及执行耗时情况;
2. 调用方法遇到异常时,灵活控制是否要捕获异常或者抛出异常;
实现思路
- 使用函数式编程;
1.1. 创建一个接口(用来获取函数真实的调用路径和方法)
package com.xxx.utils.function;
import java.io.Serializable;
import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;
/**
*
*/
public interface SerializedLambdaFunction extends Serializable {
/**
* 这个方法返回的SerializedLambda是重点
* @return
* @throws Exception
*/
default SerializedLambda getSerializedLambda() throws Exception {
//writeReplace改了好像会报异常
Method write = this.getClass().getDeclaredMethod("writeReplace");
write.setAccessible(true);
return (SerializedLambda) write.invoke(this);
}
/**
* 获取函数真实调用的实现类名
* @return
*/
default String getImplClass() {
try {
return getSerializedLambda().getImplClass();
} catch (Exception e) {
return null;
}
}
/**
* 获取函数真实调用的实现方法名
* @return
*/
default String getImplMethodName() {
try {
return getSerializedLambda().getImplMethodName();
} catch (Exception e) {
return null;
}
}
/**
* 获取函数真实调用的类名#方法名
* @return
*/
default String getClassAndMethodName() {
try {
return getImplClass() + "#" + getImplMethodName();
} catch (Exception e) {
return null;
}
}
}
1.2. 创建一个函数接口(继承SerializedLambdaFunction)
下面是只接收一个参数并且有返回值的函数接口,如果要编写多个参数的函数接口只需要在<>泛型中和apply方法中添加泛型即可;
package com.xxx.utils.function;
/**
* 接收一个参数并返回结果的函数
* 函数方法是 {@link #apply(Object)}
*
* @param <T> 第一个参数
* @param <R> 返回结果
*/
@FunctionalInterface
public interface MonoFunction<T, R> extends SerializedLambdaFunction {
/**
* 使用指定的参数调用该方法
*
* @param t 第一个参数
* @return 返回结果
*/
R apply(T t);
}
2. 创建获取枚举属性的接口
package com.xxx.constant;
/**
* 获取枚举属性
*/
public interface EnumMessage {
/**
* 获取code
* @return
*/
int getCode();
/**
* 获取信息
* @return
*/
String getMessage();
}
3. 创建异常信息枚举类 (实现EnumMessage接口)
package com.xxx.exception;
import com.xxx.EnumMessage;
/**
* 实现EnumMessage接口
*/
public enum ErrorCode implements EnumMessage {
;
/**
* 错误代码
*/
private int code;
/**
* 错误信息
*/
private String message;
ErrorCode(int errCode, String errMessage) {
this.code = errCode;
this.message = errMessage;
}
@Override
public int getCode() {
return code;
}
@Override
public String getMessage() {
return message;
}
}
4. 编写FunctionUtils工具类
4.1. 编写接收函数的方法
方法介绍
- apply(MonoFunction<T, R> function, T param):执行方法并返回结果,不进行异常处理;
- applyTry(MonoFunction<T, R> function, T param):执行方法并返回结果,如果遇到异常则捕获并返回null值;
- applyTry(MonoFunction<T, R> function, T param, ErrorCode exceptionMessage):执行方法并返回结果,如果遇到异常则捕获异常并抛出新的异常。
/**
* 接受一个函数和一个参数,并执行函数调用返回结果
*
* @param function 函数
* @param param 第一个参数
* @param <R> 返回结果
* @return
*/
public static <T, R> R apply(MonoFunction<T, R> function, T param) {
StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
R result = function.apply(param);
stopWatch.stop();
return result;
} finally {
logInfo(function, String.valueOf(stopWatch.getTotalTimeMillis()), param);
}
}
/**
* 接受一个函数和一个参数,并执行函数调用返回结果;
* 调用过程中遇到异常则会捕获异常,并返回null值
*
* @param function 函数
* @param param 第一个参数
* @param <R> 返回结果
* @return
*/
public static <T, R> R applyTry(MonoFunction<T, R> function, T param) {
R apply = null;
try {
apply = apply(function, param);
} catch (Exception e) {
logError(e);
}
return apply;
}
/**
* 接受一个函数和一个参数,并执行函数调用返回结果;
* 调用过程中遇到异常则会抛出exception异常
*
* @param function 函数
* @param param 第一个参数
* @param exceptionMessage 异常信息
* @param <R> 返回结果
* @return
*/
public static <T, R> R applyTry(MonoFunction<T, R> function, T param, EnumMessage exceptionMessage) {
try {
R apply = apply(function, param);
return apply;
} catch (Exception e) {
logError(e);
throw exception(exceptionMessage);
}
}
4.2. 编写打印日志的方法
/**
* 日志工具
*/
private static final Log logger = LogFactory.get();
/**
* 日志信息
*/
private static final String INFO_MESSAGE = "【调用信息】:%s(%s),耗时:%s毫秒";
/**
* 打印请求的方法路径和参数名称
*
* @param function 函数
* @param params 参数
*/
public static void logInfo(SerializedLambdaFunction function, String totalTimeMillis, Object... params) {
String paramStr = Arrays.stream(params).map(JSON::toJSONString).collect(Collectors.joining(","));
logger.info(String.format(INFO_MESSAGE, function.getClassAndMethodName(), paramStr, totalTimeMillis));
}
/**
* 打印请求的方法路径和参数名称
*
* @param function 函数
* @param param 参数
*/
public static void logInfo(SerializedLambdaFunction function, Object... param) {
logInfo(function, "-", param);
}
/**
* 打印error级别的异常信息
*
* @param exception 异常
*/
public static void logError(Exception exception) {
logger.error(exception.getMessage(), exception);
}
/**
* 默认异常信息
*/
private static EnumMessage DEFAULT_MESSAGE = new EnumMessage() {
@Override
public int getCode() {
return 0;
}
@Override
public String getMessage() {
return "获取信息失败";
}
};
/**
* 创建异常信息
* @param message
*/
private static RuntimeException exception(EnumMessage message) {
if (ObjectUtils.isEmpty(message)) {
message = DEFAULT_MESSAGE;
}
return new RuntimeException(message.getMessage(), message.getCode());
}
4.3. 完整工具类代码
package com.xxx.utils;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.alibaba.fastjson.JSON;
import com.xxx.EnumMessage;
import com.xxx.utils.function.*;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.util.StopWatch;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* 函数工具类
*/
public class FunctionUtils {
/**
* 日志工具
*/
private static final Log logger = LogFactory.get();
/**
* 日志信息
*/
private static final String INFO_MESSAGE = "【调用信息】:%s(%s),耗时:%s毫秒";
/**
* 打印请求的方法路径和参数名称
*
* @param function 函数
* @param params 参数
*/
public static void logInfo(SerializedLambdaFunction function, String totalTimeMillis, Object... params) {
String paramStr = Arrays.stream(params).map(JSON::toJSONString).collect(Collectors.joining(","));
logger.info(String.format(INFO_MESSAGE, function.getClassAndMethodName(), paramStr, totalTimeMillis));
}
/**
* 打印请求的方法路径和参数名称
*
* @param function 函数
* @param param 参数
*/
public static void logInfo(SerializedLambdaFunction function, Object... param) {
logInfo(function, "-", param);
}
/**
* 打印error级别的异常信息
*
* @param exception 异常
*/
public static void logError(Exception exception) {
logger.error(exception.getMessage(), exception);
}
/**
* 默认异常信息
*/
private static EnumMessage DEFAULT_MESSAGE = new EnumMessage() {
@Override
public int getCode() {
return 0;
}
@Override
public String getMessage() {
return "获取信息失败";
}
};
/**
* 创建异常信息
* @param message
*/
private static xxxException exception(EnumMessage message) {
if (ObjectUtils.isEmpty(message)) {
message = DEFAULT_MESSAGE;
}
// 自定义一个Exception,接收一个message和一个code
return new xxxException(message.getMessage(), message.getCode());
}
/**
* 接受一个函数和一个参数,并执行函数调用返回结果
*
* @param function 函数
* @param param 第一个参数
* @param <R> 返回结果
* @return
*/
public static <T, R> R apply(MonoFunction<T, R> function, T param) {
StopWatch stopWatch = new StopWatch();
try {
stopWatch.start();
R result = function.apply(param);
stopWatch.stop();
return result;
} finally {
logInfo(function, String.valueOf(stopWatch.getTotalTimeMillis()), param);
}
}
/**
* 接受一个函数和一个参数,并执行函数调用返回结果;
* 调用过程中遇到异常则会捕获异常,并返回null值
*
* @param function 函数
* @param param 第一个参数
* @param <R> 返回结果
* @return
*/
public static <T, R> R applyTry(MonoFunction<T, R> function, T param) {
R apply = null;
try {
apply = apply(function, param);
} catch (Exception e) {
logError(e);
}
return apply;
}
/**
* 接受一个函数和一个参数,并执行函数调用返回结果;
* 调用过程中遇到异常则会抛出exception异常
*
* @param function 函数
* @param param 第一个参数
* @param exceptionMessage 异常信息
* @param <R> 返回结果
* @return
*/
public static <T, R> R applyTry(MonoFunction<T, R> function, T param, EnumMessage exceptionMessage) {
try {
R apply = apply(function, param);
return apply;
} catch (Exception e) {
logError(e);
throw exception(exceptionMessage);
}
}
}
5. 使用方式(以调用Service为例)
5.1. 引入Service
@Autowired
private xxxService service;
5.2. 通过FunctionUtils调用service的方法
String id= "123456";
String value= FunctionUtils.applyTry(xxxService::getxxxById, id);
最后
以上就是清新爆米花为你收集整理的JAVA调用方法统一打印日志和try/catch 实现思路1.1. 创建一个接口(用来获取函数真实的调用路径和方法)1.2. 创建一个函数接口(继承SerializedLambdaFunction)2. 创建获取枚举属性的接口3. 创建异常信息枚举类 (实现EnumMessage接口)4. 编写FunctionUtils工具类5. 使用方式(以调用Service为例)的全部内容,希望文章能够帮你解决JAVA调用方法统一打印日志和try/catch 实现思路1.1. 创建一个接口(用来获取函数真实的调用路径和方法)1.2. 创建一个函数接口(继承SerializedLambdaFunction)2. 创建获取枚举属性的接口3. 创建异常信息枚举类 (实现EnumMessage接口)4. 编写FunctionUtils工具类5. 使用方式(以调用Service为例)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复