Play'de RESTful! iskelet


117

Öncelikle mobil uygulamalara içerik sunan bir proje planlıyoruz, ancak bir web sitemiz olması gerekiyor.

Sorum, mobil uygulamalarımız için REST API'leri geliştirmek için Jersey veya Restlet kullanmanın ve ardından Play'i kullanmanın mantıklı olup olmadığıdır! web sitesine hizmet etmek için.

Yoksa sadece Play'i kullanmak daha mı mantıklı? hepsini yapmak için? Öyleyse, Play ile REST nasıl yapılır! Çerçeve?

Yanıtlar:


112

İsteğe göre, basit bir REST benzeri yaklaşım. Codemwncis'in çözümünün çalıştığı şekilde hemen hemen aynı şekilde çalışır, ancak içerik anlaşması için Accept başlığını kullanır. Önce rotalar dosyası:

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

Burada herhangi bir içerik türü belirtmiyorsunuz. Bunu yapmak, IMHO yalnızca belirli kaynaklar için "özel" URI'lara sahip olmak istediğinizde gereklidir. /users/feed/Her zaman Atom / RSS'de geri dönmek için bir rota bildirmek gibi .

Uygulama denetleyicisi şuna benzer:

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);
}

Gördüğünüz gibi sadece getUserJSON yöntemini kaldırdım ve getUser yöntemini yeniden adlandırdım. Farklı içerik türlerinin çalışması için artık birkaç şablon oluşturmanız gerekir. İstenen her içerik türü için bir tane. Örneğin:

user.xml:

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

user.json:

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

user.html:

<html>...</html>

Bu yaklaşım, tarayıcılara her zaman HTML görünümünü verir, çünkü tüm tarayıcılar Accept başlıklarında bir metin / html içerik türü gönderir. Diğer tüm istemciler (muhtemelen bazı JavaScript tabanlı AJAX istekleri) kendi istedikleri içerik türlerini tanımlayabilir. JQuerys ajax () yöntemini kullanarak şunları yapabilirsiniz:

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

Bu, JSON biçiminde ID 1'e sahip Kullanıcı hakkındaki ayrıntıları size sağlamalıdır. Play şu anda HTML, JSON ve XML'yi yerel olarak desteklemektedir, ancak resmi belgeleri izleyerek veya içerik görüşme modülünü kullanarak farklı bir türü kolayca kullanabilirsiniz .

Geliştirme için Eclipse kullanıyorsanız , rotalarınızı ve ilgili içerik türlerini test etmenizi sağlayan REST istemci eklentisini kullanmanızı öneririm .


2
Bunu gönderdiğiniz için teşekkürler. Oyun! Dokümanlar, nesnelerin temel yapısını açıklamak için gördüğüm en iyilerden bazılarıdır, ancak bazen ayrıntılı örneklerde eksiktirler. Aynı örnekte gösterilen iki yaklaşımın olması işleri gerçekten açıklığa kavuşturuyor.
Brad Mace

Örneğinizi deniyorum, yayınlanan JSON verilerinin Kullanıcı sınıfına nerede dönüştürüldüğünü merak ediyorum. örneğin, createUser işlevinin içinde newUser'ın null olduğunu buluyorum.
Gary

2
@Gary: "newUser" yerine "user" kullandınız mı? Denetleyicinin adı ve form parametresi eşleşmelidir. Github.com/sebhoss/play-user-sample
seb

Teşekkürler, JSON dizesi göndermek için curl kullanarak test ettim ve oynatma çerçevesinin uygulama / json içerik türünü tanımadığı görülüyor: groups.google.com/group/play-framework/browse_thread/thread/…
Gary

@Gary: İpucu için teşekkürler! Görünüşe göre ana dalda düzeltildi, kendiniz oluşturmayı deneyebilir ve sonra tekrar test edebilirsiniz ..
seb

68

Bu hala popüler bir sorudur, ancak en yüksek oyu alan cevaplar oyunun mevcut sürümüyle güncel değil. İşte 2.2.1 oyunuyla çalışan bir REST örneği:

conf / yolları:

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)

Uygulamanın / kontrolörleri / 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
}

Ayrıca seb's Answer'ın güncellenmiş bir versiyonunu görmek istiyorum, ancak ne yazık ki cevabınız tüm .xml ve .html sihrini kaldırdı. :-(
flaschenpost

26

Play'i kullanın! hepsini yapmak için. Play'de REST hizmetleri yazmak çok çok kolaydır.

İlk olarak, yollar dosyası, REST yaklaşımına uyan yolları yazmayı kolaylaştırır.

Ardından, oluşturmak istediğiniz her API yöntemi için eylemlerinizi denetleyiciye yazarsınız.

Sonucu nasıl döndürmek istediğinize bağlı olarak (XML, JSON vb.), Kullanabileceğiniz birkaç yöntem vardır. Örneğin, renderJSON yöntemini kullanmak, sonuçların çok kolay bir şekilde oluşturulmasını sağlar. XML oluşturmak istiyorsanız, bunu Görünümünüzde bir HTML belgesi oluşturduğunuz gibi yapabilirsiniz.

İşte güzel bir örnek.

yollar dosyası

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

Uygulama dosyası

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 dosyası

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

Accept başlığına göre doğru getUser yöntemini seçmek mümkün müdür?
Timo Westkämper

öyle, ancak tamamen güvenilir değil. Play, başlığın bir JSON isteği olduğunu bilirse, bir getuser.json dosyası oluşturmaya çalışır. Başlık bir xml ise, getuser.xml'yi deneyecektir. Bununla birlikte, kullanıcı / Kullanıcı / {id} / type
Codemwnci

29
Temsil türünü açıkça URI'de belirtmenin daha REST benzeri olduğunu düşünmüyorum. Accept başlığını doğrudan kullanmak ve görmek istediğiniz kaynak aynı kaldığından URI'yi değiştirmemek daha iyidir. Yukarıdaki örnek, mevcut uygulamasıyla tam olarak aynı şeyi yapan tek bir getUser (Long id) yöntemine sahip olacak şekilde yeniden yazılabilir, ancak bir getUserJSON, getUserXML, vb. Tanımlamak yerine, bir getUser.json ve getUser.xml şablonu tanımlamayı tercih edersiniz. Bunu user.json / user.xml olarak yeniden adlandırsam da
seb

Teşekkürler, bu çok yardımcı oldu. Takdir et!
Gary

1
@seb - yorumunuzu bir yanıta dönüştürebilir misiniz? Tarif ettiğiniz tekniğin bir örneğini görmeyi çok isterim
Brad Mace

5

Bir JAX-RS uygulamasıyla entegrasyon, Play'in yerleşik HTTP yönlendirmesini kullanmak için olası bir alternatif yaklaşımdır. RESTEasy örneği için, RESTEasy Play! modül .

Bu yaklaşım, JAX-RS'ye zaten yatırım yaptıysanız veya içerik pazarlığı gibi JAX-RS'nin sağladığı gelişmiş REST özelliklerinden bazılarına ihtiyacınız varsa mantıklıdır. Değilse, HTTP isteklerine yanıt olarak JSON veya XML sunmak için doğrudan Play'i kullanmak daha kolay olacaktır.



2

Görünüşe göre bu yaklaşım Play 1.2.3 sürümünde bozulmuş. @Seb tarafından yapılan ve daha önce bahsedilen https://github.com/sebhoss/play-user-sample kaynağını indirirseniz, bir JSON nesnesiyle POST kullanarak yeni bir kullanıcı nesnesi oluşturmak artık mümkün değildir.

Json ve xml POST'ları kullanarak oluşturmak için belirli yöntemlere sahip olmanız gerekir. Burada özetlenen: https://groups.google.com/forum/#!topic/play-framework/huwtC3YZDlU

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.