如何在请求开始时创建 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
来实现这一点,第一个将对象填充到上下文中,第二个拦截 onReady
和 onComplete
来初始化和关闭对象分别。
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。如果想法是在每次服务器调用开始时调用初始化,我认为你应该在调用拦截发生时才这样做。
onComplete
和onCancel
中的一个会被调用,所以当onCancel
被调用时,你也应该调用close()
。
(免责声明:我正在涉足 grpc)
我有一个对象,我想将其与每个请求相关联,initialize
在请求开始时对其进行处理,并在请求完成后close
对其进行处理。
目前我通过使用两个 ServerInterceptors
来实现这一点,第一个将对象填充到上下文中,第二个拦截 onReady
和 onComplete
来初始化和关闭对象分别。
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。如果想法是在每次服务器调用开始时调用初始化,我认为你应该在调用拦截发生时才这样做。
onComplete
和onCancel
中的一个会被调用,所以当onCancel
被调用时,你也应该调用close()
。