将参数化 URL 添加到 Lift 应用程序

Add a parametrised URL to a Lift application

我需要参数化 URLs 的最基本情况:有一个像 localhost:8080/editStudy/4 这样的 URL,这将导致一个用于编辑 ID 等于 4 的研究的表格。

但即使翻阅了 Lift Wiki 和我拥有的书籍,我也没有找到如何去做。到目前为止,我有一个 HTML 页面 editStudy.html,将来会包含编辑表单,一个 class StudyDisplayer 应该呈现表单,一个对象StudyDisplayer 定义了菜单之类的东西(它是一个 ParamMenuable,不管它是什么),以及站点地图中的一个条目。

当去 localhost:8080/editStudy/4 我得到

The Requested URL /editStudy/4 was not found on this server

尽管站点地图中引用了该位置。我做错了什么?当 URL 被访问时,我在哪里告诉 Lift 显示 editStudy 页面?


editStudy.html:

<html>
  <head>
    <title></title>
    <meta content="">
        <link rel="stylesheet" type="text/css" href="litsuche.css">
  </head>
  <body>
    <nav>
      <span data-lift="Menu.builder"></span>
    </nav>
    <div data-lift="StudyDisplayer">
        <h1>Editing the study <span id="reference"></span></h1>
    </div>
  </body>
</html>

StudyDisplayer:

package code
package snippet

import org.rumtscho.litsuche._
import net.liftweb.util.BindHelpers._
import xml.Text

import net.liftweb.sitemap._

object StudyDisplayer {

  def showStudies = {
    val theStudies = Study.findAll

    "li *" #> theStudies.map {
      s =>
        ".id *" #> Text(s.id.toString) &
        ".handmadeRef *" #> Text(s.reference) & 
        ".description *" #> Text(s.description) & 
        ".editStudyButton" #> <button class="editStudyButton" onclick={"location.href='" + editStudyLoc.calcHref(s) + "'"}>edit</button>
    }
  }


    val editStudyLoc = Menu.param[Study](
        "EditStudy", 
        "editStudy", //This is supposed to be some kind of link, but it doesn't work with the name of the file, with or without a .html ending. The file itself is in the root directory. 
        Study.findByIdAsString(_),
        _.id.toString()
        ) / "editStudy" / *
}

class StudyDisplayer(study: Study) {
  def render = "#reference *" #> study.reference
}

以及Boot.scala的相关摘录:

def sitemap(): SiteMap = SiteMap(
  Menu.i("Home") / "index",
  Menu.i("List studies") / "studies", 
  Menu(StudyDisplayer.editStudyLoc),
  Menu.i("Temporary page") / "scratchpad")

LiftRules.setSiteMap(sitemap())

Lift 有两种添加参数的机制。 Menu.param and Menu.params。它们之间的区别在于所需参数的数量。

Menu.param 假设有一个参数,所以在你的情况下你有:

Menu.param[Study](
    "EditStudy", 
    "editStudy", 
    Study.findByIdAsString(_),
    _.id.toString()
) / "editStudy" 

这是最简单的机制,因为它会查找名为 "editStudy.html" 的模板,并采用它假定存在的一个参数并将其传递给您的函数:Study.findIdAsString。如果函数 returns Full,未装箱的值将传递给您的代码段进行渲染。如果函数 returns Empty Lift 将 return 默认为 404。

Menu.Params 大致是相同的想法,但它允许您指定多个参数 and/or 匹配多个 URL。例如,我们可以将您的示例调整为:

Menu.params[Study]("EditStudy", "EditStudy", {
    case s :: Nil => Study.findByIdAsString(s)
    case _ => Empty
}, {
    case g = > g.id :: Nil
}) / "editStudy" / *

您会注意到我们在 "editStudy" 之后有一个通配符匹配。原因是没有对参数数量的假设,因此如果您正在寻找单个参数或 ** 以将每个子路径与 [=40= 匹配,则需要指定它正在寻找的内容 * ].对于您想要查找的每个模式,您只需将一个新的 case 语句添加到您的匹配中。

如果您想 return 多个项目,您甚至可以使用元组键入 Menu.params,例如:

Menu.param[(Study, Grade)]("EditStudy", "EditStudy", {
    case s :: g :: Nil => (Study.findByIdAsString(s), Grade.findByIdAsString(g))
    case _ => Empty
}, {
    case (g, s) => g.id :: s.id :: Nil
}) / "editStudy" / **

它会在 url 中查找两个 id 参数,例如:“/editStudy/1234/5678”

另请注意,在处理模式匹配时,使用提取器来检索值通常更简洁。如果需要,This article 有更多关于它们的信息。