2011-09-12 485 views
15

私のSpring MVC webappには、CRUD操作用の汎用RESTfulコントローラがあります。そして、各コンクリートコントローラは@RequestMappingだけを宣言しなければなりませんでした。例えば、/fooです。汎用コントローラはすべての要求を/foo/foo/{id}に処理しました。Spring MVCコントローラの継承とルーティング

しかし、私はもう少し複雑なCRUDコントローラを書く必要があります。これは追加のリクエストパラメータやパス変数を取得します。たとえば/foo/{date}/foo/{id}/{date}です。だから私は一般的なCRUDコントローラを拡張し、{id}{date}の両方を扱うオーバーロードされたfetch(id, date)メソッドを書きます。それは問題ではない。

でも、基本クラスから派生したfetch(id)実装を無効にする必要があります(リソースは/foo/{id}でもう利用できないようにしてください。/foo/{id}/{date}のみ)。私が思いついた唯一のアイデアは、具体的なコントローラーのこのメソッドをオーバーライドして、偽の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

スプリングを使用して、ジャージのサブリソースタイプを達成しようとしていますか?それは直接可能ではないかもしれません。ジェネリック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) {...} 

のparam1とPARAM2が存在し、param3が存在しないこのメソッドマップ/ fooの/ ID /日付。

+0

ありがとうございます。それは私のニーズに非常によく合います。時々あなたが立ち往生しているときに、必要なものは視点を変えることです) – Nofate

+0

+1良い答えとよく説明されています – andyb

関連する問題