2011-09-12 72 views
15

在我的Spring MVC webapp中,我有一個用於CRUD操作的通用RESTful控制器。並且每個具體控制器必須僅聲明@RequestMapping,例如/foo。通用控制器處理對/foo/foo/{id}的所有請求。Spring MVC控制器的繼承和路由

但是現在我需要編寫一個更復雜的CRUD控制器,它將獲得更多的請求參數或路徑變量,例如/foo/{date}/foo/{id}/{date}。因此,我擴展了我的通用CRUD控制器並且寫入超載的fetch(id, date)方法,該方法將同時處理{id}{date}。這不是問題。

但我還需要從基類派生的(資源絕不能提供/foo/{id}了,只在/foo/{id}/{date})「禁用」 fetch(id)實現。我想出的唯一想法是在我的具體控制器中重寫此方法,將其映射到假的uri上並返回null。但是這看起來很醜陋,因爲我們暴露了一些虛假的資源uri,而不是禁用它。可能有更好的做法?

任何想法?

//My generic CRUD controller 
public abstract class AbstractCRUDControllerBean<E, PK extends Serializable> implements AbstractCRUDController<E, PK> { 

    @RequestMapping(method=RequestMethod.GET) 
    public @ResponseBody ResponseEntity<E[]> fetchAll() { ... } 

    @RequestMapping(value="/{id}", method=RequestMethod.GET) 
    public @ResponseBody ResponseEntity<E> fetch(@PathVariable("id") PK id) { ... } 

    @RequestMapping(method=RequestMethod.POST) 
    public @ResponseBody ResponseEntity<E> add(@RequestBody E entity) { ... } 

    @RequestMapping(value="/{id}", method=RequestMethod.PUT) 
    public @ResponseBody ResponseEntity<E> update(@PathVariable("id") PK id, @RequestBody E entity) { ... } 

    @RequestMapping(value="/{id}", method=RequestMethod.DELETE) 
    public @ResponseBody ResponseEntity<E> remove(@PathVariable("id") PK id) { .. } 
} 

//Concrete controller, working with Foo entities 
@Controller 
@RequestMapping("/foo") 
public class FooControllerImpl extends 
     AbstractCRUDControllerBean<Foo, Long> implements FooController { 

    //ugly overriding parent's method 
    @RequestMapping(value="/null",method=RequestMethod.GET) 
    public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id) { 
    return null; 
    } 

    //new fetch implementation 
    @RequestMapping(value="/{id}/{date}", method=RequestMethod.GET) 
    public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id, @PathVariable("date") Date date) { .... } 

} 

回答

18

您是否試圖使用spring實現資源,球衣的子資源類型?這可能不是直接可能的。爲什麼不將它委派給他們,而不是將通用RESTful服務聲明爲控制器?

//My generic CRUD Operations 
public abstract class AbstractCRUDControllerBean<E, PK extends Serializable> implements AbstractCRUDController<E, PK> { 

    public ResponseEntity<E[]> fetchAll() { ... } 

    public ResponseEntity<E> fetch(@PathVariable("id") PK id) { ... } 

    public ResponseEntity<E> add(@RequestBody E entity) { ... } 

    public ResponseEntity<E> update(@PathVariable("id") PK id, @RequestBody E entity) { ... } 

    public ResponseEntity<E> remove(@PathVariable("id") PK id) { .. } 
} 

和委託在控制器中。

//Concrete controller, working with Foo entities 
@Controller 
@RequestMapping("/foo") 
public class FooControllerImpl extends 
     AbstractCRUDControllerBean<Foo, Long> implements FooController { 

    //we are interested in using fetchall but not others 
    @RequestMapping(method=RequestMethod.GET) 
    public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id) { 
    return fetchAll(); 
    } 

    //fetch with id and date 
    @RequestMapping(value="/{id}/{date}", method=RequestMethod.GET) 
    public @ResponseBody ResponseEntity<Foo> fetch(@PathVariable("id") PK id, @PathVariable("date") Date date) { .... } 

} 

另外,還可以根據這些參數太多的可用性映射方法,

@RequestMapping(value="/{id}/{date}", params={"param1","param2","!param3"}) 
public @ResponseBody ResponseEntity<E> customFetch(@PathVariable("id") PK id, 
      @PathVariable("date") Date date, @RequestParam("param1") String param1,     
      @RequestParam("param2") String param2) {...} 

當參數1和參數存在,參數3不存在這種方法圖/富/ ID /日。

+0

感謝您的意見。它非常適合我的需求。有時當你被困住時,你需要的每一件事都是改變一個觀點) – Nofate

+0

+1好答案,並且很好的解釋 – andyb