将 servlet 引用为 OSGI 组件是一种好习惯吗?

Is it a good practice to reference servlet as OSGI component?

在我的项目中,我们有几个 servlet 是 osgi 组件并且具有与其相关的属性。喜欢

@Component(label = "Default Address Servlet", immediate = true)
@Service(value = Servlet.class)
@Properties(
    @Property(name = "sling.servlet.resourceTypes", value = { "sling/servlet/default" }),
    @Property(name = "sling.servlet.selectors", value = { "defaultaddress" }),
    @Property(name = "sling.servlet.extensions", value = { "json" }),
    @Property(name = "sling.servlet.methods", value = { "POST" }), 
    @Property(name = "prop1", value = { "value1" }) })
public class SetDefaultAddressServlet extends SlingAllMethodsServlet {

现在我需要在加载组件期间在吊索模型 class 中使用此 prop1。虽然从技术上讲 servlet 是 osgi 组件,但可以将此 servlet 引用为 osgi 组件吗?喜欢

@Model(adaptables = SlingHttpServletRequest.class)
public class Address {

    @Inject
    @Reference
    private SetDefaultAddressServlet service;

虽然这在技术上是可行的,但这是一个好方法吗?或者,我需要使用各自的 属性 创建单独的 OSGi 服务并引用它。什么是可取的方法?

这是一个哲学问题,而不是技术问题,因为没有人能给你 100% 的正确答案,但我会把我的意见放在那里。

我更喜欢将六边形架构应用到我的代码中 (original post on this pattern or another great one),这会为您的应用程序带来高可维护性。

其主要思想之一是依赖项应指向内部 - 因此外部世界取决于您的 servlet,servlet 取决于您的业务层。

Servlet 在这里可以被视为外部世界和您的业务逻辑之间的适配器。 Sling 模型是一样的 - 它位于您的 html 页面和服务之间。

根据这种设计模式,从一个适配器引用另一个适配器是个坏主意。

另外,还有一盏灯code smell:这些class需要这个属性做什么?需要相同 属性 的代码是否应该放在两个不同的地方,而不是放在一个小的 Util class 或服务中?

再次重申,这只是我的意见。

补充一下其他用户之前的回答,考虑到它不是可靠的代码架构方法,在 AEM 上下文中,这也不是一个好方法。

您的模型(地址)依赖于服务实现。一个 servlet 中有很多与 HTTP 请求相关的信息,通常这个模型不需要访问 HTTP servlet 中的所有大量信息。

您可能希望在 HTTP 请求中访问一些有限的属性集并将它们转换为 POJO 模型,这些属性可以是请求信息的一部分。在这种情况下,您最好从 HttpRequest 或一些可以从您的请求中提取的以价值为中心的对象制作一个自适应对象。

另外,想想其他用户指出的code-smells。是什么阻止了 Address 对象在引用的 class 上调用 Servlet 方法并修改请求的状态(如访问会话等)

同样,它有效,但它不是最好的方法,因为只要将其限制为 AEM 最佳实践就有更好的方法。我建议您阅读以下文章:

https://sling.apache.org/documentation/bundles/models.html

希望对您有所帮助