Sling/OSGi 请求范围对象问题如何访问过滤器和服务类中对象的相同实例在相同的请求上下文中?

问题描述

我正在使用带有 Osgi DS 注释的 Sling 框架工作。

背景:我正在使用微服务。当我们在它们之间发送调用时,我们会传递并记录一个“事务 ID”(它只是一个 UUID)。这样我们就可以轻松地跟踪所有不同服务之间的调用。这意味着每个 Web 请求都有不同的 UUID。我们通常使用 Spring Boot,但在这种情况下,我使用 Sling 在 AEM 中。

问题:我似乎无法创建自己的“网络请求范围”osgi 组件。我尝试将其设置为 Prototype 服务范围,但它不起作用。下面是一个我认为应该工作的例子,但这不是因为在我的“服务”类中,我得到了 RequestInfo 类的不同实例,而不是从当我在 Filter 类中获取实例时。

请求范围对象:

@Component(service = RequestInfo.class,scope = ServiceScope.PROTOTYPE)
public class RequestInfo {
     private String transactionId;
     ...
}

过滤器:

@Component(service = Filter.class,immediate = true,property = { sling.filter.scope=REQUEST })
@ServiceRanking(0)
public class RequestInfoFilter implements Filter {
     @Reference(scope = ReferenceScope.PROTOTYPE_required)
     private RequestInfo requestInfo;

     @Override
     public void doFilter(ServletRequest baseRequest,ServletResponse baseResponse,FilterChain filterChain) {
          HttpServletRequest request = (HttpServletRequest) baseRequest;
          HttpServletResponse response = (HttpServletResponse) baseResponse;
          requestInfo.setTransactionId(...);
          filterChain.doFilter(request,response);
     }
     ...
}

服务类:

@Component(service = MyService.class,immediate = true)
public class MyService {
     @Reference(scope = ReferenceScope.PROTOTYPE_required)
     private RequestInfo requestInfo; <--- Does not pick up same instance of RequestInfo that filter had!!! Why??? It's still in the context of the same request!!!

     public String callAnotherService {
          String transactionID = requestInfo.getTransactionId();
          ... add ID as header and call another service with httpclient ...
     }
 }

其他尝试的解决方案:

  • 我尝试在组件内引用 SlingHttpServletRequest 对象,但它不起作用,除非我扩展 SlingallMethodsServlet,这不适用于服务类。
  • 我尝试设置一个 SlingModel 来保存请求中的信息,但后来我不知道如何将该 SlingModel 的实例拉入 Osgi 组件中。

我不喜欢的后备解决方案:
我可以在我的 Servlet 中提取事务 ID 并在所有不同的类/方法之间传递,直到我到达 Service 类,但这有点废话。

有人可以帮忙吗?

解决方法

也许这会帮助你http://blog.vogella.com/2017/02/13/control-osgi-ds-component-instances/

将服务组件的范围设置为 PROTOTYPE 并不意味着每个消费者都会自动获得一个不同的服务实例。默认情况下,结果将与使用 BUNDLE 范围相同。因此,如果您使用更新后的 Hitman 服务启动应用程序,您将获得与之前相同的结果。 这样做的原因是 DS 1.3 也引入了参考范围。它通过@Reference 在消费者端进行配置,并指定应如何解析服务引用。有三个可能的值:

捆绑 捆绑包中的所有组件实例都将使用相同的服务对象。 (默认) 原型 捆绑包中的每个组件实例都可以使用不同的服务对象。 原型_必需 捆绑包中的每个组件实例都必须使用不同的服务对象。