1、逆向生成URL
Play路由器是按照Java調用生成URL的,所以可以將URI表達式都集中到同個配置文件中,使得重構應用變得更加便捷。比如,爲conf/routes文件添加如下路由配置:
GET /clients/{id} Clients.show
之後在Java代碼中,就可以調用Client.show來生成URL:
map.put("id", 1541);
String url = Router.reverse("Clients.show", map).url; // GET /clients/1541
URL的生成已經集成到框架的大部分組件當中,一般我們不需要直接調用Router.reverse方法。
如果增加的參數不包含在URI表達式中,這些參數會被添加到查詢字符串中:
map.put("id", 1541);
map.put("display", "full");
String url = Router.reverse("Clients.show", map).url; // GET /clients/1541?display=full
同樣地,路由器會根據優先順序匹配最適的URL。
2、設置content type
Play會根據request.format設定的值,選擇指定的media類型來響應HTTP請求。該值通過文件擴展名來決定使用何種視圖模板進行渲染,並且通過Play框架中的mime-types.properties文件進行映射處理(映射關係詳見play\framework\src\play\libs\mime-types.properties文件),爲media類型設定Content-type響應。
Play請求的默認格式爲html,因此index()控制器方法默認的渲染模板文件爲index.html。如果需要指定其他的格式,有以下四種方式:
(1)可以在程序代碼調用render()方法之前進行格式設置。比如將media類型設置爲text/css,就可以使用CSS文件進行渲染:
public static void index() {
request.format = "css";
render();
}
(2)推薦一種更直接的做法,直接在routes文件中使用URL來指定格式。以下列路由配置爲例:首先客戶端通過index.xml請求服務器,服務器端將響應格式設置爲xml,最後使用index.xml模版進行渲染。
GET /index.xml Application.index(format:'xml')
同樣地,我們也可以使用CSS進行渲染:
GET /stylesheets/dynamic_css css.SiteCSS(format:'css')
(3)Play還可以直接從URL中獲取請求格式,動態指定渲染的模板類型。參考如下路由配置:
GET /index.{format} Application.index
當請求爲/index.xml時,服務器會將返回格式設置爲xml並使用相應的XMl文件進行渲染;請求爲/index.txt時,則會使用文本進行渲染。
(4)使用Play中的HTTP內容協商進行格式設置,詳見以後更新的內容。
3、HTTP內容協商
Play與其他REST架構的框架一樣,直接使用HTTP方法,而不是試圖隱藏HTTP或者在上面構建抽象層。內容協商是HTTP的特性,它允許HTTP服務器根據客戶端的請求類型,實現同個URL提供不同的media類型響應。客戶端可以在Accept header中設置media屬性,指定可接收的響應類型。如果用戶需要XML響應,則進行如下設置:
Accept:application/xml
客戶端可以指定多種media類型,或使用cacth-all通配符(*/*)來指定任何media類型。
Accept:application/xml,image/png,*/*
3.1 在HTTP頭中設置content type#
如果Accept header中包含了text/html,application/xhtml或者通配符 */*,Play會選擇使用其默認的請求格式(即HTML)。只有當通配符的值被顯式指定時,Play纔會選擇其默認的請求格式。
Play內置了一些常規格式支持:html、txt、json、xml。下例代碼定義了控制器方法(Action)進行數據渲染:
public static void index() {
final String name = "Peter Hilton";
final String organisation = "Lunatech Research";
final String url = "http://www.lunatech-research.com/";
render(name, organisation, url);
}
如果在瀏覽器中訪問http://localhost:9000,Play默認會使用index.html模板進行渲染,因爲瀏覽器發送了包含text/html的Accept header。
通過將請求的格式設置爲xml,可以使用index.xml模板響應標識爲Accept: text/xml的請求:
<?xml version="1.0"?>
<contact>
<name>${name}</name>
<organisation>${organisation}</organisation>
<url>${url}</url>
</contact>
下表針對index()控制器方法給出了Play內置的Accept header請求格式映射:Accept header包含了Play能夠映射成的所有格式(最後轉化爲相應的模板文件),如表3.1:
(表3.1 Play內置的Accept header請求格式映射)
Accept header | Format | Template file name | mapping |
---|---|---|---|
null | null | index.html | null格式請求提供默認模版擴展 |
image/png | null | index.html | media類型沒有映射爲指定格式 |
*/*, image/png | html | index.html | 默認將media類型映射爲html格式 |
text/html | html | index.html | 內置映射 |
application/xhtml | html | index.html | 內置映射 |
text/xml | xml | index.xml | 內置映射 |
application/xml | xml | index.xml | 內置映射 |
text/plain | txt | index.txt | 內置映射 |
text/javascript | json | index.json | 內置映射 |
application/json, */* | json | index.json |
內置映射, 忽略默認media類型 |
3.2 自定義格式#
在Play中可以通過檢查HTTP請求頭,爲應用選擇相應的media類型來實現自定義格式。比如使用@Before標籤攔截該控制器下的所有Action,檢查請求的media類型是否爲text/x-vcard:
@Before
static void setFormat() {
if (request.headers.get("accept").value().equals("text/x-vcard")) {
request.format = "vcf";
}
}
如果檢查後發現請求頭中media類型爲text/x-vcard時,將調用index.vcf模板渲染:
BEGIN:VCARD
VERSION:3.0
N:${name}
FN:${name}
ORG:${organisation}
URL:${url}
END:VCARD
4 關於REST
REST全稱爲Representational State Transfer,即表述性狀態傳輸。它是一種爲分佈式超媒體系統(比如萬維網)而設計的軟件架構方式。REST定義了一些關鍵的規則:
- 應用的所有功能都被劃分爲資源。
- 每個資源都使用URI來唯一訪問。
- 所有資源共享統一的接口用於客戶端與資源之間進行狀態傳輸。
如果應用使用的是HTTP協議,那麼這些接口是通過一系列可用的HTTP方法來定義的。HTTP協議往往通過以下方法來使用資源的狀態:
- 客戶端-服務器模式。
- 無狀態模式。
- 緩存模式。
- 分層模式。
如果應用遵循了REST設計規則,那麼該應用就可以被稱爲RESTful了。Play框架可以很容易地構建RESTful應用:
- Play的路由器通過解析URI和HTTP方法,將請求路由至Action方法。基於正則表達形式的URI爲開發提供了更好的靈活性。
- 協議是無狀態的,這意味着在兩次成功的請求之間不會把任何狀態保存在服務器中。
- Play將HTTP作爲關鍵的特性,因此框架提供了對HTTP信息的完全訪問。