繁体   English   中英

这是处理Lift Framework中类似RESTful URL的正确方法吗?

[英]Is this correct way to handle RESTful like URL in Lift Framework?

如果我有一个http:// localhost / Test / edit / {id}之类的URL,并且我想{id}转换为参数而不是URL路径部分。

用RewriteRequest创建菜单是最好的方法吗? 因为如果我有很多这样的URL模式,我会发现它有点样板。

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")) -> ()

    })
})

在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))
}

感谢您的所有答复。

我最想要的是这些重写内容与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) -> ()
        }
    })
}

我偶然发现了这个帖子,因为我有同样的问题。 Jim Barrows的答案是正确的(也是最简单的),但是没有任何解释,我很难理解该代码在做什么。 有关Jim的解决方案为何有效的详细说明,请参见在线Lift手册( http://groups.google.com/group/the-lift-book )。 请参阅标题为“ URL重写”的第3.12节,它逐步指导您如何构建RESTful URL。

无论如何,都无需编写自定义Loc即可达到所需的效果。

祝你好运!

抱歉,上面的评论有点混乱。

问题是,如果我在webapp / Test下有一个名为edit.html的模板,这是我用来编辑项目的模板。

我有一个如下的Menu实例:

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

它只会匹配类似http:// localhost / Test / edit的 URL,而不匹配类似http:// localhost / Test / edit / 1的 URL

为什么要更改它以查询参数? 是出于技术或框架原因?

在我看来,{id}​​属于URI路径,它标识唯一的资源,我希望将此信息保留在路径内。 URI可以是任何类型的字符串(因此查询参数也可以使用),但是我将对URI进行建模,使其与资源ID尽可能接近。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM