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

Posted

技术标签:

【中文标题】Sling/OSGi 请求范围对象问题。如何访问过滤器和服务类中对象的相同实例(在相同的请求上下文中)?【英文标题】:Sling/OSGi request scope object issue. How can I access the same instance of the object in filter and service class (in same request context)? 【发布时间】:2021-07-05 16:29:32 【问题描述】:

我正在使用 OSGi DS 注释在 Sling 框架中工作。

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

问题:我似乎无法创建自己的“web 请求范围”osgi 组件。我尝试将其设置为原型服务范围,但它不起作用。下面是我认为 应该 工作的示例,但这不是因为在我的“服务”类中,我得到了 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 类,但这有点废话。

有人可以帮忙吗?

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

以上是关于Sling/OSGi 请求范围对象问题。如何访问过滤器和服务类中对象的相同实例(在相同的请求上下文中)?的主要内容,如果未能解决你的问题,请参考以下文章

Spring:如何将 HttpServletRequest 注入到请求范围的 bean 中?

有没有办法请求特定于存储桶的读取范围?

如何使请求绑定的数据在 Ktor 中全局可用?

如何在jsp的会话范围内存储请求对象

Django - 如何访问视图之外的请求对象?

如何在 Vuex 中通过 POST 请求发送状态数据?