2010-01-10 82 views
3

如果我有一個類似http://localhost/Test/edit/ {id}的網址,我希望將{id}轉換爲參數而不是URL路徑部分。這是正確的方式來處理像Lift的RESTful URL嗎?

是否通過創建一個帶有RewriteRequest的菜單來實現它的最佳方式?因爲我發現它有點樣板,如果我有像這樣的很多網址模式。

val menu = Menu(new Loc[Unit] { 

    override def name = "Test" 
    override def text = "Test" 
    override def link = (List ("Test"), true) 
    override def params = Nil 
    override def defaultValue = Full(()) 


    def isTarget (path: ParsePath) = path match { 
     case ParsePath (List("Test", "edit", id), _, _, _) => true 

     case _ => false 
    } 

    override def rewrite = Full (NamedPF("Test") { 
     case RewriteRequest (path, _, _) if isTarget(path) => 
      RewriteResponse(List("Test", "edit"), 
          Map("id" -> "1024")) ->() 

    }) 
}) 

回答

3

在你boot.scala需要以下(從實際工作代碼!)請注意,每個RewriteResponse路徑必須位於您的站點地圖中。

LiftRules.rewrite.append { 
    case RewriteRequest(ParsePath(List("shopInfo", "view", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "view" :: Nil, Map("id" -> id)) 
    case RewriteRequest(ParsePath(List("shopInfo", "orders", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "orders" :: Nil, Map("id" -> id)) 
    case RewriteRequest(ParsePath(List("shopInfo", "sync", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "sync" :: Nil, Map("id" -> id)) 
    case RewriteRequest(ParsePath(List("shopInfo", "delete", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "delete" :: Nil, Map("id" -> id)) 
    case RewriteRequest(ParsePath(List("shopInfo", "edit", id), _, _, _), _, _) => RewriteResponse("shopInfo" :: "edit" :: Nil, Map("id" -> id)) 
} 
0

爲什麼要將其更改爲查詢參數?是出於技術還是框架的原因?

{id}屬於我的URI路徑視圖,它標識了一個唯一的資源,我喜歡將這些信息保存在路徑中。 URI可以是任何類型的字符串(所以查詢參數也可以),但是我會將URI建模爲儘可能接近資源id一致。

+0

問題是,如果我在webapp/Test下有一個名爲edit.html的模板,這是我用來編輯項目的模板。 和我有類似下面的菜單實例: 菜單(LOC(「測試」,列表(「測試」) - >真,「測試」)) 它只會匹配的網址,如http://本地主機/測試/編輯,而不是像http:// localhost/Test/edit/1 – 2010-01-10 05:14:19

1

對不起,上面的評論是一個混亂。

問題是,如果我在webapp/Test下有一個名爲edit.html的模板,這是我用來編輯項目的模板。

而且我有一個像菜單實例如下:

Menu (Loc("Test", List("Test") -> true, "Test")) 

它只會像http://localhost/Test/edit匹配的網址,而不是類似的東西http://localhost/Test/edit/1

2

感謝您的回覆。

我最需要的是這些重寫事項與Menu緊密結合,因此我可以將它們設置在我的Model類中,就像CRUDify特徵一樣。最後,我創建了一個Loc自己的子類來處理這些重寫規則,並且我發現它工作得很好,並且使事情變得更簡單(至少對我而言),所以我在這裏發佈代碼。

隨意複製此,如果有人需要它

/** 
* A RESTful-like URL handling Loc 
* 
* If you have the following templates: 
* 
* * webapps/item/edit.html 
* * webapps/item/view.html 
* 
* You want the following URL map to corresponding template with 
* last path component as a S parameter. 
* 
* http://localhost/item/edit/1 to http://localhost/item/edit 
* http://localhost/item/view/1 to http://localhost/item/view 
* 
* You could create a Menu with this Loc class in your Model object. 
* 
* <code> 
* object Item extends Item with LongKeyedMetaMapper[Item] 
* { 
*  // Other methods here... 
* 
*  def menu() { 
* 
*   // What methods do we have? 
*   val methods = List ("view", "edit") 
* 
*   val parameterName = "itemID" 
*   val itemLoc = new RESTfulLoc("Item", List("item"), "Item", 
*          methods, parameterName) 
* 
*   Menu (itemLoc) 
*  } 
* } 
* </code> 
* 
* Now add the menu to SiteMap in Boot.boot 
* 
* <code> 
* class Boot { 
*  def boot() { 
*   
*   val entries = Item.menu :: Nil 
* 
*   LiftRules.setSiteMap(SiteMap(entries:_*)) 
*  } 
* } 
* </code> 
* 
* 
* Finally, You could access the parameter in your snippet with 
* S.param("itemID") 
* 
*/ 
class RESTfulLoc (val name: String, val path: List[String], 
        val text: LinkText[Unit], val methods: List[String], 
        val parameterName: String, 
        val locParams: LocParam[Unit]*) extends Loc[Unit] 
{ 
    override val defaultValue = Full(()) 
    override val params = locParams.toList 
    override val link: Link[Unit] = (List(path.first), true) 

    def this (name: String, path: List[String], text: LinkText[Unit], 
       methods: List[String], locParams: LocParam[Unit]*) = 
    { 
     this (name, path, text, methods, "id", locParams:_*) 
    } 

    private def isTarget (path: ParsePath) = 
    { 
     path.partPath -- this.path match { 
      case List (action, id) => { 
       (methods contains action) && id != "index" 
      } 
      case _ => false 
     } 
    } 

    override def rewrite = Full (NamedPF("RESTfulLoc") 
    { 
     case RewriteRequest (path, _, _) if isTarget(path) => { 
      val parameter = path.partPath.last 
      val action = path.partPath.init 
      val data  = Map (parameterName -> parameter) 

      RewriteResponse(action, data) ->() 
     } 
    }) 
} 
2

我無意中發現這個職位,因爲我有同樣的問題。 Jim Barrows的回答是正確的(也是最簡單的),但沒有任何解釋,我很難琢磨那些代碼在做什麼。有關吉姆解決方案工作原因的詳細解釋,請參閱電梯在線書籍(http://groups.google.com/group/the-lift-book)。查看題爲「URL重寫」的第3.12節,它將詳細介紹如何構建RESTful URL。

無論如何,應該不需要編寫自定義Loc來達到預期的效果。

祝你好運!

相關問題