我正在尝试关注Lift Web App Cookbook:
中的REST api示例(该项目可以在github上找到:https://github.com/kindlychung/liftrestapi)
客户端模型:
package code.model
import net.liftweb.json.JsonDSL._
case class Client(id: Int, name: String, email: String) {
def asJson = {
("id" -> id) ~
("name" -> name) ~
("email" -> email)
}
}
客户数据存储:
package code.session
import code.model.Client
object ClientCache {
var clients: List[Client] = Nil
def startClient(): Unit = {
if (clients.isEmpty) clients = (1 to 10).toList.map(
i => Client(i, "Client " + i, "client_" + i + "@email.com")
)
}
}
休息服务提供商:
package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http._
import net.liftweb.json.JsonDSL._
import net.liftweb.util.Helpers._
import code.session.ClientCache
/**
* Created by IDEA on 29/10/15.
*/
object Clients extends RestHelper {
serve({
case Req("api" :: "clients" :: Nil, _, GetRequest) => listClients()
})
def listClients(): LiftResponse = JsonResponse("clients" -> ClientCache.clients.map(_.asJson))
}
初始化客户端数据并启动REST API:
package bootstrap.liftweb
import net.liftweb._
import util._
import Helpers._
import common._
import http._
import sitemap._
import Loc._
import net.liftmodules.JQueryModule
import net.liftweb.http.js.jquery._
import net.liftweb.common.Logger
import code.rest.Clients
import code.session.ClientCache
/**
* A class that's instantiated early and run. It allows the application
* to modify lift's environment
*/
class Boot extends Logger {
def boot {
// where to search snippet
LiftRules.addToPackages("code")
ClientCache.startClient()
LiftRules.statelessDispatch.append(Clients)
val canManage_? = If(
// always true means everybody can manage
() => {
true
},
// if false, redirect to root
() => RedirectResponse("/"))
val isAdmin_? = If(
// always false means nobody is admin
() => {
false
},
// if false, redirect to /contacts/list
() => RedirectWithState("/contacts/list", MessageState("Authorized personnel only" -> NoticeType.Warning)))
// Build SiteMap
val entries = List(
Menu.i("Home") / "index", // the simple way to declare a menu
Menu.i("List contacts") / "contacts" / "list" >> canManage_?,
Menu.i("Create") / "contacts" / "create" >> canManage_?,
Menu.i("Edit") / "contacts" / "edit" >> canManage_?,
Menu.i("Delete") / "contacts" / "delete" >> canManage_?,
Menu.i("View") / "contacts" / "view" >> canManage_?,
Menu.i("Send email") / "contacts" / "send",
// more complex because this menu allows anything in the
// /static path to be visible
Menu(Loc("Static", Link(List("static"), true, "/static/index"),
"Static Content")))
// set the sitemap. Note if you don't want access control for
// each page, just comment this line out.
LiftRules.setSiteMap(SiteMap(entries: _*))
//Show the spinny image when an Ajax call starts
LiftRules.ajaxStart =
Full(() => LiftRules.jsArtifacts.show("ajax-loader").cmd)
// Make the spinny image go away when it ends
LiftRules.ajaxEnd =
Full(() => LiftRules.jsArtifacts.hide("ajax-loader").cmd)
// Force the request to be UTF-8
LiftRules.early.append(_.setCharacterEncoding("UTF-8"))
//Init the jQuery module, see http://liftweb.net/jquery for more information.
LiftRules.jsArtifacts = JQueryArtifacts
JQueryModule.InitParam.JQuery = JQueryModule.JQuery191
JQueryModule.init()
}
}
从客户端访问api:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Home</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$.ajax({
url: "/api/clients",
contentType: "application/json"
}).done(function(data) {
var clients = "";
$.each(data.clients, function(i, client) {
clients += '<tr>' +
'<td>' + client.ed + '</td><td>' + client.name + '</td><td>' + 'client.email' + '</td><td>' + 'view' + '</td><td>' + 'delete' + '</td>'
}
});
$tbody.html(clients);
};
</script>
</head>
<body data-lift-content-id="main">
<div id="main" data-lift="surround?with=default;at=content">
<h2>Welcome to your project!!!!!</h2>
<p>
<span data-lift="HelloWorld.howdy">
Welcome to your Lift app at <span id="time">Time goes here</span>
</span>
</p>
<div data-lift="Calculator.plus">
2 + 2 = <span id="result">some number</span>
</div>
<table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Email</th>
<th>View</th>
<th>Delete</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</body>
</html>
根据这本书,我应该在刷新浏览器后看到类似的内容:
但我只看到表格的标题。这里出了什么问题?
build.sbt:
name := "Lift 2.6 starter template"
version := "0.0.4"
organization := "net.liftweb"
scalaVersion := "2.11.2"
resolvers ++= Seq("snapshots" at "https://oss.sonatype.org/content/repositories/snapshots",
"releases" at "https://oss.sonatype.org/content/repositories/releases"
)
seq(webSettings :_*)
unmanagedResourceDirectories in Test <+= (baseDirectory) { _ / "src/main/webapp" }
scalacOptions ++= Seq("-deprecation", "-unchecked")
libraryDependencies ++= {
val liftVersion = "2.6.2"
Seq(
"net.liftweb" %% "lift-webkit" % liftVersion % "compile",
"net.liftmodules" %% "lift-jquery-module_2.6" % "2.8",
"org.eclipse.jetty" % "jetty-webapp" % "8.1.7.v20120910" % "container,test",
"org.eclipse.jetty" % "jetty-plus" % "8.1.7.v20120910" % "container,test", // For Jetty Config
"org.eclipse.jetty.orbit" % "javax.servlet" % "3.0.0.v201112011016" % "container,test" artifacts Artifact("javax.servlet", "jar", "jar"),
"ch.qos.logback" % "logback-classic" % "1.0.6",
"org.specs2" %% "specs2" % "2.3.12" % "test"
)
}
我还尝试了Lift cookbook:
中的另一个例子package code.rest
import net.liftweb.http.rest.RestHelper
import net.liftweb.http.LiftRules
object IssuesService extends RestHelper {
def init() : Unit = {
LiftRules.statelessDispatch.append(IssuesService)
}
serve("issues" / "by-state" prefix {
case "open" :: Nil XmlGet _ => <p>None open</p>
case "closed" :: Nil XmlGet _ => <p>None closed</p>
case "closed" :: Nil XmlDelete _ => <p>All deleted</p>
})
}
使用以下命令将其连接到Boot.scala:
import code.rest.IssuesService
IssuesService.init()
预期结果:
curl -H 'Content-Type: application/xml' http://localhost:8080/issues/by-state/open
<?xml version="1.0" encoding="UTF-8"?>
<p>None open</p>
观察结果:
curl -H 'Content-Type: application/xml' http://localhost:8080/issues/by-state/open
<!DOCTYPE html>
<html> <body>The Requested URL /issues/by-state/open was not found on this server</body> </html>
WEB-INF / web.xml的内容:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>LiftFilter</filter-name>
<display-name>Lift Filter</display-name>
<description>The Filter that intercepts lift calls</description>
<filter-class>net.liftweb.http.LiftFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LiftFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
答案 0 :(得分:0)
通过修改Clients.scala
这样的文件来解决问题:
package code.rest
import code.model.Client
import net.liftweb.http.rest.RestHelper
import net.liftweb.http._
import net.liftweb.json.JsonDSL._
import net.liftweb.util.Helpers._
/**
* Created by IDEA on 29/10/15.
*/
object Clients extends RestHelper {
var clients = (1 to 10).toList.map(
i => Client(i, "Client " + i, "client_" + i + "@email.com")
)
def init: Unit = {
LiftRules.statelessDispatch.append(Clients)
}
serve(List("clients") prefix {
case Nil XmlGet _ => listClients()
})
def listClients(): LiftResponse = JsonResponse("clients" -> clients.map(_.asJson))
}
我仍然不太清楚为什么原版本没有用。