【问题标题】:Architectural Design of Restful API ServerRestful API 服务器的架构设计
【发布时间】:2012-05-29 20:16:32
【问题描述】:

我正在使用 Spring 3.1 / Hibernate / Jackson 创建一个 Restfull API 服务器。

我有一个“购买”控制器/模型/Dao。

我现在需要添加“标记”购买的功能。

因此,一个带有“tagId”和“tagName”的简单类链接回“Purchase”。
一个“Purchase”可以有多个“Tags”,一个“Tag”只能属于一个“Purchase”。

表示我必须添加的这个新的“标签”类的最佳方式是什么? IE。

  • 我是否应该将 purchaseId 属性添加到“标记”模型并以某种方式对其进行标注?
  • 我是否应该将“标签列表”属性添加到“购买”模型?
  • 我要创建一个“Tag”控制器,它是“PurchaseController”的子类吗?
  • 等等……

基本上,我正在寻找使用 Spring 进行设计的最佳实践方法。

此外,欢迎对我可以采用的设计模式提出任何建议。
也许装饰者模式在这里适用?

当然,所有购买和标签都必须保存到数据库中。

谢谢

采购总监:

@Controller
public class PurchaseController
{

    @Autowired
    private IPurchaseService purchaseService;

    @RequestMapping(value = "purchase", method = RequestMethod.GET)
    @ResponseBody
    public final List<Purchase> getAll()
    {
        return purchaseService.getAll();
    }

    @RequestMapping(value = "purchase/{id}", method = RequestMethod.GET)
    @ResponseBody
    public final Purchase get(@PathVariable("id") final Long id)
    {
        return RestPreconditions.checkNotNull(purchaseService.getById(id));
    }

    @RequestMapping(value = "purchase/tagged", method = RequestMethod.GET)
    @ResponseBody
    public final List<Purchase> getTagged()
    {
        return RestPreconditions.checkNotNull(purchaseService.getTagged());
    }

    @RequestMapping(value = "purchase/pending", method = RequestMethod.GET)
    @ResponseBody
    public final List<Purchase> getPending()
    {
        return RestPreconditions.checkNotNull(purchaseService.getPending());
    }

    @RequestMapping(value = "purchase", method = RequestMethod.POST)
    @ResponseStatus(HttpStatus.CREATED)
    public void create(@RequestBody final Purchase entity)
    {
        RestPreconditions.checkRequestElementNotNull(entity);
        purchaseService.addPurchase(entity);
    }
}

购买模式:

@Entity
@XmlRootElement
public class Purchase implements Serializable
{
    /**
     * 
     */
    private static final long serialVersionUID = 6603477834338392140L;

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private Long pan;

    public Long getId()
    {
        return id;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    public Long getPan()
    {
        return pan;
    }

    public void setPan(Long pan)
    {
        this.pan = pan;
    }
}

【问题讨论】:

    标签: spring oop design-patterns restful-architecture


    【解决方案1】:

    购买模式需要修改如下。

    @Entity
    public class Purchase implements Serializable
    {
    /**
     * 
     */
        private static final long serialVersionUID = 6603477834338392140L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        private Long pan;
    
        @OneToMany(mappedBy = "instance", fetch = FetchType.LAZY)
        private Set<Tag> tags;
    
        public Long getId()
        {
          return id;
        }
    
        public void setId(Long id)
        {
            this.id = id;
        }
    
        public Long getPan()
        {
            return pan;
        }
    
        public void setPan(Long pan)
        {
            this.pan = pan;
        }
    
        public void setTags(Set<Tag> tags){
            this.tags = tags;
        }
    
        @JsonIgnore
        public Set<Tag> getTags(){
            if(tags == null){
               tags = new LinkedHashSet<Tag>();
            }
            return tags;
        }
    }
    

    标签模型如下所示。

    @Entity
    public class Tag implements Serializable{
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Long id;
    
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumns({ @JoinColumn(name = "PURCHASE__ID", referencedColumnName = "ID") })
        private Purchase purchase;
    
        //Other attributes, getters and setters
    
       @JsonIgnore
       public Purchase getPurchase(){
           return this.purchase;
       }
    
    
    }
    

    如果 Purchase 拥有关系(父级),您可以在 PurchaseService 和 PurchaseController 中实现标签特定的方法,或者为标签实现单独的服务和控制器类。

    【讨论】:

    • 感谢 Firoz,这是我开始采用的方法。 @JsonIgnore 的原因是什么?
    • @JsonIgnore 是为了避免父子关系中的循环引用,而不是序列化延迟加载的属性(因为在持久化上下文之外调用延迟加载的属性的getter方法会导致异常)。
    【解决方案2】:

    您已经在购买控制器中包含“标记”概念:getTagged

    我将构建一个在 Purchase 模型中包含 List&lt;ITag&gt; Tags 属性的设计,因为这可能是在您当前的设计中实现它的最简单、最直接的方法。

    【讨论】:

      猜你喜欢
      • 2015-08-12
      • 2017-10-15
      • 1970-01-01
      • 1970-01-01
      • 2018-04-28
      • 2012-12-11
      • 1970-01-01
      相关资源
      最近更新 更多