[英]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
的實現?
上面的FooService
和BarService
類太相似了,以至於讓我的重用性保持沉默。
在我的資源類中很常見的就是這種模式
@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
,可以將其擴展為Foo
或Bar
。
但是,如果在同一服務上有另一個方法,也要具有相同的層次結構級別,例如/ foobar,則必須小心。 它應該有一個固定的標識符並且不使用花括號,否則您的路徑將無法正確匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.