HTTP 路由

內置的HTTP路由器

這個路由器用于翻譯每一個接收到的HTTP請求到對應的action(一個controller類的public方法)調用.
一個HTTP請求被視為MVC框架的一個event.這個event包含兩個主要的信息部分:

  • request path (e.g. /clients/1542, /photos/list),包含query string.
  • HTTP method (GET,POST,...).

路由被定義在conf/routes 文件中,是被編譯過的.這意味著你會在路由出錯的時候直接在你的瀏覽器中看到他們:


路由出錯的時候,你會在你的瀏覽器中與她相逢
路由出錯的時候,你會在你的瀏覽器中與她相逢

路由的依賴注入

Play 支持生成兩種類型的路由器.一個是依賴注入路由器,另一個是靜態(tài)路由器.默認的是依賴注入路由器,這也是 Play的種子模板(Play seed Activator templates)中選擇的方案,因為我們推薦你使用依賴注入的controllers.如果你需要使用靜態(tài)controller,你可以切換靜態(tài)路由生成器 通過添加下面的配置到你的 build.sbt 文件中:

routesGenerator := StaticRoutesGenerator

Play 的文檔中代碼例子假定你使用的是依賴注入的路由生成器.如果是靜態(tài)路由生成器,你可以通過在路由文件中controller的調用地方使用@符號作為前綴,或者聲明每一個action方法為一個 static 方法來適配代碼示例.

路由文件的書寫語法

conf/routes 是路由器使用的配置文件.這個文件列出了應用需要的所有路由.每一個路由由一個HTTP method, 一個URI pattern和需要調用的相關action method組成.
讓我們看看路由定義的樣子:

GET      /clients/:id            controllers.Clients.show(id: Long)

注意:在action的調用地方,需要將參數(shù)的類型寫在參數(shù)名稱后面, 類似Scala風格.

每一個路由由HTTP method 開始,后面是URI pattern.最后是一個調用定義.你也可以添加一些注釋在路由文件中,使用 # 字符:

# Display a client.
GET      /clients/:id            controllers.Clients.show(id: Long)

HTTP method

這個 HTTP method 可以是任何 HTTP支持的有效方法(GET, PATCH, POST, PUT, DELETE, HEAD,OPTIONS).

URI pattern

URI pattern 定義了路由的請求路徑.請求路徑的一部分可以是動態(tài)的.

靜態(tài)的path

舉個例子,要完全匹配 GET /clients/all 這個請求,你可以這樣定義路由:

GET      /clients/all            controllers.Clients.list()
動態(tài)部分

如果你想定義一個路由,比如說,通過ID檢索客戶端,你需要添加一個動態(tài)部分:

GET      /clients/:id            controllers.Clients.show(id: Long)

注意:一個URI pattern可能有不止一個動態(tài)部分.

動態(tài)部分的默認匹配策略是由正則表達式:

[^/]+

定義的,即任何使用 :id 定義的動態(tài)部分將匹配一個URI的path段.

動態(tài)部分跨越多個/

如果你想要一個動態(tài)部分來捕獲多個URI path段胰柑,用斜線分開,你可以使用* id語法來定義一個動態(tài)部分,它使用 .* 正則表達式:

GET      /files/*name            controllers.Application.download(name)

這里,像 GET /files/images/logo.png 這樣的請求, 這個name動態(tài)部分將捕獲 /images/logp.png 作為值.

自定義正則表達式的動態(tài)部分

當然你通過你自己的正則表達式定義一個動態(tài)部分,使用 $id<regex> 語法:

GET      /items/$id<[0-9]+>            controllers.Items.show(id:Long)

調用action生成器方法

路由的最后一部分定義了一個調用.這部分必須定義一個有效的action method 調用.
如果這個調用方法沒有定義任何參數(shù)确镊,那么只需要一個方法名稱就可以:

GET      /            controllers.Application.homePage() 

如果action方法定義了參數(shù),相對應的參數(shù)就會在request URI中查找匹配滥搭,URI中的URI path和query string都會被查找何什。

# Extract the page parameter from the path.
# i.e. http://myserver.com/index
GET      /:page            controllers.Application.show(page)

或者是:

# Extract the page parameter from the query string
#  i.e. http://myserver.com/?page=index
GET      /            controllers.Application.show(page)

下面是定義在 controllers.Application控制器中對應的show方法:

public Result show(String page) { 
        String content = Page.getContentOf(page);             
        response().setContentType("text/html");
        return ok(content);
}
參數(shù)類型

對于String類型的參數(shù),參數(shù)類型是可選的.如果你想要 Play去轉換參數(shù)為一個指定的Scala類型,你可以添加一個顯式類型:

GET      /clients/:id            controllers.Clients.show(id: Long)

然后在對應控制器的action方法參數(shù)中使用相同的類型:

public Result show(Long id) { 
      Client client = clientService.findById(id);
      return ok(views.html.Client.show(client));
}

注意:這個參數(shù)類型的指定使用的是后綴語法.此外,泛型的指定使用[]符號代替java中的<>符號.比如,List[String]就是Java 里的List<String>.

固定值的參數(shù)

有時候你可能想要使用一個固定值的參數(shù):

# Extract the page parameter from the path, or fix the value for /
GET      /            controllers.Application.show(page = "home")
GET      /:page            controllers.Application.show(page)
具有默認值的參數(shù)

當然你也可以提供一個默認值用在一個請求沒有攜帶參數(shù)值的時候:

# Pagination links, like /clients?page=3
# 分頁的時候
GET      /clients            controllers.Clients.list(page: Int ?= 1)
可選參數(shù)

你可以指定只一個不需要存在于所有請求中的可選參數(shù):

# The version parameter is optional. E.g. /api/list-all?version=3.0
GET      /api/list-all            controllers.Api.list(version ?= null)

路由優(yōu)先級

很多路由可以匹配一些相同的請求,如果有沖突,按照聲明順序的第一個路由將被使用.

反向路由

路由器可以被java調用生成一個URL.這使你可以將你的URI patterns 集中在一個單獨的配置文件中,這樣當你重構你的應用的時候你可以更加自信.

對于路由文件使用的每一個控制器,路由器會生成一個反向控制器在routes包中,包含相同的action方法,相同的簽名但是返回的play.mvc.Result對象被paly.mvc.Call對象替代.
這個play.mvc.Call 定義了一個HTTP調用,提供相同的HTTP method和 URI.
舉個例子,如果你創(chuàng)建了一個這樣的controller:

package controllers;
import play.*;
import play.mvc.*;
public class Application extends Controller{
    public Result hello(String name) { 
        return ok("Hello " + name + "!"); 
       }
}

并且在 conf/routes文件中映射它:

# Hello action
GET      /hello/:name            controllers.Application.hello(name)

那么你可以導向一個URL到 hello action方法,通過使用 controllers.routes.Application reverse controller:

// Redirect to /hello/Bob
public Result index() { 
return redirect(controllers.routes.Application.hello("Bob"));
}

注意: 這里每個controller有一個routes子包,比如 controllers.admin.Applications.hello 的action可以被反向調用通過 controllers.admin.routes.Application.hello .

高級路由

參考 Routing DSL

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市咖楣,隨后出現(xiàn)的幾起案子督笆,更是在濱河造成了極大的恐慌,老刑警劉巖诱贿,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娃肿,死亡現(xiàn)場離奇詭異,居然都是意外死亡珠十,警方通過查閱死者的電腦和手機料扰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來宵睦,“玉大人记罚,你說我怎么就攤上這事】呛浚” “怎么了桐智?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長烟馅。 經(jīng)常有香客問我说庭,道長,這世上最難降的妖魔是什么郑趁? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任刊驴,我火速辦了婚禮,結果婚禮上寡润,老公的妹妹穿的比我還像新娘捆憎。我一直安慰自己,他們只是感情好梭纹,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布躲惰。 她就那樣靜靜地躺著,像睡著了一般变抽。 火紅的嫁衣襯著肌膚如雪础拨。 梳的紋絲不亂的頭發(fā)上氮块,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音诡宗,去河邊找鬼滔蝉。 笑死,一個胖子當著我的面吹牛塔沃,可吹牛的內容都是我干的蝠引。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼芳悲,長吁一口氣:“原來是場噩夢啊……” “哼立肘!你這毒婦竟也來了?” 一聲冷哼從身側響起名扛,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茧痒,沒想到半個月后肮韧,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡旺订,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年弄企,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片区拳。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡拘领,死狀恐怖,靈堂內的尸體忽然破棺而出樱调,到底是詐尸還是另有隱情约素,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布笆凌,位于F島的核電站圣猎,受9級特大地震影響,放射性物質發(fā)生泄漏乞而。R本人自食惡果不足惜送悔,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望爪模。 院中可真熱鬧欠啤,春花似錦、人聲如沸屋灌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽声滥。三九已至眉撵,卻和暖如春侦香,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纽疟。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工罐韩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人污朽。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓散吵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蟆肆。 傳聞我的和親對象是個殘疾皇子矾睦,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內容

  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)炎功,斷路器枚冗,智...
    卡卡羅2017閱讀 134,659評論 18 139
  • HTTP請求/響應路由是用于決定在當前請求下,哪一個句柄去接收和響應蛇损。句柄可以是一個函數(shù)赁温、過程或者方法,只要能夠接...
    小笨憨閱讀 2,037評論 0 0
  • 1.基本路由 所有應用路由都定義在 App\Providers\RouteServiceProvider 類載入的...
    lmem閱讀 913評論 0 0
  • 上圖列出了 Laravel HTTP 層的相關知識大綱稚疹。由于目前自己的工作中網(wǎng)頁、App祭务、小程序等都采用前后臺分離...
    胖福哥閱讀 1,847評論 0 21
  • “慎獨” “此謂誠于中内狗,形于外,故君子必慎其獨也”出自《大學》意思即是一個人內心中的喜怒哀樂待牵、善良邪惡其屏,無論如何隱...
    大才閱讀 995評論 0 5