play使用起來(4)

1、路由


Play框架中的路由器是負責將傳入的HTTP請求映射爲Action調用(即控制器中被聲明爲public static void的方法)的組件。HTTP請求被MVC框架視爲事件,其主要包括以下兩塊內容:

  • 請求路徑(比如/clients/1542,/photos/list),其中可以包含查詢字符串。
  • HTTP方法(GET,POST,PUT,DELETE)。

Play路由器使用的配置文件爲conf/routes,該文件列出了應用需要的所有路由規則。每條路由由HTTP方法和與Java調用相關聯的URI組成。以下是路由配置的例子:

GET    /clients/{id}             Clients.show 
      路由配置總是從HTTP方法開始,URI作爲中間部分,最後的元素是Java調用。在路由文件中可以使用#進行註釋:
# Display a client
GET    
/clients/{id}             Clients.show    


1.1 HTTP方法#

      HTTP協議支持以下所列的方法,用於指定客戶請求服務器的動作,其中GET和POST是最爲常用的兩種方法:

  • GET
  • POST
  • PUT
  • DELETE
  • HEAD


 Play同時也支持以WebSocket的方式來調用服務器端的Action方法

 如果在路由文件中指定*作爲HTTP方法,那麼這個路由會匹配任何HTTP請求:

*   /clients/{id}             Clients.show    

      使用上述的路由配置,以下兩個HTTP請求都會被框架接受:

GET /clients/1541
PUT
/clients/1212

1.2 URI表達式#

      URI表達式定義了路由規則需要的請求路徑,請求路徑中允許存在動態內容,但必須被聲明在{}中。


/clients/all
      以上的路由配置只能精確匹配到:
/clients/all


      但是如果以包含動態部分配置路由規則:

/clients/{id}
      則可以分別匹配:
/clients/12121
      和
/clients/toto


      如果某條路由配置的URI中需要包含多個動態部分,可以採用下例方法進行配置:

/clients/{id}/accounts/{accountId}

      默認情況下,動態部分的匹配策略採用的是正則表達式/[^/]+/。也可以爲動態部分定義自己的正則表達式,以下是使用正則表達式的例子。

      路由規則只允許接受id爲數字的值:

/clients/{<[0-9]+>id}

      路由規則確保id是長度爲4到10字符的小寫單詞:

/clients/{<[a-z]{4,10}>id}

      正則表達式的使用非常靈活,還可以定義更多的路由規則,本節就不做贅述了。

注意:

動態部分指定後,控制器可以在HTTP參數map中獲取該值。


      默認情況下,Play將URI尾部的斜線(“/”)作爲重要的組成部分,因爲有無“/”將會出現不同的結果。比如:

GET     /clients         Clients.index

      該路由規則會匹配/clients,而不是/clinets/(注意這裏的區別),但可以通過在斜線後面增加問號來同時匹配兩個URI:

GET     /clients/?       Clients.index
注意:

URI除了尾斜線不允許有其他可選的部分。


1.3 定義Java調用#

      路由定義的最後部分爲需要調用的Java方法:控制器中必須定義指定的Action方法,否則會提示找不到控制器方法的錯誤信息;必須聲明爲public static void方法;控制器需作爲play.mvc.Controller的子類定義在controllers包中。

      如果控制器沒有在controllers包中定義,在配置路由規則時可以在其名稱之前增加Java包(比如admin.Dashboard.index)的說明。由於controllers包本身被Play默認包含,所以用戶在配置路由時不需要顯式地指定。

GET    /admin             admin.Dashboard.index   

1.4 404作爲Action#

      可以直接使用404作爲路由配置中的Action部分。如果這樣進行配置,對應的URL路徑就會被Play應用所忽略。比如:

# 忽略favicon請求
GET    
/favicon.ico            404


1.5 指定靜態參數#

      在某些情況下,可能會需要基於不同的參數值定義特殊路由。以下是預先定義好的Action:

public static void page(String id) {
   
Page page = Page.findById(id);
    render
(page);
}

      針對該Action,常規的路由配置爲:

GET            /pages/{id}                    Application.page

      現在給參數id=home的頁面指定一條特殊的URL,需要通過設置靜態參數來實現:

GET            /home                          Application.page(id:'home')
GET            
/pages/{id}                    Application.page

      當參數id=home時,兩條路由配置等價,但是由於前者具有較高的優先級,所以被作爲默認的URL來調用Application.page。



1.6 變量和腳本#

      與模板中的使用方法類似,在routes文件中可以使用${...}作爲變量表達式,使用%{...}作爲腳本表達式,比如:

%{ context = play.configuration.getProperty('context', '') }%
 
# 主頁
GET    $
{context}         Secure.login
GET    $
{context}/        Secure.login

      在路由文件中定義變量和腳本的典型例子是CRUD模塊的routes文件。該文件中使用crud.types標籤對model類型進行迭代,爲每種類型生成控制器路由定義。以後文章會詳細介紹CRUD模塊的使用。

#{crud.types}
GET                    
/?                                              ${type.controllerClass.name.substring(12).replace('$','')}.index
GET                    
/${type.controllerName}                         ${type.controllerClass.name.substring(12).replace('$','')}.list
GET                    
/${type.controllerName}/new                     ${type.controllerClass.name.substring(12).replace('$','')}.blank
GET                    
/${type.controllerName}/{id}                    ${type.controllerClass.name.substring(12).replace('$','')}.show
GET                    
/${type.controllerName}/{id}/{field}            ${type.controllerClass.name.substring(12).replace('$','')}.attachment
GET                    
/${type.controllerName}/{id}/edit               ${type.controllerClass.name.substring(12).replace('$','')}.edit
POST                    
/${type.controllerName}                         ${type.controllerClass.name.substring(12).replace('$','')}.create
POST                    
/${type.controllerName}/{id}                    ${type.controllerClass.name.substring(12).replace('$','')}.save
DELETE                  
/${type.controllerName}/{id}                    ${type.controllerClass.name.substring(12).replace('$','')}.delete
#{/crud.types}

Play會按照聲明的順序,優先選擇最先聲明的路由,比如:

GET             /clients/all                       Clients.listAll
GET            
/clinets/{id}                      Clients.show

      在上例的路由配置中,雖然請求/clients/all可以同時匹配這兩條路由配置,但按照聲明的優先順序會被第一條路由攔截,並調用相應的Clients.listAll方法。


  如果id參數需要匹配5個數字,在不使用重複規則的前提下,只能連續使用五個\d元字符,而使用重複規則後,規則的如下:

GET          /clinets/{<\d{5}>id}                    Clients.index

      以下路由規則匹配2個大寫字母以及3-4個數字:

GET          /clinets/{<[A-Z]{2}[0-9]{3,4}>id}       Clients.index

1.7 staticDir:mapping#

      Play的路由配置使用特殊的Action(staticDir)將存放靜態資源的public目錄開放。該目錄裏包含的資源可以是圖片,Javascript,Stylesheet等,這些資源將直接響應給客戶端,並不需要服務器做進一步加工處理:

GET    /public/           staticDir:public

      當客戶端請求/public/*路徑時,Play會從應用的public文件夾中獲取相應的靜態資源。這裏的優先級與標準路由配置一樣適用。


1.8 staticFile:mapping#

      還可以直接將URL路徑映射爲靜態文件:

GET     /home                   staticFile:/public/html/index.html

      當客戶端通過GET方法請求/home時,服務器將不做任何處理直接把/public/html目錄下面的index.html文件返回給客戶端。


 1.9 虛擬主機

   Play的路由器具有主機匹配功能,當Action的變量需要從主機參數(指子域名,而不是子目錄)中獲取時,就顯得特別有用。比如SAAS應用可以使用如下方式配置路由規則:

GET    {client}.mysoftware.com/         Application.index

      根據以上配置,框架會自動獲取client的值作爲請求的參數:

public static void index(String client) {
   
...
}

      如果在模板中使用@@{...}標籤,那麼框架會根據指定的條件來選擇對應的路由,這種方式在很多場合下都非常實用。比如,需要在產品中使用額外的服務器來提供靜態資源,則可以採用如下方式進行路由配置:

#{if play.Play.mode.isDev()}
    GET    
/public/                        staticDir:public
#{/}
#{else}
    GET     assets
.myapp.com/               staticDir:public
#{/}

      對應模板中的代碼如下:

<img src="@@{'/public/images/logo.png'}">

      當應用在DEV模式下運行時,靜態資源的URL爲http://locahost:9000/public/images/logo.png;如果運行在PROD模式下,URL爲http://assets.myapp.com/images/logo.png。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章