簡體   English   中英

使用JAX-RS在REST服務中的可重用性

[英]Reusability in REST services with JAX-RS

我有一個簡單的類似REST的服務,已在JAX-RS中實現以維護Foo 它使用POST foos創建foos,列出具有GET foos並使用GET foo/42詳細說明給定的foo(其中42是給定foo的id)。

public class FooService {

  @POST
  @Path("/foos")
  public Foo create(Foo foo){
    entityManager.getTransaction().begin();
    entityManager.persist(foo);
    entityManager.getTransaction().commit();
    return foo;
  }

  @GET
  @Path("/foos")
  public List<Foo> get(){
        List<Foo> foos = //more-or-less generic JPA querying-code
        return foos;
  }

  @GET
  @Path("/foos/{id}")
  public Foo get(@PathParam("id") int id){
        Foo foo = //more-or-less generic JPA querying-code
        return foo;
  }
}

現在,如果我也有類似的服務來維護Bar ,我應該如何優雅地避免代碼重復?

public class BarService {

  @POST
  @Path("/bars")
  public Bar create(Bar bar){
    entityManager.getTransaction().begin();
    entityManager.persist(bar);
    entityManager.getTransaction().commit();
    return bar;
  }

  @GET
  @Path("/bars")
  public List<Bar> get(){
        List<Bar> bars = //more-or-less generic JPA querying-code
        return bars;
  }

  @GET
  @Path("/bars/{id}")
  public Bar get(@PathParam("id") int id){
        Bar bar = //more-or-less generic JPA querying-code
        return bar;
  }
}

唯一的區別是@Path批注中指定的路徑值。 由於此值應該是靜態的(在編譯時可見),因此無法創建如下的AbstracService類:

public abstract class AbstracService<X> {

  //abstrac static is not possible
  public abstract static final String PATH;

  @POST
  @Path(PATH)
  public X create(X entity){ ... }

  @GET
  @Path(PATH)
  public List<X> get(){ ... }

  @GET
  @Path(PATH + "/{id}")
  public X get(@PathParam("id") int id){ ... }
}


public class FooService extends AbstractService<Foo>{
      //just override the PATH to be "foos"
}    

public class BarService extends AbstractService<Bar>{
      //just override the PATH to be "bars"
}    

我是否需要重寫每個服務方法只是為了調整@Path並且它們調用super的實現?

上面的FooServiceBarService類太相似了,以至於讓我的重用性保持沉默。

在我的資源類中很常見的就是這種模式

@Path("foo")
public class FoosResource {
    @GET  // get all `Foo` resources
    ...
    @GET 
    @Path("{id}")  // get `Foo` with this id
    ...
    @POST // create new `Foo` in `foo` collection
    ...
    @PUT 
    @Path("{id}")  // Update `Foo` with this id
}

你明白了。 關鍵是集合的名稱在資源類上,而不是像您所擁有的那樣在資源方法級別上

@Path("foo/{id}")

無論如何,您都將需要一個@Path來使該類成為資源類,為什么不為其使用最合適的名稱。

我可能要添加的另一件事是我經常做的事情。 我在抽象類中添加一個Class字段,並帶有一個構造函數arg,我可以將該Class傳遞給該構造函數。 然后在具體的類實現中,我super(Foo.class) 這樣,JPA可以訪問該類,這使得使用類型查詢更容易。

好吧,我相信你可以做這樣的事情

@POST
@Path("/{foosOrBars}")//will match to any string
public BaseFooBar create(@PathParam("foosOrBars") String type){

if(type.equals("foos")){
//do something with the foo
}else{
//do something different
}

}

因此,您有一個基類BaseFooBar ,可以將其擴展為FooBar

但是,如果在同一服務上有另一個方法,也要具有相同的層次結構級別,例如/ foobar,則必須小心。 它應該有一個固定的標識符並且不使用花括號,否則您的路徑將無法正確匹配。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM