簡體   English   中英

Spring gRPC - 如何攔截帶有正文信息的異常

[英]Spring gRPC - How intercept an exception with body info

我有一個使用 spring gRPC 的項目。 我創建了一個攔截器,當服務響應成功時,攔截器工作正常,但是當服務捕獲異常時,攔截器不起作用。

服務:

@GrpcService
public class ClientAppImpl extends ClientAppGrpc.ClientAppImplBase {
    
    @Autowired MyService myService;

    @Override
    public void myMethod(Request request, StreamObserver<CreateDigitalCertificateResponse> responseObserver) {
        try {
            Response response = myService.doStuff(request);
            responseObserver.onNext(response);
            responseObserver.onCompleted();
        } catch(Exception ex) {
            responseObserver.onError(Status.INTERNAL.withDescription(exception.getMessage()).withCause(exception).asRuntimeException());
        }

    }
}

攔截器:

@GrpcGlobalServerInterceptor
public class GrpcServerInterceptor implements ServerInterceptor {

    public static final String REQUEST_ID_HEADER = "request-id-bin";
    public static final Metadata.Key<byte[]> REQUEST_ID_METADATA_KEY = Metadata.Key.of(REQUEST_ID_HEADER, Metadata.BINARY_BYTE_MARSHALLER);
    private static final Map<String, GrpcCall> CALLS = new HashMap<>();

    @Override
    public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {

        ForwardingServerCall<ReqT, RespT> responseServerCall = new ForwardingServerCall.SimpleForwardingServerCall<ReqT, RespT>(call) {
            @Override
            public void sendMessage(RespT response) {
                String callId = new String(headers.get(REQUEST_ID_METADATA_KEY));

                GrpcCall grpcCall = CALLS.get(callId);
                grpcCall.setResponse(response);

                GrpcCallProcessor grpcCallProcessor = new GrpcCallProcessor(grpcCall);
                grpcCallProcessor.processCall();

                super.sendMessage(response);
            }

        };

        ServerCall.Listener<ReqT> listenerWithContext = Contexts.interceptCall(Context.current(), responseServerCall, headers, next);

        return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(listenerWithContext) {

            @Override
            public void onMessage(ReqT request) {
                String callId = UUID.randomUUID().toString();

                headers.put(REQUEST_ID_METADATA_KEY, callId.getBytes());

                GrpcCall grpcCall = new GrpcCall();
                grpcCall.setCall(call);
                grpcCall.setHeaders(headers);
                grpcCall.setRequest(request);

                CALLS.put(callId, grpcCall);

                super.onMessage(request);
            }
        };
    }
}

當服務未捕獲異常時,攔截器工作正常,並調用方法 sendMessage。 但是當服務捕獲異常時,不會調用方法 sendMessage。

有什么方法可以攔截異常,並在攔截器中獲取請求體?

謝謝!

如果myService.doStuff()拋出異常,則不會發送任何消息 sendMessage()不會被調用,但close(Status, Metadata)仍然會被調用。

headers的當前用法已被破壞。 Metadata不是線程安全的,您不知道 object 的當前“所有者”在用它做什么。 headers.get(REQUEST_ID_METADATA_KEY)應該在返回之前直接在interceptCall()中執行。

尚不完全清楚onMessage()的目的是什么,但看起來您應該在interceptCall()中制作元數據( new Metadata().merge(headers ) 的副本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM