2011-08-29 24 views
13

Spring MVCを使用してRESTful APIを構築しようとしています。私は、パッケージ構造がURL構造に従う、きれいで管理しやすいコードを作成しています。だからここSpring 3 MVC REST APIでRequestMappingsを継承する方法

は、私が持っているものである:これは動作しますが、私はそれが厄介とエラーが発生しやすい「繰り返す必要を見つける

// com.test.api.library 
@RequestMapping("/library/{libraryId}") 
public Library getLibrary(@PathVariable long libraryId) { 
    return service.getLibraryById(libraryId); 
} 

// com.test.api.library.book 
@RequestMapping("/library/{libraryId}/book/{bookId}") 
public Book getBook(@PathVariable long libraryId, @PathVariable long bookId) { 
    Library library service.getLibraryById(libraryId); 
    return library.getBookById(bookId); 
} 

/ライブラリ/ {libraryId}すべての継承された@RequestMappingsでは、/ libraryはAPIの大きな部分を根ざしている可能性があり、一度書き込んですべての場所に書き込むのではなく、再利用する必要があります。

私はこのような何かにブッククラスを書き換えるしたいと思います:

// com.test.api.library.book 
@RequestMapping("/book/{bookId}") 
public Book getBook(@PathVariable long bookId) { 
    // long libraryId magically given to me from the library-class's getLibrary() 

    Library library service.getLibraryById(libraryId); 
    return library.getBookById(bookId); 
} 

は、春はここに私を助けることができる方法はありますか?私が書いたすべてのURLの一部として "/ library/{libraryId}"を書き込まないようにするために、通常のJava継承、春の注釈などを使用することは可能です。

答えて

1

私は考えられません。しかし、クラス自体に@RequestMapping注釈を付けることができるので、少なくともいくつかの入力を省くことができます。

+0

ええ、私はその可能性を認識することだし、それはただのメソッドが、まだ完璧からの長い道のりに注釈を付けるよりもずっといいです。 –

+0

あなたの応答に基づいて、完全にはっきりしていない私からあなたが望むものまで、長い道のりです。おそらく、いくつかのリソースの完全なURLを表示し、どのコントローラを処理するかを記述できますか? – SingleShot

+0

これは奇妙な例かもしれませんが... '/国/ {countryCode} /都道府県/ {cityCode}/street/{streetCode}/number/{streetNumber}' それぞれこれらの手順(国、州、市、市区町村、市町村、市町村、市区町村、市町村番号など)は、それ自身のコントローラに移動し、それぞれに動詞のサブセットがあります。主な質問は、私が国からすべての方法でURLを繰り返さないようにnumberControllerを行うときです。私はcountryCodeがこのリソースの鍵であることを「知っている」ことを「知っている」わけではありません。私はちょうどそれを "持っている"ようにしたい。 –

-1
@Controller 
@RequestMapping("/library/{libraryId}") 
public class HelloWorldController { 

    @RequestMapping(value="/book/{bookId}") 
    public ModelAndView helloWorld() { 
     .... 
    } 

} 
+0

それは私の質問に答えません。私はこの可能性をよく承知している(もしBozhoによって与えられた答えで何も指摘されていなければ)。このようにすることは、すべてのサブレポートを図書館に同じコントローラに入れなければならないことを意味します。それはもちろん可能ですが、私が求めていることではありません。とにかくありがとうございます。 –

4

私はこの質問をする前に答え&を依頼されていると信じて:言ったSpring MVC @RequestMapping Inheritance

、ここでは重複する情報の量を減らすための1つの方法です。コードの隣にURIを置くことは、たとえそれが少し重複していても、より保守的であると思うので、私は自分のコードでこれを実際に行いません。

@RequestMapping(URI_LIBRARY) 
public interface LibraryNamespace { 
    public static String URI_LIBRARY = "/library/{libraryId}"; 
} 

@RequestMapping(URI_BOOK) 
public interface BookNamespace { 
    public static String URI_BOOK = LibraryNamespace.URI_LIBRARY + "/book/{bookId}"; 
} 

@Controller 
public class LibraryController implements LibraryNamespace { 
    @RequestMapping("") 
    public Library get(@PathVariable long libraryId) { 
    return service.getLibraryById(libraryId); 
    } 
} 

@Controller 
public class BookController implements BookNamespace { 
    @RequestMapping("") 
    public Book get(@PathVariable long libraryId, @PathVariable long bookId) { 
    Library library service.getLibraryById(libraryId); 
    return library.getBookById(bookId); 
    } 
} 

私はこのアプローチを自分でとらないので、実際にはこの解決策を試していません。私の春の理解に基づいて、私はそれがうまくいくはずだと思います...

+0

私は答えが「いいえ、それはできません」と考え始めています。あなたのアイデアは抽象レベルを追加しますが、ライブラリクラスの近くの「@PathVariable long libraryId」を扱う主な問題は解決しません。私が相続するために使用され、親クラスのハンドルをさせることは自身の変数だとちょうどサブクラスがそれらに固有のものを扱うせるよ「ノーマル」Javaから来る 。とにかくありがとうございます。 –

+0

これはできません。申し訳ありませんが、私はここでこれをより明確にしませんでした。私はリンク先の質問/回答が十分に分かりやすいと思った。 – jtoberon

+0

私はこれをしました。このアプローチを多相親アプローチと組み合わせると、DRYパスと分離分離引数を得ることができます。私は自分のコードを掘り下げて回答を投稿します。 – Alex

3

多型の親のアプローチを使用してください。

@Controller 
public class CommentsController { 
    @RequestMapping(value="/comments", method = RequestMethod.GET) 
    public @ResponseBody String index() { 
     /* kludge to allow optional path parameters */ 
     return index(null, null); 
    } 

    @RequestMapping(value="/{parent_collection}/{parent_id}/comments", method = RequestMethod.GET) 
    public @ResponseBody String index(@PathVariable("parent_collection") String parentCollection, @PathVariable("parent_id") String parentId) { 
     if (parentCollection == null) { 
      return "all comments"; 
     } 
     else if ((parentCollection != null) && (parentCollection.equals("posts"))) { 
      /* get parent, then get comments for parent */ 
      return "comments for single post"; 
     } 
     else if ((parentCollection != null) && (parentCollection.equals("customers"))) { 
      /* get parent, then get comments for parent */ 
      return "comments for single customer"; 
     } 
     else if ((parentCollection != null) && (parentCollection.equals("movies"))) { 
      /* get parent, then get comments for parent */ 
      return "comments for single movie"; 
     } 
    } 

    @RequestMapping(value = "/comments/{id}", method = RequestMethod.GET) 
    public @ResponseBody String show(@PathVariable Integer id) { 
     /* kludge to allow optional path parameters */ 
     return show(null, null, id); 
    } 

    @RequestMapping(value = "/{parent_collection}/{parent_id}/comments/{id}", method = RequestMethod.GET) 
    public @ResponseBody String show(@PathVariable("parent_collection") String parentCollection, @PathVariable("parent_id") String parentId, @PathVariable Integer id) { 
     /* get comment, then get parent from foreign key */ 

     if (parentCollection == null) { 
      return "single comment"; 
     } 
     else if ((parentCollection != null) && (parentCollection.equals("posts"))) { 
      return "single comment for single post"; 
     } 
     else if ((parentCollection != null) && (parentCollection.equals("customers"))) { 
      return "single comment for single customer"; 
     } 
     else if ((parentCollection != null) && (parentCollection.equals("movies"))) { 
      return "single comment for single movie"; 
     } 
    } 
} 

また、あなたは、親リソース(/libraries/{library_id}/../..)にルーティングするURI接頭辞をベースコントローラを使用して、リクエストスコープに親モデルを追加し、定期的な要求のマッピングがにURIの残りの部分を処理させることができ子リソース(/../../books/1)。私はこのオフハンドの例はありません。

サイドノート。単数形のネストされたリソースは、一般にURI設計の反パターンとみなされます。コントローラは、独自のリソースを処理する必要があります。最も一般的なインプリメンテーションは、特異なネストされたリソースの鍵を一意的に、すなわちその親リソースに依存しないようにする。たとえば、データベースレコードの主キー。しかし、序数や位置の値(例えば、第1章、第1章、第2章)や自然なキー(例えば、ISBN本、SSN人、Eメールアドレス、ユーザー名、ファイル名)。ネストされたリソースのための標準的なURIの

例:

  • /articles => ArticlesControllerの#インデックス
  • /articles/1 => ArticlesController番号を示し
  • /articles/1/comments => CommentsController#インデックス
  • /articles/1/comments/2 => CommentsController# show(大丈夫ですが、好きではありません)
  • /comments/2 => CommentsController#show )
関連する問題