2012-03-11 21 views
60

phép nói rằng tôi có một vai framework 2.0 dựa trên ứng dụng đã hoạt động trong Scala phục vụ một URL như:Làm thế nào để xử lý các tham số truy vấn tùy chọn trong khuôn khổ Chơi

http://localhost:9000/birthdays

mà đáp lại với một danh sách của tất cả được biết đến sinh nhật

bây giờ tôi muốn nâng cao này bằng cách thêm khả năng hạn chế kết quả với tùy chọn "từ" (ngày) và "thành" yêu cầu params như

http://localhost:9000/birthdays?from=20120131&to=20120229

(ngày ở đây hiểu là yyyyMMdd)

Câu hỏi của tôi là làm thế nào để xử lý các param yêu cầu ràng buộc và giải thích trong Chơi 2.0 với Scala, đặc biệt là cho rằng cả hai params nên bắt buộc.

Các tham số này có thể được diễn tả bằng cách nào đó trong đặc tả "tuyến đường" không? Ngoài ra, phương pháp điều khiển đáp ứng có phải tách các tham số khỏi đối tượng yêu cầu bằng cách nào đó không? Có một cách khác để làm điều này?

Trả lời

52

Mã hóa các thông số tùy chọn của bạn như Option[String] (hoặc Option[java.util.Date], nhưng bạn sẽ phải thực hiện của riêng QueryStringBindable[Date]):

def birthdays(from: Option[String], to: Option[String]) = Action { 
    // … 
} 

Và tuyên bố các tuyến đường sau:

GET /birthday  controllers.Application.birthday(from: Option[String], to: Option[String]) 
+0

Cảm ơn dường như hoạt động khá tốt! – magicduncan

+6

Đối với tôi điều này là không đủ để làm định tuyến không có tham số. Tôi mở rộng nó để 'GET/birthday controllers.Application.birthday (từ: Option [String]? = None, to: Option [String]? = None)' –

+0

Thêm thành công: 'GET/birthday controllers.Application.birthday (Option [from], Option [to]) ' –

17

Một lẽ ít sạch cách thực hiện việc này cho người dùng java là cài đặt mặc định:

GET /users controllers.Application.users(max:java.lang.Integer ?= 50, page:java.lang.Integer ?= 0) 

Và trong bộ điều khiển

public static Result users(Integer max, Integer page) {...} 

Một vấn đề nữa, bạn sẽ phải lặp lại giá trị mặc định bất cứ khi nào bạn liên kết đến trang của bạn trong các mẫu

@routes.Application.users(max = 50, page = 0) 
+0

Ai đó có thể xác nhận rằng (max: java.lang .Integer = null) hoạt động? 'max' luôn kết thúc bằng null cho tôi ... – ejain

+1

Tôi đã sửa câu trả lời, phải là? = – Somatik

+6

Trong Java, bạn có thể sử dụng 'play.libs.F.Option' thay vì Scala' Option' –

7

Dưới đây là ví dụ Julien viết lại bằng java, sử dụng F .Option: (chỉ hoạt động khi chơi 2,1)

import play.libs.F.Option; 
public static Result birthdays(Option<String> from, Option<String> to) { 
    // … 
} 

Route:

GET /birthday  controllers.Application.birthday(from: play.libs.F.Option[String], to: play.libs.F.Option[String]) 

Bạn cũng có thể chỉ cần chọn các tham số truy vấn tùy ý ra như dây đàn (bạn phải làm các loại chuyển đổi chính mình):

public static Result birthdays(Option<String> from, Option<String> to) { 
    String blarg = request().getQueryString("blarg"); // null if not in URL 
    // … 
} 
2

cách của tôi để làm điều này liên quan đến việc sử dụng một tùy chỉnh QueryStringBindable. Bằng cách này, tôi thể hiện các thông số trong các tuyến đường như sau:

GET /birthdays/ controllers.Birthdays.getBirthdays(period: util.Period) 

Mã cho khoảng thời gian trông như thế này.

public class Period implements QueryStringBindable<Period> { 

    public static final String PATTERN = "dd.MM.yyyy"; 
    public Date start; 

    public Date end; 

    @Override 
    public F.Option<Period> bind(String key, Map<String, String[]> data) { 
     SimpleDateFormat sdf = new SimpleDateFormat(PATTERN); 

     try { 
      start = data.containsKey("startDate")?sdf.parse(data.get("startDate") [0]):null; 
      end = data.containsKey("endDate")?sdf.parse(data.get("endDate")[0]):null; 
     } catch (ParseException ignored) { 
      return F.Option.None(); 
     } 
     return F.Option.Some(this); 
    } 

    @Override 
    public String unbind(String key) { 
     SimpleDateFormat sdf = new SimpleDateFormat(PATTERN); 
     return "startDate=" + sdf.format(start) + "&amp;" + "endDate=" + sdf.format(end); 
    } 

    @Override 
    public String javascriptUnbind() { 
     return null; 
    } 

    public void applyDateFilter(ExpressionList el) { 
     if (this.start != null) 
      el.ge("eventDate", this.start); 
     if (this.end != null) 
      el.le("eventDate", new DateTime(this.end.getTime()).plusDays(1).toDate()); 
    } 

}

applyDateFilter chỉ là một phương pháp convienence tôi sử dụng trong các bộ điều khiển của tôi nếu tôi muốn áp dụng lọc ngày để truy vấn. Rõ ràng bạn có thể sử dụng các mặc định ngày khác ở đây, hoặc sử dụng một số mặc định khác null cho ngày bắt đầu và ngày kết thúc theo phương thức bind.

1

Đối với các thông số truy vấn tùy chọn, bạn có thể làm theo cách này

Trong tập tin tuyến đường, tuyên bố API

GET /birthdays  controllers.Application.method(from: Long, to: Long) 

Bạn cũng có thể đưa ra một số giá trị mặc định, trong trường hợp API không chứa những params truy vấn nó sẽ tự động gán các giá trị mặc định cho các tham số này

GET /birthdays controllers.Application.method(from: Long ?= 0, to: Long ?= 10) 

Trong phương pháp được viết bên trong bộ điều khiển Ứng dụng các thông số này sẽ có giá trị null nếu không có giá trị mặc định nào được gán giá trị mặc định khác.

8

Ngoài câu trả lời của Julien. Nếu bạn không muốn đưa nó vào tệp tuyến đường.

Bạn có thể nhận được thuộc tính này trong phương pháp điều khiển sử dụng RequestHeader

String from=request().getQueryString("from"); 
String to=request().getQueryString("to"); 

này sẽ cung cấp cho bạn các thông số yêu cầu mong muốn, cộng với giữ nộp sạch các tuyến đường của bạn.

+0

làm thế nào để tệp bộ định tuyến của bạn trông như thế nào? Tôi có một số thông tin như 'GET \t \t/url @ com.mycompany.controllers.MyClass.fetchget()' và không thể tìm thấy tuyến đường – Zennichimaro

Các vấn đề liên quan