【问题标题】:CDI for incoming JSON deserialised POJOs用于传入 JSON 的 CDI 反序列化 POJO
【发布时间】:2020-10-14 10:37:21
【问题描述】:

我正在将 Payara 微服务用于 Java Web 应用程序,并希望将一个 bean 注入我的反序列化 JSON 对象,以便我可以添加执行一些额外的逻辑。

到目前为止,我已经有了用@Path 和@POST 注释的资源类,我通过 Postman 使用一些 JSON 调用它。该方法调用正常,但是无论我尝试什么,我都无法让 bean 注入。

JSON 对象的类如下所示:

public class IncomingJsonRequest {

    @NotNull
    private String value;

    private AdditionalLogicClass additionalLogicBean;

    public String setValue(String value) {
        this.value = value;
    }

    public void performAdditionalLogic() {
        additionalLogicBean.performLogic(value);
    }
}

我想做的是注入AdditionalLogicClass bean,这样当我从资源方法调用performAdditionalLogic() 方法时,它不会抛出空指针异常。

我已经尝试了各种注释,到目前为止,我似乎可以做到这一点的唯一方法是让资源类将 bean 传入,但这不是很好的封装。我不想让资源知道这个额外的逻辑是如何完成的。

另一种方式是以编程方式加载 bean,但我读到这不是一个好习惯。

实现这一目标的最佳方法是什么?

谢谢

【问题讨论】:

  • 将服务注入模型也不是好的做法。你为什么要那个?
  • 增加封装并且没有贫血的对象。对象的类具有调用附加逻辑所需的信息。如果我想将它推送到服务层,那么我必须制作吸气剂,而服务层必须协调这一切。这不是 Martin Fowler 所写的反模式,还是我误解了重点。
  • 我不是一个真正的模式/反模式人,更多的是实用的类型 ;-) 要使注入工作,您需要明确地“管理”类或通过配置隐式地符合条件注入(空构造函数要求)并且实例必须由管理它们的容器创建。那么它可能会起作用。
  • 来自martinfowler.com/bliki/AnemicDomainModel.html“同样值得强调的是,将行为放入域对象中不应与使用分层将域逻辑与持久性和表示责任等事物分离的可靠方法相矛盾。应该在域对象中的逻辑是域逻辑 - 验证、计算、业务规则 - 随便你怎么称呼它。(在某些情况下,你提出了将数据源或表示逻辑放在域对象中的论据,但那是与我对贫血的看法正交。)"
  • “所有这一切的一个混乱来源是许多 OO 专家确实建议在域模型之上放置一层过程服务,以形成服务层。但这不是一个使域模型没有行为的论点,实际上服务层倡导者将服务层与行为丰富的域模型结合使用。”所以幸运的是我做得对;-)只是从来没有需要在技​​术上由“服务”提供的域模型中使用复杂的(业务)逻辑。但是en.wikipedia.org/wiki/Anemic_domain_model 也包含有趣的信息('批评';-))

标签: java cdi payara


【解决方案1】:

使用程序化 CDI 方法,您可以通过以下方式实现它:

@Path("sample")
public class SampleResource {

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public Response message(MyPayload myPayload) {
        return Response.ok(myPayload.getName()).build();
    }

}

一个示例业务逻辑 CDI bean

public class BusinessLogic {
    public String doFoo(String name) {
        return name.toUpperCase();
    }
}

有效载荷:

public class MyPayload {

    private String name;
    private BusinessLogic businessLogic;

    public MyPayload() {
        this.businessLogic = CDI.current().select(BusinessLogic.class).get();
    }

    public String getName() {
        return businessLogic.doFoo(this.name);
    }

    public void setName(String name) {
        this.name = name;
    }
}

最后是beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_2_0.xsd"
       bean-discovery-mode="all">
</beans>

点击端点以大写形式返回预期的输入:

curl -v -d '{"name": "duke"}' -H 'Content-Type: application/json' http://localhost:9080/resources/sample
< HTTP/1.1 200 OK
< X-Powered-By: Servlet/4.0
< Content-Type: application/octet-stream
< Date: Thu, 02 Jul 2020 06:16:34 GMT
< Content-Language: en-US
< Content-Length: 4
< 
* Connection #0 to host localhost left intact
DUKE

这样你注入默认构造函数中的CDI bean,当它尝试序列化传入的有效负载时由JSON-B调用。

另一种方法是以编程方式加载 bean,但我读过 这不是一个好习惯。

不确定是否有任何其他解决方案可以实现这一点并让 CDI 容器处理注入。

【讨论】:

猜你喜欢
  • 2017-08-09
  • 2023-03-23
  • 2012-04-07
  • 2018-07-15
  • 1970-01-01
  • 1970-01-01
  • 2013-01-08
  • 2015-11-04
  • 1970-01-01
相关资源
最近更新 更多