【问题标题】:spring boot dynamic object modellingspring boot 动态对象建模
【发布时间】:2018-03-03 09:34:50
【问题描述】:

我正在使用 Spring Boot 创建一个 RESTful API。我有需要向资源提出请求的要求

/用户/通知

通知资源将接受 bodyrequest 中的值并将通知发送给用户。

@ResponseBody
@RequestMapping(value = "/user/notification", method = RequestMethod.POST)
public NotificationResponse sendNotification(@Valid @RequestBody NotificationRequest notificationRequest){
  // here is code where I need to build right
  // object of type text/file/link/map (please read full question below)
   notificationService.send(notificationRequest.getUsername(), object);
}

它接受:用户名和通知数据。这是 NotificationRequest 类:

public class NotificationRequest {

  @NotEmpty
  private String username;

  @NotEmpty
  private String type;

  private String title;

  @NotEmpty
  private String content;

  private String url;

  private String longitude;

  private String latitude;

  private String file_url;

 //getters and setters
 }

我有 4 种类型的通知,即。文本、链接、地图和文件。它们的属性就是这些。

text
  - type
  - title
  - content

link
  - type
  - title
  - content
  - url

map
 - type
 - title
 - longitude
 - latitude

file
 - type
 - title
 - content
 - file_url

我为这些创建了 4 个类,所以我可以创建正确的对象,如您所见,typetitle 是常见的属性,所以我使用了继承。

public class NotificationBase {
  private String type;
  private String title;
  //getters and setters here
 }

并像这样扩展了其他 4 个类。

 public class TextNotification extends NotificationBase {
    private String content; 
   //getters and setters here
 }

我的问题是,我如何创建我的类,以便

如果有人想发送文本通知,我可以得到一个 TextNotification 对象,如果有人想发送文件通知,我可以创建 FileNotification 对象吗?

注意:请注意,在这种情况下,我不想使用 gJson 或 Jackson 创建 JSON 对象。

如果我需要在此处添加更多信息,请告诉我。

【问题讨论】:

  • type 的属性是 NotificationRequest 的实际类型(文本、地图等)吗?如果是这样,只需根据该类型进行实例化。否则,您可以将通知类型作为 url 上的查询参数。您可以根据需要将创建过程抽象为工厂或其他东西,但这是最简单的解决方案

标签: java oop spring-boot


【解决方案1】:

您可以使用jackson 注释进行子类型化。在您的情况下,您有字段 type 将表示您期望的对象的类型。

所以最好有一个抽象的NotificationRequest 类,只包含所需的字段:

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
    @JsonSubTypes({
            @JsonSubTypes.Type(value = TextNotificationRequest.class, name = "text"),
            @JsonSubTypes.Type(value = LinkNotificationRequest.class, name = "link")})
public abstract class NotificationRequest {

  @NotEmpty
  private String username;

  @NotEmpty
  private String type;

  private String title;

  public abstract NotificationResponse buildNotificationResponse();
}

以及您需要的每种类型的实现。

public class TextNotificationRequest extends NotificationRequest {
 public String content;

 public NotificationResponse buildNotificationResponse{
   return new TextNotificationResponse(content);
 }
}

现在你可以做这样的事情

@ResponseBody
@RequestMapping(value = "/user/notification", method = RequestMethod.POST)
public NotificationResponse sendNotification(@Valid @RequestBody NotificationRequest notificationRequest){
   NotificationResponse response = notificationRequest.buildNotificationResponse();
   notificationService.send(notificationRequest.getUsername(), response);
}

这里有一些解释。通过设置这些注释,您可以告诉jackson 要根据type 字段的值实例化哪个类。如果type == "text" jackson 将实例化TextNotificationRequest 等等。现在您可以利用多态性的力量来创建NotificationResponse 并避免if-else 语句。

另外jackson 不仅允许基于字段值进行子类型化。你可以在这里阅读更详细的信息@JsonTypeInfo

【讨论】:

    猜你喜欢
    • 2021-07-16
    • 1970-01-01
    • 2016-05-28
    • 1970-01-01
    • 2019-11-22
    • 1970-01-01
    • 2019-08-06
    • 2023-03-25
    • 2017-06-12
    相关资源
    最近更新 更多