昨天写了个sbt构建scala项目的文章,就是为了今天的scalatra做铺垫。
运行了下,确实很强大.它集web容器、编译全套。不多说了大家自己玩玩!
还蛮有意思的
Scalatra is a tiny, [Sinatra](http://www.sinatrarb.com/)-like web framework for [Scala](http://www.scala-lang.org/).
## Example
import org.scalatra._
class ScalatraExample extends ScalatraServlet {
get("/") {
<h1>Hello, world!</h1>
}
}
## Quick start
1. Git-clone the prototype. Alternatively, download and extract a [tarball](https://github.com/scalatra/scalatra-sbt-prototype/tarball/master) or [zip](https://github.com/scalatra/scalatra-sbt-prototype/zipball/master).
$ git clone git://github.com/scalatra/scalatra-sbt-prototype.git my-app
2. Change directory into your clone.
$ cd my-app
3. Launch [SBT](http://code.google.com/p/simple-build-tool).
$ sbt
4. Fetch the dependencies.
> update
5. Start Jetty, enabling continuous compilation and reloading.
> jetty-run
> ~prepare-webapp
6. Browse to http://localhost:8080/.
7. Start hacking on `src/main/scala/MyScalatraFilter.scala`.
Note: if you keep getting frequent OutOfMemory errors from `sbt` you can try changing its script as described in [this document](http://www.assembla.com/wiki/show/liftweb/Using_SBT) so that it executes this command line:
java -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256m -Xmx512M -Xss2M -jar `dirname $0`/sbt-launch.jar "$@"
Note 2: if you already have a checkout, and after a `git pull` the build fails, try to explicitly run the `update` and `clean` sbt tasks before running `compile`.
### Alternative Maven quickstart.
See the [simple-scalatra-archetype](http://github.com/Srirangan/simple-scalatra-archetype).
## Community
### Mailing list
The [scalatra-user](http://groups.google.com/group/scalatra-user) mailing list is open to anybody. It is the best place to ask questions, so everybody can see the answer.
### IRC channel
For those topics that are easier to discuss in real time, or just to hang out with some fun people, join us on the #scalatra channel on irc.freenode.org.
## Routes
In Scalatra, a route is an HTTP method paired with a URL matching pattern.
get("/") {
// show something
}
post("/") {
// submit/create something
}
put("/") {
// update something
}
delete("/") {
// delete something
}
### Route order
The first matching route is invoked. Routes are matched from the bottom up. _This is the opposite of Sinatra._ Route definitions are executed as part of a Scala constructor; by matching from the bottom up, routes can be overridden in child classes.
### Path patterns
Path patterns add parameters to the `params` map. Repeated values are accessible through the `multiParams` map.
#### Named parameters
Route patterns may include named parameters:
get("/hello/:name") {
// Matches "GET /hello/foo" and "GET /hello/bar"
// params("name") is "foo" or "bar"
<p>Hello, {params("name")}</p>
}
#### Wildcards
Route patterns may also include wildcard parameters, accessible through the `splat` key.
get("/say/*/to/*) {
// Matches "GET /say/hello/to/world"
multiParams("splat") # == Seq("hello", "world")
}
get("/download/*.*) {
// Matches "GET /download/path/to/file.xml"
multiParams("splat") # == Seq("path/to/file", "xml")
}
#### Regular expressions
The route matcher may also be a regular expression. Capture groups are accessible through the `captures` key.
get("""^\/f(.*)/b(.*)""".r) {
// Matches "GET /foo/bar"
multiParams("captures") # == Seq("oo", "ar")
}
#### Path patterns in the REPL
If you want to experiment with path patterns, it's very easy in the REPL.
scala> import org.scalatra.pattern._
import org.scalatra.pattern._
scala> val pattern = PathPatternParser.parseFrom("/foo/:bar")
pattern: PathPattern = PathPattern(^/foo/([^/?]+)$,List(bar))
scala> pattern("/y/x") // doesn't match
res1: Option[MultiParams] = None
scala> pattern("/foo/x") // matches
res2: Option[MultiParams] = Some(Map(bar -> ListBuffer(x)))
Obligatory scolding: the REPL is not a substitute for proper unit tests!
#### Rails-like pattern matching
By default, route patterns parsing is based on Sinatra. Rails has a similar, but not identical, syntax, based on Rack::Mount's Strexp. The path pattern parser is resolved implicitly, and may be overridden if you prefer an alternate syntax:
class RailsLikeRouting extends ScalatraFilter {
implicit override val string2RouteMatcher(path: String) =
RailsPathPatternParser(path)
get("/:file(.:ext)") { // matched Rails-style }
}
### Conditions
Routes may include conditions. A condition is any expression that returns Boolean. Conditions are evaluated by-name each time the route matcher runs.
get("/foo") {
// Matches "GET /foo"
}
get("/foo", request.getRemoteHost == "127.0.0.1") {
// Overrides "GET /foo" for local users
}
Multiple conditions can be chained together. A route must match all conditions:
get("/foo", request.getRemoteHost == "127.0.0.1", request.getRemoteUser == "admin") {
// Only matches if you're the admin, and you're localhost
}
No path pattern is necessary. A route may consist of solely a condition:
get(isMaintenanceMode) {
<h1>Go away!</h1>
}
### Actions
Each route is followed by an action. An Action may return any value, which is then rendered to the response according to the following rules:
<dl>
<dt>`Array[Byte]`</dt>
<dd>If no content-type is set, it is set to `application/octet-stream`. The byte array is written to the response's output stream.</dd>
<dt>`NodeSeq`</dt>
<dd>If no content-type is set, it is set to`text/html`. The node sequence is converted to a string and written to the response's writer.</dd>
<dt>`Unit`</dt>
<dd>This signifies that the action has rendered the entire response, and no further action is taken.</dd>
<dt>Any</dt>
<dd>For any other value, if the content type is not set, it is set to `text/plain`. The value is converted to a string and written to the response's writer</dd>.
</dl>
This behavior may be customized for these or other return types by overriding `renderResponse`.
## Filters
Before filters are evaluated before each request within the same context as the routes.
before {
// Default all responses to text/html
contentType = "text/html"
}
After filters are evaluated after each request, but before the action result is rendered, within the same context as the routes.
after {
if (response.status >= 500)
println("OMG! ONOZ!")
}
## Halting
To immediately stop a request within a filter or route:
halt()
You can also specify the status:
halt(410)
Or the body:
halt("This will be the body")
Or both:
halt(401, "Go away!")
## Passing
A route can punt processing to the next matching route using pass. Remember, unlike Sinatra, routes are matched from the bottom up.
get("/guess/*") {
"You missed!"
}
get("/guess/:who") {
params("who") match {
case "Frank" => pass()
case _ => "You got me!"
}
}
The route block is immediately exited and control continues with the next matching route. If no matching route is found, a 404 is returned.
## Accessing the Servlet API
### HttpServletRequest
The request is available through the `request` variable. The request is implicitly extended with the following methods:
1. `body`: to get the request body as a string
2. `isAjax`: to detect AJAX requests
3. `cookies` and `multiCookies`: a Map view of the request's cookies
4. Implements `scala.collection.mutable.Map` backed by request attributes
### HttpServletResponse
The response is available through the `response` variable.
### HttpSession
The session is available through the `session` variable. The session implicitly implements `scala.collection.mutable.Map` backed by session attributes. To avoid creating a session, it may be accessed through `sessionOption`.
### ServletContext
The servlet context is available through the `servletContext` variable. The servlet context implicitly implements `scala.collection.mutable.Map` backed by servlet context attributes.
## Configuration
The environment is defined by:
1. The `org.scalatra.environment` system property.
2. The `org.scalatra.environment` init property.
3. A default of `development`.
If the environment starts with "dev", then `isDevelopmentMode` returns true. This flag may be used by other modules, for example, to enable the Scalate console.
## Error handling
Error handlers run within the same context as routes and before filters.
### Not Found
Whenever no route matches, the `notFound` handler is invoked:
notFound {
<h1>Not found. Bummer.</h1>
}
### Error
The `error` handler is invoked any time an exception is raised from a route block or a filter. The throwable can be obtained from the `caughtThrowable` instance variable. This variable is not defined outside the `error` block.
error {
log.error(caughtThrowable)
redirect("http://www.sadtrombone.com/")
}
## Flash scope
Flash scope is available by mixing in `FlashMapSupport`, which provides a mutable map named `flash`. Values put into flash scope during the current request are stored in the session through the next request and then discarded. This is particularly useful for messages when using the [Post/Redirect/Get](http://en.wikipedia.org/wiki/Post/Redirect/Get) pattern.
## Templating with Scalate
Scalatra provides optional support for [Scalate](http://scalate.fusesource.org/), a Scala template engine.
1. Depend on scalatra-scalate.jar and a [slf4j binding](http://www.slf4j.org/manual.html#binding). In your SBT build:
val scalatraScalate = "org.scalatra" %% "scalatra-scalate" % scalatraVersion
val slf4jBinding = "ch.qos.logback" % "logback-classic" % "0.9.25" % runtime
2. Extend your application with `ScalateSupport`
import org.scalatra._
import org.scalatra.scalate._
class MyApplication extends ScalatraServlet with ScalateSupport {
// ....
}
3. A template engine is created as the `templateEngine` variable. This can be used to render templates and call layouts.
get("/") {
templateEngine.layout("index.scaml", "content" -> "yada yada yada")
}
Additionally, `createRenderContext` may be used to create a render context for the current request and response.
Finally, the [Scalate Console](http://scalate.fusesource.org/documentation/console.html) is enabled in development mode to display any unhandled exceptions.
## File upload support
Scalatra provides optional support for file uploads with <a href="http://commons.apache.org/fileupload/">Commons FileUpload</a>.
1. Depend on scalatra-fileupload.jar. In your SBT build:
val scalatraFileUpload = "org.scalatra" %% "scalatra-fileupload" % scalatraVersion
2. Extend your application with `FileUploadSupport`
import org.scalatra.ScalatraServlet
import org.scalatra.fileupload.FileUploadSupport
class MyApp extends ScalatraServlet with FileUploadSupport {
// ...
}
3. Be sure that your form is of type `multipart/form-data`:
get("/") {
<form method="post" enctype="multipart/form-data">
<input type="file" name="foo" />
<input type="submit" />
</form>
}
4. Your files are available through the `fileParams` or `fileMultiParams` maps:
post("/") {
processFile(fileParams("file"))
}
## WebSocket and Comet support through Socket.IO
Scalatra provides optional support for websockets and comet through [socket.io](http://socket.io). We depend on [the socketio-java project](http://code.google.com/p/socketio-java) to provide this support.
1. Depend on the scalatra-socketio.jar. In your SBT build:
val scalatraSocketIO = "org.scalatra" %% "scalatra-socketio" % scalatraVersion
2. SocketIO mimics a socket connection so it's easiest if you just create a socketio servlet at /socket.io/*
import org.scalatra.ScalatraServlet
import org.scalatra.socketio.SocketIOSupport
class MySocketIOServlet extends ScalatraServlet with SocketIOSupport {
// ...
}
3. Setup the callbacks
socketio { socket =>
socket.onConnect { connection =>
// Do stuff on connection
}
socket.onMessage { (connection, frameType, message) =>
// Receive a message
// use `connection.send("string")` to send a message
// use `connection.broadcast("to send")` to send a message to all connected clients except the current one
// use `connection.disconnect` to disconnect the client.
}
socket.onDisconnect { (connection, reason, message) =>
// Do stuff on disconnection
}
}
4. Add the necessary entries to web.xml
<servlet>
<servlet-name>SocketIOServlet</servlet-name>
<servlet-class>com.example.SocketIOServlet</servlet-class>
<init-param>
<param-name>flashPolicyServerHost</param-name>
<param-value>localhost</param-value>
</init-param>
<init-param>
<param-name>flashPolicyServerPort</param-name>
<param-value>843</param-value>
</init-param>
<init-param>
<param-name>flashPolicyDomain</param-name>
<param-value>localhost</param-value>
</init-param>
<init-param>
<param-name>flashPolicyPorts</param-name>
<param-value>8080</param-value>
</init-param>
</servlet>
When you want to use websockets with jetty the sbt build tool gets in the way and that makes it look like the websocket stuff isn't working. If you deploy the war to a jetty distribution everything should work as expected.
## Testing Your Scalatra Applications
Scalatra includes a test framework for writing the unit tests for your Scalatra application. The framework lets you send requests to your app and examine the response. It can be mixed into the test framework of your choosing; integration with [ScalaTest](http://www.scalatest.org/) and [Specs](http://code.google.com/p/specs/) is already provided. ScalatraTests supports HTTP GET/POST tests with or without request parameters and sessions. For more examples, please refer to core/src/test/scala.
ScalaTest
---------
### Dependencies
- scalatra-scalatest
### Code
Mix in ShouldMatchers or MustMatchers to your taste...
class MyScalatraServletTests extends ScalatraFunSuite with ShouldMatchers {
// `MyScalatraServlet` is your app which extends ScalatraServlet
addServlet(classOf[MyScalatraServlet], "/*")
test("simple get") {
get("/path/to/something") {
status should equal (200)
body should include ("hi!")
}
}
}
Specs
-----
### Dependencies
- scalatra-specs
### Example
object MyScalatraServletTests extends ScalatraSpecification {
addServlet(classOf[MyScalatraServlet], "/*")
"MyScalatraServlet when using GET" should {
"/path/to/something should return 'hi!'" in {
get("/") {
status mustEqual(200)
body mustEqual("hi!")
}
}
}
}
Other test frameworks
---------------------
### Dependencies
- scalatra-test
### Usage guide
Create an instance of org.scalatra.test.ScalatraTests. Be sure to call `start()` and `stop()` before and after your test suite.
## Maven Repository
To make usage of Scalatra as a dependency convenient, Maven hosting is now available courtesy of [Sonatype](https://docs.sonatype.com/display/NX/OSS+Repository+Hosting).
* [Releases](https://oss.sonatype.org/content/repositories/releases)
* [Snapshots](https://oss.sonatype.org/content/repositories/snapshots)
Authentication
==============
There is a new authentication middleware in the auth directory, to be documented soon. See an example at [usage example](http://gist.github.com/660701).
Another [example](https://gist.github.com/732347) for basic authentication can be found
To use it from an SBT project, add the following to your project:
val auth = "org.scalatra" %% "scalatra-auth" % scalatraVersion
## FAQ
### It looks neat, but is it production-ready?
- It is use in the backend for [LinkedIn Signal](http://sna-projects.com/blog/2010/10/linkedin-signal-a-look-under-the-hood/).
- [ChaCha](http://www.chacha.com/) is using it in multiple internal applications.
- A project is in currently development to support a site with over one million unique users.
Are you using Scalatra in production? Tell us your story on the [mailing list](http://groups.google.com/group/scalatra-user/).
### ScalatraServlet vs. ScalatraFilter
The main difference is the default behavior when a route is not found. A filter will delegate to the next filter or servlet in the chain (as configured by web.xml), whereas a ScalatraServlet will return a 404 response.
Another difference is that ScalatraFilter matches routes relative to the WAR's context path. ScalatraServlet matches routes relative to the servlet path. This allows you to mount multiple servlets under in different namespaces in the same WAR.
### Use ScalatraFilter if:
- You are migrating a legacy application inside the same URL space
- You want to serve static content from the WAR rather than a dedicated web server
### Use ScalatraServlet if:
- You want to match routes with a prefix deeper than the context path.
## Migration Guide
### scalatra-2.0.0.M2 to scalatra-2.0.0.M3
Should be compatible. If it broke, please share your tale of woe on the
mailing list.
### scalatra-2.0.0.M1 to scalatra-2.0.0.M2
1. Session has been retrofitted to a Map interface. `get` now returns an option instead of the value.
2. ScalaTest support has been split off into `scalatra-scalatest` module. ScalatraSuite moved to `org.scalatest.test.scalatest` package, and no longer extends FunSuite in order to permit mixing in a BDD trait. You may either use ScalatraFunSuite or explicitly extend FunSuite yourself.
### Step to Scalatra
Scalatra was renamed from Step to Scalatra to avoid a naming conflict with (an unrelated web framework)[http://sourceforge.net/stepframework]. scalatra-1.2.1 is identical to step-1.2.0 with the following exceptions:
1. The package has changed from `com.thinkminimo.step` to `org.scalatra`.
1. The `Step` class has been renamed to `ScalatraServlet`.
1. All other `Step*` classes have been renamed to `Scalatra*`.
## Related Projects
- [SSGI](http://github.com/scalatra/ssgi): Work in progress. Will provide an abstraction layer allowing a future version of Scalatra to run on web servers other than Servlet containers.
- [Bowler](http://bowlerframework.org): A RESTful, multi-channel ready web framework in Scala with a functional flavour, built on top of Scalatra and [Scalate](http://scalate.fusesource.org/).
发表评论
-
Scala + Twitter = Scitter(scala代码学习第15天)
2011-04-08 09:11 866Twitter 迅速占领了 Interne ... -
面向 Java 开发人员的 Scala 指南: Scala 和 servlet(scala代码学习第十一天)
2011-04-02 07:40 732Scala 显然是一门有趣的语言,很适合体现语言理论和创新方面 ... -
构建计算器,第 3 部分将 Scala 解析器组合子和 case 类结合起来(scala代码学习第十天)
2011-04-01 09:25 950欢迎勇于探索的读者回到我们的系列文章中!本月继续探索 Scal ... -
scala代码学习构建计算器,第2 部分(代码学习第九天)
2011-03-31 10:53 808回忆一下我们的英雄所处的困境:在试图创建一个 DSL(这里只不 ... -
Scala构建计算器,第1 部分(代码学习第8天)
2011-03-30 11:59 1193特定于领域的语言 可能您无法(或没有时间)承受来自于您的项目 ... -
scala包和访问修饰符(代码学习第七天)
2011-03-29 15:51 1615系列的过程中我遗漏了 ... -
实现继承(代码学习第五天)
2011-03-26 10:13 963近十几年来,面向对象语言设计的要素一直是继承的核心。不支持继承 ... -
关于特征和行为(代码学习第四天)
2011-03-25 09:38 698著名科学家、研究学者 ... -
Scala 控制结构内部揭密(scala代码学习第三天)
2011-03-24 09:15 1304迄今为止,在此 系列 ... -
面向 Java 开发人员的 Scala 指南: 类操作(代码学习第2天)
2011-03-22 19:06 740第一天中只是些简单应用 ,您只是稍微了解了一些 Scala 语 ... -
programming in scala 2nd代码学习(第一天)
2011-03-22 18:42 933近来没事,拿出了原先学习scala的代码 书中代码噢、拿出自己 ... -
A build tool for Scala(simple-build-tool) sbt安装指南
2011-03-20 22:49 2201今天有位写框架的大哥叫我学一学scalatra框架,找了 ... -
Scala functional style deferent from java OOP(特点)
2011-03-20 17:34 982该程序通过一段斐波那契数列的计算,比较一下Scala的函数式编 ... -
Java 开发人员的 Scala 指南: 面向对象的函数编程
2011-03-20 11:59 1035函数概念 开始之前, ...
相关推荐
Scalatra是轻量级的Web框架,有时也称为微框架 它主要将HTTP请求路由到操作。 实际的逻辑由取决于多个库的动作代码执行 scalatra应用程序可在任何Java servlet容器(例如tomcat,jetty和JBoss)上运行 它易于安装,...
通过研究源代码和相关文档,不仅可以深入理解Scalatra框架和Whirlycache的工作原理,还能了解到如何将这两个组件整合在一起,构建出一个安全、快速的Web服务。对于想要提升Scala和Java Web开发技能的开发者来说,这...
scalatra, 小型 Scala 高性能,异步网络框架,受 Sinatra 启发 Scalatra Scalatra是一个用于 Scala的小型。 Sinatra -like框架。示例import org.scalatra._class ScalatraExample extends Sc
Scalatra是一个轻量级、基于Servlet的Scala Web框架,它允许开发者快速构建高性能的RESTful web服务。这个压缩包"scalatra-scalatest_2.10-2.0.4.zip"包含了Scalatra库的特定版本,适用于Scala 2.10,并集成了Scala...
Scalatra的特点是它能够快速地开发微服务,因为它的灵感来自于Sinatra,一个Ruby界的轻量级Web框架。 ScalaTest是Scala社区广泛使用的单元测试和集成测试框架,它提供了一套强大的匹配器和协作模式,使得测试代码...
Scalatra是一个类似于的微型Web框架。 例 import org . scalatra . _ class ScalatraExample extends ScalatraServlet { get( " / " ) { < h1> Hello , world ! } } 文献资料 如果您只是刚入门,请参阅我们网站...
xitrum 是一个 Scala 的 Web 框架,基于 Netty 开发。结构如下图所示: ----------------- | Your app | ----------------- | Xitrum | ; Other instances| ------------- || | Action/View | || -----------...
Scalatra是一个轻量级、基于Servlet的Scala web框架,它深受Sinatra(Ruby语言的微框架)启发,为开发者提供了构建RESTful API和服务的强大工具。Scalatra-specs则专门用于测试Scalatra应用的正确性和行为一致性,...
Scalatra是一个轻量级的Scala Web框架,而Swagger则是一个用于API文档化和测试的工具。在这个"scalatra-activate-swagger-demo"项目中,我们将探讨如何结合这两个工具来创建一个具有自动文档化的RESTful API。 ...
Scalatra是一个灵感来源于Sinatra的快速、简洁且高效的Web框架,而Spring则是Java生态中的核心企业级框架,提供依赖注入、事务管理、AOP(面向切面编程)等服务。这个特定的版本(2.4.0.M1)是Scalatra与Spring的一...
【标题】"todomvc-scalatra"是一个使用Scala编程语言和Scalatra框架构建的简单TodoMVC应用程序。TodoMVC是一个跨平台的项目,旨在为各种前端和后端技术提供一个统一的、简单的待办事项管理应用的实现,以便开发者...
Scalatra in Action English | ISBN: 1617291293 | 2016 Scalatra in Action covers the Scalatra framework in its entirety, starting with concepts such as request routing, input handling, actions, and ...
Scalatra是一个轻量级的Scala Web框架,它基于Servlet API构建,提供了类似于Sinatra的简洁语法。在"scalatra-auth"项目中,我们看到的是一个包含身份验证功能的Scalatra应用程序示例。这个项目旨在帮助开发者了解...
利用 Mina 可以高效地完成以下任务: <br>TCP/IP 和 UDP/IP 通讯 串口通讯 VM 间的管道通讯 SSL/TLS JXM 集成 IoC 容器集成( Spring 、 Pico 等) 状态机 <br>据官方评测, APR 的...
模板,用于快速启动和运行 Scalatra Web 服务。 使用这个模板 版本0.13.13或更高版本 跑步: $ sbt new scalatra/scalatra.g8 $ cd $ sbt > jetty:start 在浏览器中打开 。 修改此模板 将 GitHub 上的到您的帐户...
这包含了为了集成 Spark 和 Scalatra 而需要改进的所有版本内容。 这是定义调用 Spark 作业的 JSON REST API 的部分。 这会使用 jQuery 调用 API 并将结果打印到控制台。 另请参阅 由 Curran Kelleher 2015 年 2...
面向Scala的对象化Objectify是一个轻量级的Web框架,可通过提供策略管理和依赖项注入来帮助您构建应用程序。 这是我在Scala见面会上快速介绍的内容,它是关于所有内容的想法:Scala见面会 注意:当前唯一随附的...