Play에서 RESTful! 뼈대


117

주로 모바일 앱에 콘텐츠를 제공하는 프로젝트를 계획하고 있지만 웹 사이트가 필요합니다.

제 질문은 Jersey 또는 Restlet을 사용하여 모바일 앱용 REST API를 개발 한 다음 Play를 사용하는 것이 합리적입니까? 웹 사이트를 제공합니다.

아니면 그냥 Play를 사용하는 것이 더 합리적입니까? 다할까요? 그렇다면 Play로 REST를 수행하는 방법! 뼈대?

답변:


112

요청에 따라 간단한 REST 방식입니다. Codemwncis의 솔루션이 작동하는 방식과 거의 동일하지만 콘텐츠 협상에 Accept 헤더를 사용합니다. 먼저 경로 파일 :

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

여기에 콘텐츠 유형을 지정하지 않습니다. IMHO는 특정 리소스에 대한 "특별한"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 메서드의 이름을 변경했습니다. 다양한 콘텐츠 유형이 작동하려면 이제 여러 템플릿을 만들어야합니다. 원하는 각 콘텐츠 유형에 대해 하나씩. 예를 들면 :

user.xml :

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

user.json :

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

user.html :

<html>...</html>

이 접근 방식은 모든 브라우저가 Accept 헤더에 텍스트 / 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
게시 해 주셔서 감사합니다. 플레이! 문서는 사물의 기본 구조를 설명하기 위해 내가 본 것 중 최고이지만 때로는 자세한 예제가 부족합니다. 동일한 예제에서 두 가지 접근 방식을 시연하면 문제가 해결됩니다.
Brad Mace

귀하의 예제를 시도하고 있는데 게시 된 JSON 데이터가 User 클래스로 변환되는 위치가 궁금합니다. 예를 들어, createUser 함수 내부에서 newUser가 null이라는 것을 알았습니다.
Gary

2
@Gary : "newUser"대신 "user"를 사용 하셨나요? 컨트롤러의 이름과 양식 매개 변수가 일치해야합니다. github.com/sebhoss/play-user-sample
seb

감사합니다. curl을 사용하여 JSON 문자열을 전송하여 테스트했는데 play 프레임 워크가 application / json 콘텐츠 유형을 인식하지 못하는 것 같습니다. groups.google.com/group/play-framework/browse_thread/thread/…
Gary

@Gary : 힌트 주셔서 감사합니다! 마스터 브랜치에서 수정 된 것 같습니다. 직접 빌드 한 다음 다시 테스트 할 수 있습니다.
seb

68

이것은 여전히 ​​인기있는 질문이지만 가장 많이 득표 한 답변은 현재 버전의 플레이와 최신이 아닙니다. 다음은 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의 답변의 업데이트 된 버전을보고 싶지만 불행히도 귀하의 답변은 모든 .xml 및 .html 마법을 제거했습니다. :-(
flaschenpost

26

플레이를 사용하세요! 모든 것을 할 수 있습니다. Play에서 REST 서비스를 작성하는 것은 매우 쉽습니다.

첫째, 경로 파일을 사용하면 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 메소드를 선택할 수 있습니까?
Timo Westkämper 2010

하지만 완전히 신뢰할 수있는 것은 아닙니다. play가 헤더가 JSON 요청임을 알고 있으면 getuser.json 파일을 렌더링하려고합니다. 헤더가 xml이면 getuser.xml을 시도합니다. 그러나 사용자 / User / {id} / type
Codemwnci

29
URI에서 표현 유형을 명시 적으로 지정하는 것이 더 REST와 비슷하다고 생각하지 않습니다. Accept 헤더를 직접 사용하고 보려는 리소스가 동일하게 유지되므로 URI를 변경하지 않는 것이 좋습니다. 위의 예제는 현재 구현과 정확히 동일한 단일 getUser (Long id) 메서드를 갖도록 다시 작성할 수 있지만 getUserJSON, getUserXML 등을 정의하는 대신 getUser.json 및 getUser.xml 템플릿을 정의합니다. user.json / user.xml로 이름을 변경했지만
seb

감사합니다. 매우 도움이됩니다. 감사합니다!
Gary

1
@seb-댓글을 답으로 확장 할 수 있습니까? 난 당신이 설명하는 기술의 예를보고 싶어요
브래드 메이스

5

JAX-RS 구현과 통합하는 것은 Play의 기본 제공 HTTP 라우팅을 사용하는 가능한 대안입니다. RESTEasy 예제는 RESTEasy Play! 모듈 .

이 접근법은 이미 JAX-RS에 투자했거나 컨텐츠 협상과 같이 JAX-RS가 제공하는 고급 기능 REST 중 일부가 필요한 경우에 적합합니다. 그렇지 않은 경우 HTTP 요청에 대한 응답으로 JSON 또는 XML을 제공하기 위해 Play를 직접 사용하는 것이 더 간단합니다.



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.