版权说明: 本文由博主keep丶原创,转载请注明出处。
原文地址: https://blog.csdn.net/qq_38688267/article/details/120787954
前言
作者有一个项目中考虑到性能和跨平台能力,采用Grpc
作为服务间调度的方案,但是Grpc
对JAVA的支持太差,使用起来比较麻烦,为了简化部分代码,作者封装了Grpc的全局异常捕获功能。
代码
服务端
@GrpcGlobalServerInterceptor
public class GrpcServerInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> serverCall,
Metadata metadata,
ServerCallHandler<ReqT, RespT> serverCallHandler) {
return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(serverCallHandler.startCall(serverCall, metadata)) {
@Override
public void onHalfClose() {
try {
super.onHalfClose();
} catch (Exception e) {
if (!(e instanceof BusinessException)) {
e.printStackTrace();
}
// 通过元数据传输消息
metadata.put(Metadata.Key.of("message-bin", new Metadata.BinaryMarshaller<String>() {
@Override
public byte[] toBytes(String value) {
return value.getBytes(StandardCharsets.UTF_8);
}
@Override
public String parseBytes(byte[] serialized) {
return new String(serialized);
}
}), e.getMessage());
serverCall.close(Status.INVALID_ARGUMENT, metadata);
}
}
};
}
}
客户端
@ControllerAdvice
@ResponseBody
public class GlobalExceptionHandler {
/**
* Grpc远程调用异常处理
*/
@ExceptionHandler(StatusRuntimeException.class)
public ResponseMessage statusRuntimeException(StatusRuntimeException e) {
Metadata metadata = e.getTrailers();
// 这里可以细化到根据状态确定返回值
if (e.getStatus().getCode().value() == Status.INVALID_ARGUMENT.getCode().value()) {
}
// 这里的message-bin,要跟服务端返回的值一致
return new ResponseMessage(Constant.ERROR_CODE, metadata.get(Metadata.Key.of("message-bin", new MyBinaryMarshaller())));
}
private static class MyBinaryMarshaller implements Metadata.BinaryMarshaller<String> {
@Override
public byte[] toBytes(String value) {
return value.getBytes(StandardCharsets.UTF_8);
}
@Override
public String parseBytes(byte[] serialized) {
return new String(serialized);
}
}
}