问题描述
我正在使用带有 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 在消费者端进行配置,并指定应如何解析服务引用。有三个可能的值:
捆绑 捆绑包中的所有组件实例都将使用相同的服务对象。 (默认) 原型 捆绑包中的每个组件实例都可以使用不同的服务对象。 原型_必需 捆绑包中的每个组件实例都必须使用不同的服务对象。