如何在Java中将数据从grpc rpc调用传递到服务器拦截器 [英] How to pass data from grpc rpc call to server interceptor in java

查看:154
本文介绍了如何在Java中将数据从grpc rpc调用传递到服务器拦截器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在处理rpc服务器调用之后,我尝试使用响应中的值设置一些元数据.计划是使用服务器拦截器并覆盖 close 方法.

I am trying to set some metadata with a value from the response after the rpc server call has been processed. The plan was to use server interceptor and override close method.

类似这样的内容:由于元数据值取决于响应,因此我需要某种方式将数据从rpc服务器调用传递到服务器拦截器,或从拦截器访问响应

Since the metadata value depends on the response, I need some way to pass data from rpc server call to server interceptor or access the response from interceptor

在Golang中,处理后可以在rpc调用 grpc.SetTrailer 中轻松设置元数据,但是在Java中,无法在rpc调用中进行设置.因此,我尝试使用服务器拦截器.

In Golang, the metadata can be set easily in the rpc call grpc.SetTrailer after processing but in java there is no way to do it in rpc call. So I am trying to use server interceptor for the same.

有人可以帮忙吗?

推荐答案

您可以为此使用grpc-java的 Context .在拦截器中,将 Context 附加到包含可变引用的自定义键.然后在通话中,您再次访问该标头并从中提取值.

You can use grpc-java's Contexts for that. In the interceptor you attach a Context with a custom key containing a mutable reference. Then in the call you access that header again and extract the value from it.

public static final Context.Key<TrailerHolder> TRAILER_HOLDER_KEY = Context.key("trailerHolder");

Context context = Context.current().withValue(TRAILER_HOLDER_KEY, new TrailerHolder());
Context previousContext = context.attach();
[...]
context.detach(previousContext);

您可以像这样访问上下文值:

You can access the context value like this:

TrailerHolder trailerHolder = TRAILER_HOLDER_KEY.get();

您可能想要实现类似于以下方法的代码: <代码> Contexts#interceptCall(Context,ServerCall,元数据,ServerCallHandler)

You might want to implement your code similar to this method: Contexts#interceptCall(Context, ServerCall, Metadata, ServerCallHandler)

import io.grpc.Context;
import io.grpc.ForwardingServerCall.SimpleForwardingServerCall;
import io.grpc.ForwardingServerCallListener;
import io.grpc.Metadata;
import io.grpc.ServerCall;
import io.grpc.ServerCall.Listener;
import io.grpc.ServerCallHandler;
import io.grpc.ServerInterceptor;
import io.grpc.Status;

public class TrailerServerInterceptor implements ServerInterceptor {

    public static final Context.Key<Metadata> TRAILER_HOLDER_KEY = Context.key("trailerHolder");

    @Override
    public <ReqT, RespT> Listener<ReqT> interceptCall(final ServerCall<ReqT, RespT> call, final Metadata headers,
            final ServerCallHandler<ReqT, RespT> next) {
        final TrailerCall<ReqT, RespT> call2 = new TrailerCall<>(call);
        final Context context = Context.current().withValue(TRAILER_HOLDER_KEY, new Metadata());
        final Context previousContext = context.attach();
        try {
            return new TrailerListener<>(next.startCall(call2, headers), context);
        } finally {
            context.detach(previousContext);
        }
    }

    private class TrailerCall<ReqT, RespT> extends SimpleForwardingServerCall<ReqT, RespT> {

        public TrailerCall(final ServerCall<ReqT, RespT> delegate) {
            super(delegate);
        }

        @Override
        public void close(final Status status, final Metadata trailers) {
            trailers.merge(TRAILER_HOLDER_KEY.get());
            super.close(status, trailers);
        }

    }

    private class TrailerListener<ReqT> extends ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT> {

        private final Context context;

        public TrailerListener(final ServerCall.Listener<ReqT> delegate, final Context context) {
            super(delegate);
            this.context = context;
        }

        @Override
        public void onMessage(final ReqT message) {
            final Context previous = this.context.attach();
            try {
                super.onMessage(message);
            } finally {
                this.context.detach(previous);
            }
        }

        @Override
        public void onHalfClose() {
            final Context previous = this.context.attach();
            try {
                super.onHalfClose();
            } finally {
                this.context.detach(previous);
            }
        }

        @Override
        public void onCancel() {
            final Context previous = this.context.attach();
            try {
                super.onCancel();
            } finally {
                this.context.detach(previous);
            }
        }

        @Override
        public void onComplete() {
            final Context previous = this.context.attach();
            try {
                super.onComplete();
            } finally {
                this.context.detach(previous);
            }
        }

        @Override
        public void onReady() {
            final Context previous = this.context.attach();
            try {
                super.onReady();
            } finally {
                this.context.detach(previous);
            }
        }

    }

}

在grpc服务方法中,您只需使用 TRAILER_HOLDER_KEY.get().put(...)

In your grpc service method you can simply use TRAILER_HOLDER_KEY.get().put(...)

这篇关于如何在Java中将数据从grpc rpc调用传递到服务器拦截器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆