2013-03-28 57 views
8

我的web應用將從外部系統觸發。它會調用我的應用程序的一個請求路徑,但對不同類型的請求使用不同的查詢參數。Play框架中基於查詢參數的路由

其中一個參數是定義要做什麼的「動作」。其餘部分取決於「行動」。

這樣我就可以得到請求參數這樣的:

action=sayHello&user=Joe 
action=newUser&name=Joe&address=xxx 
action=resetPassword 
... 

我希望能夠它確實是這樣的查詢參數的路由,並儘可能多的驗證,以在比賽路線文件同樣對其進行編碼儘可能的其他參數。

我所擁有的是一個具有大量可選參數的所有這些可能性的路由。處理它的動作以大模式匹配開始,以進行分派和參數驗證。

使用谷歌搜索和檢查所以剛剛彈出了很多樣本​​,其中params在請求路徑中以某種方式編碼,所以多個路徑被路由到相同的動作,但我想反其道而行之:一條路徑被路由到不同的動作。

我的一位同事說我們可以有一個「調度員」動作,它只是基於「動作」參數重定向。它會比目前的解決方案更結構化,但它不會消除應該有選擇地傳遞給下一個動作的可選參數的長列表,所以我希望有人知道更好的解決方案:-)

BTW調用我的應用程序的外部系統是由另一家公司開發的,我對此設計沒有影響,因此不能改變我的應用程序觸發方式。

回答

6

單個調度程序操作可能是要走的路,而且您不需要在路徑中指定所有可選參數。如果action總是在那裏,那麼這是你真正需要的唯一一個。

GET /someRoute  controller.dispatcher(action: String) 

然後在動作方法,你可以訪問request.queryString得到任何其他的可選參數。

3

注:我不經歷斯卡拉開發者,所以也許呈現片段可以優化...什麼是對你很重要,他們是有效的和工作。

所以...

你並不需要聲明每個可選PARAM在routes文件。這是類型參數驗證的最佳捷徑,最好的選擇是說服'其他公司'使用您準備好的API ...無論如何,如果您沒有這種可能性,您還可以根據需要處理請求。

一般:調度的方法似乎是正確的在這個地方,好在你並不需要申報所有可選PARAMS在routes和動作/方法之間傳遞,因爲他們可以直接從請求中獲取。在PHP中,它可以與$_GET['action']和Play 2控制器的Java版本進行比較 - DynamicForm class - form().bindFromRequest.get("action")

假設你有一個路線:

GET  /dispatcher  controllers.Application.dispatcher 

在這種情況下,您的調度員的行動(和其他方法)可以看起來像:

def dispatcher = Action { implicit request => 
    request.queryString.get("action").flatMap(_.headOption).getOrElse("invalid") match { 
     case "sayHello" => sayHelloMethod 
     case "newUser" => newUserMethod 
     case _   => BadRequest("Action not allowed!") 
    } 
} 

// http://localhost:9000/dispatcher?action=sayHello&name=John 
def sayHelloMethod(implicit request: RequestHeader) = { 
    val name = request.queryString.get("name").flatMap(_.headOption).getOrElse("") 
    Ok("Hello " + name) 
} 

// http://localhost:9000/dispatcher?action=newUser&name=John+Doe&[email protected] 
def newUserMethod(implicit request: RequestHeader) = { 
    val name = request.queryString.get("name").flatMap(_.headOption).getOrElse("") 
    val address = request.queryString.get("address").flatMap(_.headOption).getOrElse("") 
    Ok("We are creating new user " + name + " with address " + address) 
} 

當然,你需要來驗證傳入的類型和值「手動」,特別是當操作將在DataBase上進行時,無論如何,這是您現在解決的最大部分問題。

+1

你的答案差不多2年過去了。在最新的播放框架中是否有更好的解決方案? – Ikrom

+0

@Ikrom,我認爲更好的解決方案就像接受的答案,但使用選項params:GET/someRoute controller.dispatcher(action:Option [String]) – faster2b