如何在请求开始时创建 Context 对象的条目并在请求结束时检索它?

How to create an entry into the Context object at the beginning of a request and retrieve it at the end of a request?

(免责声明:我正在涉足 grpc)

我有一个对象,我想将其与每个请求相关联,initialize在请求开始时对其进行处理,并在请求完成后close对其进行处理。

目前我通过使用两个 ServerInterceptors 来实现这一点,第一个将对象填充到上下文中,第二个拦截 onReadyonComplete 来初始化和关闭对象分别。

PopulateObjectServerInterceptor:

public class FooBarInterceptor implements ServerInterceptor {
@Override
public <ReqT, RespT> ServerCall.Listener<ReqT> interceptCall(ServerCall<ReqT, RespT> call, Metadata headers, ServerCallHandler<ReqT, RespT> next) {
    FooBar foobar = FooBar.create(foo, bar);
    Context ctx = Context.current().withValue(Constants.FOO_BAR, foobar);

    return Contexts.interceptCall(ctx, call, headers, next);
}

RequestLifecycleInterceptor

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

        final ServerCall.Listener<ReqT> original = next.startCall(call, headers);

        return new ForwardingServerCallListener.SimpleForwardingServerCallListener<ReqT>(original) {
            @Override
            public void onReady() {
                FooBar foobar = (FooBar) Context.key("foobarname").get();
                foobar.initialize()
                super.onReady();
            }

            @Override
            public void onMessage(final ReqT message) {
                FooBar foo = (FooBar) Context.key("foobar").get();
                foobar.someaction()
                super.onMessage(message);
            }

            @Override
            public void onComplete() {
                FooBar foo = (FooBar) Context.key("foobar").get();
                foobar.close()
                super.onComplete();
            }
        }
    } 
}

这是correct/recommended方式吗?我想知道我是否可以只用一个拦截器来做到这一点...

你所做的看起来不错。另一种方法是在 FooBarLifecycleServerInterceptor 中创建对象并首先避免使用 Context,但可能还有一些其他要求未在您的示例中说明。

注意: onReady may not do what you think it does。如果想法是在每次服务器调用开始时调用初始化,我认为你应该在调用拦截发生时才这样做。

onCompleteonCancel中的一个会被调用,所以当onCancel被调用时,你也应该调用close()