PlayでRESTful!フレームワーク


117

モバイルアプリにコンテンツを提供するプロジェクトを計画していますが、ウェブサイトが必要です。

私の質問は、JerseyまたはRestletを使用してモバイルアプリ用のREST APIを開発し、次にPlayを使用するのが理にかなっているかどうかです。ウェブサイトを提供する。

または、Playを使用する方が理にかなっていますか?それをすべて行うには?もしそうなら、PlayでRESTを実行する方法!フレームワーク?

回答:


112

リクエストに応じて、シンプルなRESTのようなアプローチ。これは、Codemwncisのソリューションとほぼ同じように機能しますが、コンテンツネゴシエーションにAcceptヘッダーを使用します。最初にroutesファイル:

GET     /user/{id}            Application.user
POST    /user/                Application.createUser
PUT     /user/{id}            Application.updateUser
DELETE  /user/{id}            Application.deleteUser

ここではコンテンツタイプを指定しません。これは、特定のリソースに「特別な」URIが必要な場合にのみ必要です。へのルートを宣言するように/users/feed/、常にAtom / RSSに戻ります。

アプリケーションコントローラは次のようになります。

public static void createUser(User newUser) {
    newUser.save();
    user(newUser.id);
}

public static void updateUser(Long id, User user) {
    User dbUser = User.findById(id);
    dbUser.updateDetails(user); // some model logic you would write to do a safe merge
    dbUser.save();
    user(id);
}

public static void deleteUser(Long id) {
    User.findById(id).delete();
    renderText("success");
}

public static void user(Long id)  {
    User user = User.findById(id)
    render(user);
}

ご覧のとおり、getUserJSONメソッドのみを削除し、getUserメソッドの名前を変更しました。さまざまなコンテンツタイプを機能させるには、いくつかのテンプレートを作成する必要があります。目的のコンテンツタイプごとに1つ。例えば:

user.xml:

<users>
  <user>
    <name>${user.name}</name>
    . . .
  </user>
</users>

user.json:

{
  "name": "${user.name}",
  "id": "${user.id}",
  . . . 
}

user.html:

<html>...</html>

すべてのブラウザがAcceptヘッダーでtext / htmlコンテンツタイプを送信するため、このアプローチではブラウザに常にHTMLビューが提供されます。他のすべてのクライアント(おそらくJavaScriptベースのAJAXリクエスト)は、独自の必要なコンテンツタイプを定義できます。jQuerys ajax()メソッドを使用すると、次のことができます。

$.ajax({
  url: @{Application.user(1)},
  dataType: json,
  success: function(data) {
    . . . 
  }
});

JSON形式のID 1のユーザーに関する詳細が表示されます。Playは現在HTML、JSON、XMLをネイティブでサポートしていますが、公式のドキュメントに従うか、コンテンツネゴシエーションモジュールを使用することで、別のタイプを簡単に使用できます

開発にEclipseを使用している場合は、ルートとそれに対応するコンテンツタイプをテストできるRESTクライアントプラグインを使用することをお勧めします。


2
これを投稿してくれてありがとう。遊び!ドキュメントは、物事の基本的な構造を説明するために私が見た中で最高のものの一部ですが、詳細な例では時々欠けています。同じ例で2つのアプローチを示すことで、状況が明確になります。
Brad Mace、

私はあなたの例を試しています、投稿されたJSONデータがUserクラスに変換される場所に興味があります。たとえば、createUser関数内では、newUserがnullであることがわかります。
Gary、

2
@Gary:たぶん "newUser"の代わりに "user"を使用したのですか コントローラの名前とフォームパラメータは一致する必要があります。github.com/sebhoss/play-user-sample
seb

おかげで、私は、JSON文字列を送信するためにカールを使用してそれをテストし、そのプレイフレームワークは、アプリケーション/ JSONコンテンツタイプを認識しませんでした表示されます。groups.google.com/group/play-framework/browse_thread/thread/...
ゲイリー

@ゲイリー:ヒントをありがとう!...それはマスターブランチに固定されている、あなたはそれを自分で構築しようとし、再度テストすることができそうです
SEB

68

これはまだ人気のある質問ですが、投票数の多い回答は現在のバージョンのPlayでは最新ではありません。次に、play 2.2.1を使用したRESTの動作例を示します。

conf / routes:

GET     /users                 controllers.UserController.getUsers
GET     /users/:id             controllers.UserController.getUser(id: Long)
POST    /users                 controllers.UserController.createUser
PUT     /users/:id             controllers.UserController.updateUser(id: Long)
DELETE  /users/:id             controllers.UserController.deleteUser(id: Long)

app / controllers / UserController.java:

public static Result getUsers()
{
    List<User> users = Database.getUsers();
    return ok(Json.toJson(users));
}

public static Result getUser(Long id)
{
    User user = Database.getUser(id);
    return user == null ? notFound() : ok(Json.toJson(user));
}

public static Result createUser()
{
    User newUser = Json.fromJson(request().body().asJson(), User.class);
    User inserted = Database.addUser(newUser);
    return created(Json.toJson(inserted));
}

public static Result updateUser(Long id)
{
    User user = Json.fromJson(request().body().asJson(), User.class);
    User updated = Database.updateUser(id, user);
    return ok(Json.toJson(updated));
}

public static Result deleteUser(Long id)
{
    Database.deleteUser(id);
    return noContent(); // http://stackoverflow.com/a/2342589/1415732
}

また、sebのAnswerの更新バージョンも見たいのですが、残念ながら、あなたの回答では.xmlと.htmlのマジックがすべて削除されています。:-(
flaschenpost

26

Playを使用してください!それをすべて行う。PlayでRESTサービスを書くのはとても簡単です。

まず、routesファイルを使用すると、RESTアプローチに準拠したルートを簡単に記述できます。

次に、作成するAPIメソッドごとに、コントローラーでアクションを記述します。

結果を返す方法(XML、JSONなど)に応じて、使用できるメソッドがいくつかあります。たとえば、renderJSONメソッドを使用すると、結果を非常に簡単にレンダリングできます。XMLをレンダリングしたい場合は、ビューでHTMLドキュメントを作成するのと同じ方法で行うことができます。

ここにきちんとした例があります。

ルートファイル

GET     /user/{id}            Application.getUser(format:'xml')
GET     /user/{id}/json       Application.getUserJSON
POST    /user/                Application.createUser
PUT     /user/{id}            Application.updateUser
DELETE  /user/{id}            Application.deleteUser

アプリケーションファイル

public static void createUser(User newUser) {
    newUser.save();
    renderText("success");
}

public static void updateUser(Long id, User user) {
    User dbUser = User.findById(id);
    dbUser.updateDetails(user); // some model logic you would write to do a safe merge
    dbUser.save();
    renderText("success");
}

public static void deleteUser(Long id) {
    // first check authority
    User.findById(id).delete();
    renderText("success");
}

public static void getUser(Long id)  {
    User user = User.findById(id)
    renderJSON(user);
}

public static void getUserJSON(Long id) {
    User user = User.findById(id)
    renderJSON(user);
}

getUser.xmlファイル

<user>
   <name>${user.name}</name>
   <dob>${user.dob}</dob>
   .... etc etc
</user>

Acceptヘッダーに基づいて適切なgetUserメソッドを選択することは可能ですか?
TimoWestkämper10年

それは確かですが、完全に信頼できるわけではありません。ヘッダーがJSONリクエストであることをplayが知っている場合、playはgetuser.jsonファイルをレンダリングしようとします。ヘッダーがxmlの場合、getuser.xmlを試します。ただし、ユーザー/ User / {id} / typeの方が理解しやすく、RESTに似ています
Codemwnci

29
URIで表現タイプを明示的に指定することは、RESTのようではないと思います。Acceptヘッダーを直接使用し、URIは変更しないでください。見たいリソースは同じままです。上記の例は、現在の実装とまったく同じように動作する単一のgetUser(Long id)メソッドを持つように書き換えることができますが、getUserJSON、getUserXMLなどを定義する代わりに、getUser.jsonおよびgetUser.xmlテンプレートを定義します。私もそれをuser.json / user.xmlに名前を変更します
seb

ありがとう、これはとても役に立ちます。感謝します!
Gary

1
@seb-コメントを回答に拡張できますか?あなたが説明するテクニックの例を見てみたい
Brad Mace

5

JAX-RS実装との統合は、Playの組み込みのHTTPルーティングを使用するための可能な代替アプローチです。RESTEasyの例については、RESTEasy Playをご覧くださいモジュール

このアプローチは、すでにJAX-RSに投資している場合、またはコンテンツネゴシエーションなど、JAX-RSが提供するRESTの高度な機能が必要な場合に適しています。そうでない場合は、Playを直接使用して、HTTPリクエストに応答してJSONまたはXMLを提供する方が簡単です。



2

このアプローチはPlayバージョン1.2.3では壊れているようです。@sebによって行われ、前述のhttps://github.com/sebhoss/play-user-sampleで言及されているソースをダウンロードした場合、POSTとJSONオブジェクトを使用して新しいユーザーオブジェクトを作成することはできなくなります。

jsonおよびxmlのPOSTを使用して作成するための特定のメソッドが必要です。ここで概説:https ://groups.google.com/forum/#!topic/play-framework/ huwtC3YZDlU

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.