2010-01-10 85 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来达到预期的效果。

祝你好运!

相关问题