HTTP routing[翻譯]

原文:https://www.playframework.com/documentation/2.5.x/ScalaRouting

內(nèi)置HTTP路由器

路由器的職責(zé)是負(fù)責(zé)轉(zhuǎn)換每一個進(jìn)入的HTTP請求給Action

一個HTTP請求可以被看做是由MVC框架的事件园匹。這個事件包含兩個主要的信息:

1.請求路徑(e.g.?/clients/1542,?/photos/list), 包含查詢字符串

2.HTTP 方法 (e.g.?GET,?POST, …).

路由是在可被編譯的conf/routes文件中被定義的嬉愧。這意味著你可以在你的瀏覽器中直接看到路由的錯誤信息

依賴注入

Play支持生成兩種路由器的類型烙博,一個是依賴注入路由器美浦,另一個是靜態(tài)路由。默認(rèn)的是依賴注入路由器,這也是在Play種子Activator模板中的樣例部念,因此我們推薦你使用依賴注入Contrlller。如果你需要使用靜態(tài)Contrller,你可以通過在你的build.sbt配置文件里添加下面這樣的配置來轉(zhuǎn)換到靜態(tài)路由生成器:

routesGenerator:= StaticRoutesGenerator

在Play的文檔中的代碼樣例假定你使用了依賴注入路由生成器型宙。如果你沒有使用這個,你可以容易的改寫代碼樣例到靜態(tài)路由生成器期吓,既可以使用@符號在路由的Controller的調(diào)用部分加上前綴早歇,或者通過聲明你的每一個Contrller為object而不是class。

路由文件的語法

conf/routes是路由器使用的配置文件讨勤。這個文件里出了應(yīng)用需要的所有的路由箭跳。每個路由由HTTP方法和URI模式組成,這兩個都與調(diào)用Action生成器相關(guān)潭千。

讓我們來看一看路由定義的樣子:

GET? /clients/:idcontrollers.Clients.show(id: Long)

每一個路由以HTTP方法開始谱姓,下來是URI模式。最后一個元素是調(diào)用定義刨晴。

你也可以以#字符開頭在路由文件中增加注釋屉来。

# Display a client.

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

你可以通過一個特殊的前綴“->”,告訴路由文件使用一個不同的路由器:

->? ? ? /api? ? ? ? ? ? ? ? ? api.MyRouter

當(dāng)你和String Interpolating Routing DSL也被稱作SIRD路由整合時狈癞,或者當(dāng)你使用了多個路由文件的子項目時茄靠,這非常有用。

HTTP方法

HTTP方法可以使用任何被HTTP (GET,?PATCH,?POST,?PUT,?DELETE,?HEAD)支持的有效方法蝶桶。

URI模式

URI模式定義了路由的請求路徑慨绳,請求路徑的部分可以是靜態(tài)的。

靜態(tài)路徑

例如真竖,為了準(zhǔn)確的匹配到輸入的?GET /clients/all?請求脐雪,你可以定義這樣的路由:

GET? /clients/all? ? ? controllers.Clients.list()

動態(tài)路徑

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

GET? /clients/:idcontrollers.Clients.show(id: Long)

注意:URI模式可能會有多個動態(tài)的部分恢共。

動態(tài)部分的默認(rèn)匹配策略是通過正則表達(dá)式?[^/]+定義的战秋,意思就是說任何一個定義為:id?的動態(tài)部分將嚴(yán)格的匹配一個URI路徑段。不像其他的模式類型讨韭,在路由中路徑段自動地URI-解碼脂信,而是在傳遞給你的Controller之前癣蟋,并在反向路由中解碼。

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

如果你想讓動態(tài)部分可以捕獲多個通過正斜杠分割的URI路徑段狰闪,你可以使用語法*id(沒被稱為使用.*正則表達(dá)的通配符模式)定義動態(tài)部分:

GET ? ? /files/* ? namecontrollers.Application.download(name)

這個配置匹配像GET /files/images/logo.png樣的請求梢薪,動態(tài)部分name 將會捕捉到值images/logo.png?。

注意:跨越多個/的動態(tài)部分不會被路由器解碼也不會被反向路由器編碼尝哆。你的職責(zé)是驗證任何用戶可能的輸入原生的URI段。反向路由器簡單的做一個字符串的連接甜攀,因此你將需要確保結(jié)果路徑是有效的秋泄,或不是,例如规阀,含有多個前導(dǎo)斜桿或非ASCII字符恒序。

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

你也可以使用$id?語法為動態(tài)部分定義你自己的動態(tài)表達(dá)式:

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

就像通配符路由一樣,參數(shù)不會被路由器編碼或反向路由器解碼谁撼。你的職責(zé)是驗證輸入歧胁,確保它在這個環(huán)境下的意義。

調(diào)用Action生成器方法

路由定義的最后一部分是調(diào)用厉碟。這部分必須定義一個有效的調(diào)用到一個返回?play.api.mvc.Action?值的方法喊巍,通常情況下是一個Controller的Action方法。

如果方法沒有定義任何參數(shù)箍鼓,僅使用完全限定的方法名:

GET? /? ? ? ? ? ? ? ? ? ? controllers.Application.homePage()

如果Action方法定義了一些參數(shù)崭参,所有這些參數(shù)的值將會在請求的URI中搜索,要么從URI路徑本身提取款咖,要么從查詢字符串中何暮。

# 從路徑中提取page參數(shù)

GET? /:page? ? ? ? ? ? controllers.Application.show(page)

或者:

# 從查詢字符串中提取頁面參數(shù)

GET ???/ ? ? controllers.Application.show(page)??

相應(yīng)的,在controllers.Application?Controller中定義show方法:

def show(page: String) = Action {

loadContentFromDatabase(page).map { htmlContent =>

Ok(htmlContent).as("text/html")

}.getOrElse(NotFound)

}

參數(shù)類型

對于String類型的參數(shù)铐殃,輸入?yún)?shù)是可以選的海洼。如果你想讓Play把傳入的參數(shù)轉(zhuǎn)換成特殊的Scala類型,你可以指定參賽類型:

GET? /clients/:idcontrollers.Clients.show(id: Long)

在?controllers.Clients?Controller中相應(yīng)的實現(xiàn)一個相同的show方法定義:

def show(id: Long) = Action {

Client.findById(id).map { client =>

Ok(views.html.Clients.display(client))

}.getOrElse(NotFound)

}

固定值的參數(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)

帶有默認(rèn)值的參數(shù)

在傳入的請求沒有找到值的時候富腊,你也可以提供一個默認(rèn)值:

# Pagination links, like /clients?page=3

GET /clients controllers.Clients.list(page: Int ?=?1)

Optional類型的參數(shù)

你也可以指定一個不需要在所有的請求中都出現(xiàn)的Optional類型的參數(shù):

# The version parameter is optional. E.g. /api/list-all?version=3.0

GET /api/list-all controllers.Api.list(version: Option[String])

路由的優(yōu)先級

許多路由可以匹配到相同的請求坏逢,如果有沖突,第一個路由(按聲明的順序)被使用蟹肘。

反轉(zhuǎn)路由

路由器也可以被用來從Scala調(diào)用內(nèi)部生成URL词疼。這讓在一個單獨的配置文件中集中所有的URI模式成為可能,因此你在重構(gòu)你的應(yīng)用是會更加自信帘腹。

對于路由文件中的每一個使用的Controller贰盗,路由器會在routes包中生成一個有相同簽名的相同Action方法的‘Reverse Controller’,但是返回play.api.mvc.Call?而不是play.api.mvc.Action.

例如阳欲,如果你創(chuàng)建一個這樣的Controller:

package controllers

import play.api._

import play.api.mvc._class

Application?extends?Controller?{ def hello(name: String) = Action { Ok("Hello "?+ name +?"!") } }

并且如果你在conf/routes文件中增加了映射:

# Hello action

GET ? ??/hello/:name? ? ?controllers.Application.hello(name)

然后你就可以使用controllers.routes.Application反轉(zhuǎn)Controller反轉(zhuǎn)URL到Action方法:

// Redirect to /hello/Bob

def helloBob = Action { Redirect(routes.Application.hello("Bob")) }

注意:每一個Controller包都有一個路由子包舵盈。因此Action controllers.admin.Application.hello?可以通過controllers.admin.routes.Application.hello(只要在路由文件中的這個路由之前沒有其他可匹配的生成路徑)被反轉(zhuǎn)陋率。

反轉(zhuǎn)Action方法的原理很簡單:它拿到你的參數(shù),并在路由模式中替換它們秽晚。在路徑段(:foo)的例子中瓦糟,值在替換完成之前解碼,對于正則模式和通配符模式赴蝇,字符串在原始形態(tài)中被替換菩浙,因此值可以跨越多個段。確保當(dāng)你把這些組件傳遞給反轉(zhuǎn)路由時忘記了這些必須的組件句伶,并避免傳遞無效的用戶輸入劲蜻。

默認(rèn)的Controller

Play有一個提供了幾個有用的Action的默認(rèn)Controller,這些可以在路由文件中直接調(diào)用:

# Redirects to https://www.playframework.com/ with 303 See Other

?GET??/about controllers.Default.redirect(to?="https://www.playframework.com/")

# Responds with 404 Not Found

?GET??/orders controllers.Default.notFound

# Responds with 500 Internal Server Error

?GET??/clients controllers.Default.error

?# Responds with 501 Not Implemented

?GET??/posts controllers.Default.todo

在這個例子中考余,GET /?重定向到外部的站點先嬉,但是它也可以重定向到其他的Action(如上面的例子中的/posts?)。

自定義路由

Play提供了一個 DSL 來定義嵌入的路由器楚堤,這個路由器被稱為?String Interpolating Routing DSL疫蔓,或者簡寫為SIRD。這個DSL有很多用途身冬,包括嵌入一個輕量級的Play服務(wù)衅胀,提供自定義或更高級的路由功能給規(guī)范的Play應(yīng)用,在測試方面甩REST服務(wù)幾條街酥筝。

詳見String Interpolating Routing DSL

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拗小,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子樱哼,更是在濱河造成了極大的恐慌哀九,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,294評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搅幅,死亡現(xiàn)場離奇詭異阅束,居然都是意外死亡,警方通過查閱死者的電腦和手機茄唐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,493評論 3 385
  • 文/潘曉璐 我一進(jìn)店門息裸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人沪编,你說我怎么就攤上這事呼盆。” “怎么了蚁廓?”我有些...
    開封第一講書人閱讀 157,790評論 0 348
  • 文/不壞的土叔 我叫張陵访圃,是天一觀的道長。 經(jīng)常有香客問我相嵌,道長腿时,這世上最難降的妖魔是什么况脆? 我笑而不...
    開封第一講書人閱讀 56,595評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮批糟,結(jié)果婚禮上格了,老公的妹妹穿的比我還像新娘。我一直安慰自己徽鼎,他們只是感情好盛末,可當(dāng)我...
    茶點故事閱讀 65,718評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著否淤,像睡著了一般满败。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叹括,一...
    開封第一講書人閱讀 49,906評論 1 290
  • 那天,我揣著相機與錄音宵荒,去河邊找鬼汁雷。 笑死,一個胖子當(dāng)著我的面吹牛报咳,可吹牛的內(nèi)容都是我干的侠讯。 我是一名探鬼主播,決...
    沈念sama閱讀 39,053評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼暑刃,長吁一口氣:“原來是場噩夢啊……” “哼厢漩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起岩臣,我...
    開封第一講書人閱讀 37,797評論 0 268
  • 序言:老撾萬榮一對情侶失蹤溜嗜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后架谎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體炸宵,經(jīng)...
    沈念sama閱讀 44,250評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,570評論 2 327
  • 正文 我和宋清朗相戀三年谷扣,在試婚紗的時候發(fā)現(xiàn)自己被綠了土全。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,711評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡会涎,死狀恐怖裹匙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情末秃,我是刑警寧澤概页,帶...
    沈念sama閱讀 34,388評論 4 332
  • 正文 年R本政府宣布,位于F島的核電站练慕,受9級特大地震影響绰沥,放射性物質(zhì)發(fā)生泄漏篱蝇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,018評論 3 316
  • 文/蒙蒙 一徽曲、第九天 我趴在偏房一處隱蔽的房頂上張望零截。 院中可真熱鬧,春花似錦秃臣、人聲如沸涧衙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,796評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽弧哎。三九已至,卻和暖如春稚虎,著一層夾襖步出監(jiān)牢的瞬間撤嫩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,023評論 1 266
  • 我被黑心中介騙來泰國打工蠢终, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留序攘,地道東北人。 一個月前我還...
    沈念sama閱讀 46,461評論 2 360
  • 正文 我出身青樓寻拂,卻偏偏與公主長得像程奠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子祭钉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,595評論 2 350

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理瞄沙,服務(wù)發(fā)現(xiàn),斷路器慌核,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 內(nèi)置的HTTP路由器 這個路由器用于翻譯每一個接收到的HTTP請求到對應(yīng)的action(一個controller類...
    zerolinke閱讀 1,946評論 0 0
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,825評論 25 707
  • 本系列主要翻譯自《ASP.NET MVC Interview Questions and Answers 》- B...
    圣杰閱讀 7,268評論 3 32
  • 青石的噴泉不停地唱晚 蘆葦青草邊距境,一圍古箏山高水流 許是竹影婆娑 沉香裊裊,唉 這一個下午 . 當(dāng)炭火煮熟一壺玉竹...
    東山島高永川閱讀 390評論 0 1