1. 程式人生 > >Play 2.6 路由

Play 2.6 路由

routers

conf/routers檔案中配置路由資訊
一條路由資訊包括兩個部分:

  1. http方法(get、post等)
  2. 請求路徑

無參路由

routers檔案

GET     /count                      controllers.CountController.count

程式碼

package controllers;

import play.mvc.Controller;
import play.mvc.Result;
import services.Counter;

import javax.inject.Inject;
import
javax.inject.Singleton; @Singleton public class CountController extends Controller { private final Counter counter; @Inject public CountController(Counter counter) { this.counter = counter; } public Result count() { return ok(Integer.toString(counter.nextCount())); }

一般形式

GET     /count/see/:i               controllers.CountController.see(i:Int)

public Result see(int i){return ok(Integer.toString(i));}//引數形式使用scala的方式
# request example http://localhost:9000/count/see/2

為引數設定預設值

# http://localhost:9000/count/see?i=2
GET     /count/see              controllers.CountController
.see(i:Int ?= 1 )

引數型別為String的情況下,可省略型別引數

GET     /count/seeString/:s             controllers.CountController.seeString(s)

可選引數

# The version parameter is optional. E.g. /api/list-all?version=3.0
GET   /api/list-all         controllers.Api.list(version ?= null)
# or
GET   /api/list-all         controllers.Api.listOpt(version: java.util.Optional[String])

一條請求可能會匹配到多條路由,預設使用第一條路由

反向路由

在routes檔案中配置的controller,都會在routes包下生成一個reverse controller(在Play2.6.10中,這些類在target/scala/routes/main/controllers目錄下),這些controller擁有和原controller一樣的方法及簽名,但是返回一個play.mvc.Call例項而不是play.mvc.Result例項

在呼叫一個請求時,可以在程式碼中通過重定向的方式去生成新一個新的url,並呼叫該url
假設已有方法hello及相應的對映

public Result hello(String name) {
        return ok("Hello " + name + "!");
    }

GET     /hello/:name                      controllers.CountController.hello(name)
// Redirect to /hello/Bob
public Result index() {
    return redirect(controllers.routes.CountController.hello("Bob"));
}

相對路由(Relative routes)

通過play.mcv.Call返回的url都是以/開頭的絕對路由,在使用代理、負載均衡、API gateways的環境下可能會出現問題。

package controllers;

import play.*;
import play.mvc.*;

public class Relative extends Controller {

    public Result helloview() {
        ok(views.html.hello.render("Bob", request()));
    }

    public Result hello(String name) {
        return ok("Hello " + name + "!");
    }

}

routes檔案

GET     /foo/bar/hello              controllers.Relative.helloview
GET     /hello/:name                controllers.Relative.hello(name)

views/hello.scala.html檔案

@(name: String, request: Http.RequestHeader)

<h1>Hello @name</h1>

<a href="@routes.Relative.hello(name)">Absolute Link</a>
<a href="@routes.Relative.hello(name).relativeTo(request)">Relative Link</a>

呼叫/foo/bar/hello產生的html檔案


<h1>Hello Bob</h1>

<a href="/hello/Bob">Absolute Link</a>
<a href="../../hello/Bob">Relative Link</a>

從這裡可以看的第二條url已經為相對路徑

推薦使用相對路由的場景:
- Hosting an app behind a web gateway that prefixes all routes with something other than what is configured in your conf/routes file, and roots your application at a route it’s not expecting
- When dynamically rendering stylesheets, you need asset links to be relative because they may end up getting served from different URLs by a CDN.