Java 设置gRPC服务器拦截器的执行顺序

Java 设置gRPC服务器拦截器的执行顺序,java,spring,grpc,grpc-java,Java,Spring,Grpc,Grpc Java,在io.grpc.internal.AbstractServerImplBuilder中,您可以将ServerInterceptor的实现添加到最终列表中 final List<ServerInterceptor> interceptors = new ArrayList<>(); final List interceptors=new ArrayList(); 然后在构建器的默认服务器实现中-io.grpc.internal.ServerImpl在foreach循环

在io.grpc.internal.AbstractServerImplBuilder中,您可以将ServerInterceptor的实现添加到最终列表中

final List<ServerInterceptor> interceptors = new ArrayList<>();
final List interceptors=new ArrayList();
然后在构建器的默认服务器实现中-io.grpc.internal.ServerImpl在foreach循环中调用它们

/** Never returns {@code null}. */
private <ReqT, RespT> ServerStreamListener startCall(ServerStream stream, String fullMethodName,
    ServerMethodDefinition<ReqT, RespT> methodDef, Metadata headers,
    Context.CancellableContext context, StatsTraceContext statsTraceCtx, Tag tag) {
  // TODO(ejona86): should we update fullMethodName to have the canonical path of the method?
  statsTraceCtx.serverCallStarted(
      new ServerCallInfoImpl<>(
          methodDef.getMethodDescriptor(), // notify with original method descriptor
          stream.getAttributes(),
          stream.getAuthority()));
  ServerCallHandler<ReqT, RespT> handler = methodDef.getServerCallHandler();
  for (ServerInterceptor interceptor : interceptors) {
    handler = InternalServerInterceptors.interceptCallHandler(interceptor, handler);
  }
  ServerMethodDefinition<ReqT, RespT> interceptedDef = methodDef.withServerCallHandler(handler);
  ServerMethodDefinition<?, ?> wMethodDef = binlog == null
      ? interceptedDef : binlog.wrapMethodDefinition(interceptedDef);
  return startWrappedCall(fullMethodName, wMethodDef, stream, headers, context, tag);
}
/**从不返回{@code null}*/
专用ServerStreamListener startCall(ServerStream,字符串fullMethodName,
ServerMethodDefinition methodDef、元数据头、,
Context.cancelablecontext,StatsTraceContext,statsTraceCtx,Tag-Tag){
//TODO(ejona86):我们是否应该更新fullMethodName以获得方法的规范路径?
statsTraceCtx.serverCallStarted(
新服务器CallInfo impl(
methodDef.getMethodDescriptor(),//使用原始方法描述符通知
stream.getAttributes(),
stream.getAuthority());
ServerCallHandler=methodDef.getServerCallHandler();
用于(服务器拦截器拦截器:拦截器){
handler=InternalServerInterceptors.interceptCallHandler(interceptor,handler);
}
ServerMethodDefinition interceptedDef=methodDef.withServerCallHandler(handler);
ServerMethodDefinition WMethod杰夫=binlog==null
?interceptedDef:binlog.wrapMethodDefinition(interceptedDef);
返回StartRappedCall(fullMethodName、wMethodDef、流、头、上下文、标记);
}
因此,当收到请求时,它执行从上次注册到前一个的拦截器链。 从处理程序执行响应时遵循相同的顺序

我想知道的是,它将遵循洋葱中间件模式,您可以显式地设置执行顺序(类似于servlet过滤器)。
我错过什么了吗?

没有办法设定顺序
ServerBuilder.intercept()
ServerInterceptors.intercept()
的一个方便版本,并且遵循相同的语义。有
ServerInterceptors.interceptForward()
以相反的方向运行它们,但是您不能有一个单独添加拦截器并同时支持两种形式的API

截取API有点混乱,因为它遵循洋葱原则,但洋葱围绕着服务。拦截器包装服务,因此应用的最后一个拦截器将首先执行

serviceDef=ServerInterceptors.intercept(serviceDef,
拦截器1,
拦截器2,
拦截器3);
//相当于
serviceDef=ServerInterceptors.intercept(serviceDef,interceptor1);
serviceDef=ServerInterceptors.intercept(serviceDef,interceptor2);
serviceDef=ServerInterceptors.intercept(serviceDef,interceptor3);
//gRPC服务器看到最后一个“serviceDef”,因此拦截器3是
//先打电话

否,您不能将执行顺序设置为javadoc状态。