Как создать запись в объекте Context в начале запроса и получить его в конце запроса?
(отказ от ответственности: я балуюсь 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();
}
}
}
}
Это правильный / рекомендуемый способ? Мне интересно, могу ли я сделать это только с одним перехватчиком...
1 ответ
То, что вы делаете, выглядит хорошо. Другим способом является создание объекта в FooBarLifecycleServerInterceptor и, в первую очередь, избегание использования Context, но могут быть некоторые другие требования, не показанные в вашем примере.
Замечания:onReady
может не делать то, что вы думаете, что делает. Если идея состоит в том, чтобы вызывать инициализацию в начале каждого вызова сервера, я думаю, вы должны просто сделать это, когда происходит перехват вызова.
Один из onComplete
а также onCancel
будет вызван, поэтому вы должны также позвонить close()
когда onCancel
называется.