Xitrum学习笔记03 - Action和View

Action:

Xitrum 提供了3种Action:普通Action, FutureAction 和 ActorAction

它们都是Trait,而不是 Class

1. 普通Action:

当请求到来时,Action实现类直接在Netty的 IO线程上运行,不能用普通Action来执行 消耗很长时间的处理,否则Netty就不能接收新的连接或发出响应到客户端

import xitrum.Action
import xitrum.annotation.GET
@GET("hello")
class HelloAction extends Action {
  def execute() {
    respondText("Hello")
  }
}

2. FutureAction:

扩展了 Action,FutureAction实现类异步运行在和ActorAction相同的线程池上,这个线程池和Netty线程池是分离的

FutureAction实现类的执行context是 xitrum.Config.actorSystem.dispatcher.

trait FutureAction extends Action

import xitrum.FutureAction
import xitrum.annotation.GET
@GET("hello")
class HelloAction extends FutureAction {
  def execute() {
    respondText("hi")
  }
}

3. ActorAction:

trait ActorAction extends Actor with Action

实现类是一个 Akka actor。

当有需求时,一个actor实例被创建。当连接关闭时,或者响应通过 respondText/respondView 等方法被发出时,actor会被停止。

对于分块的响应,actor会在最后一个块儿的响应发出后才被停止。

actor运行在命名为"xiturm"的Akka actor系统的线程池中。

 1 import scala.concurrent.duration._
 2 import xitrum.ActorAction
 3 import xitrum.annotation.GET
 4 @GET("actor")
 5 class HelloAction extends ActorAction {
 6   def execute() {
 7     // See Akka doc about scheduler
 8     import context.dispatcher
 9     context.system.scheduler.scheduleOnce(3 seconds, self, System.currentTimeMillis())
10     // See Akka doc about "become"
11     context.become {
12       case pastTime =>
13       respondInlineView(s"It‘s $pastTime Unix ms 3s ago.")
14     }
15   }
16 }

响应(Response)方式:

1.  对于action来说,要向客户端发出响应,可以调用如下方法

? respondView: responds view template file, with or without layout
? respondInlineView: responds embedded template (not separate template file), with or without layout
? respondText("hello"): responds a string without layout
? respondHtml("<html>...</html>"): same as above, with content type set to “text/html”
? respondJson(List(1, 2, 3)): converts Scala object to JSON object then responds
? respondJs("myFunction([1, 2, 3])")
? respondJsonP(List(1, 2, 3), "myFunction"): combination of the above two
? respondJsonText("[1, 2, 3]")
? respondJsonPText("[1, 2, 3]", "myFunction")
? respondBinary: responds an array of bytes
? respondFile: sends a file directly from disk, very fast because zero-copy (aka send-file) is used
? respondEventSource("data", "event")

2. 响应返回事先创建好的View模板文件内容

要运用这种方式,每个Action scala文件都要对应一个View jade文件。代码示例如下:

scr/main/scala/mypackage/MyAction.scala:

package mypackage
import xitrum.Action
import xitrum.annotation.GET
@GET("myAction")
class MyAction extends Action {
  def execute() {
    respondView()
  }
  def hello(what: String) = "Hello %s".format(what)
}

scr/main/scalate/mypackage/MyAction.jade:

- import mypackage.MyAction
!!! 5
html
  head
    != antiCsrfMeta
    != xitrumCss  //包含了Xitrum默认的CSS。这个CSS是可以移除的
    != jsDefaults //包含了 jQuery、jQuery验证插件等等内容,要放在<head>标签中
    title Welcome to Xitrum
  body
    a(href={url}) Path to the current action
    p= currentAction.asInstanceOf[MyAction].hello("World") //将currentAction转换为MyAction,并调用其hello方法
    != jsForView  //包含了由jsAddToView标签添加的JavaScript代码,jsForView标签应该放在整个layout的底部

在View模板中,可以使用 xitrum.Action中定义的所有方法,而且也可以使用由Scalate提供的一些utility方法(参考 Scalate doc)

默认的 Scalate 模板类型是 Jade,其他的有 Mustache, Scaml 和 Ssp。在config/xitrum.conf文件中配置默认模板类型.

  # Comment out if you don‘t use template engine.
  template {
    "xitrum.view.Scalate" {
      defaultType = jade  # jade, mustache, scaml, or ssp
    }
  }

也可以在Action实现类调用 respondView时指定模板类型

val options = Map("type" ->"mustache")
respondView(options)

如果需要在View中多次调用Action实现类的的方法的话,只需要将currentAction做一次转换,如:

- val myAction = currentAction.asInstanceOf[MyAction]; import myAction._
p= hello("World")
p= hello("Scala")
p= hello("Xitrum")

Layout

利用respondView或respondInlineView提交一个View时,Xitrum会把View内容表示成一个String,然后把这个String设置给renderedView变量。

Xitrum调用当前Action的layout方法,把方法的结果返回给浏览器。

默认的layout方法只返回 renderedView 本身,可以通过重写layout方法以添加关于view的其他内容。如果重写的layout方法中包含renderedView,它只是作为layout的一部分内容。

layout方法在action的view生成之后才被调用,layout方法返回的内容就是要响应到浏览器中的内容。

可以通过创建一个继承自Action的Trait,并将其相应的View模板文件定义为通用layout。再让其他Action scala实现这个Trait,这样其他Action的页面就会包含这个通用的layout。

示例:

src/main/scala/mypackage/AppAction.scala

package mypackage
import xitrum.Action
trait AppAction extends Action {
  override def layout = renderViewNoLayout[AppAction]()
}

src/main/scalate/mypackage/AppAction.jade

!!! 5
html
  head
    != antiCsrfMeta
    != xitrumCss
    != jsDefaults
    title Welcome to Xitrum
  body
    != renderedView
    != jsForView

src/main/scala/mypackage/MyAction.scala

package mypackage
import xitrum.annotation.GET
@GET("myAction")
class MyAction extends AppAction {
  def execute() {
    respondView()
  }
  def hello(what: String) = "Hello %s".format(what)
}

scr/main/scalate/mypackage/MyAction.jade:

- import mypackage.MyAction
a(href={url}) Path to the current action
p= currentAction.asInstanceOf[MyAction].hello("World")

此示例有待验证

layout不在View模板里的示例(直接写到 Action Scala文件里)

示例1:

import xitrum.Action
import xitrum.view.DocType
trait AppAction extends Action {
  override def layout = DocType.html5(
    <html>
      <head>
         {antiCsrfMeta}
         {xitrumCss}
         {jsDefaults}
         <title>Welcome to Xitrum</title>
       </head>
       <body>
         {renderedView}
         {jsForView}
       </body>
    </html>
  )
}

示例2:

val specialLayout = () =>
   DocType.html5(
     <html>
       <head>
          {antiCsrfMeta}
          {xitrumCss}
          {jsDefaults}
          <title>Welcome to Xitrum</title>
        </head>
        <body>
          {renderedView}
          {jsForView}
        </body>
      </html>
   )
respondView(specialLayout _)

Inline view

import xitrum.Action
import xitrum.annotation.GET

@GET("myAction")
  class MyAction extends Action {
    def execute() {
      val s = "World" // Will be automatically HTML-escaped
      respondInlineView(
         <p>Hello <em>{s}</em>!</p>
      )
    }
  }

Render fragment

有两个Jade View文件:

scr/main/scalate/mypackage/MyAction.jade,scr/main/scalate/mypackage/_MyFragment.jade

如果想提交fragment文件到相同路径下的其他Jade文件里,可以使用

renderFragment[MyAction]("MyFragment")

如果在这种情况下,MyAction是当前action,则上面的代码可以写成 renderFragment("MyFragment")

时间: 2024-10-05 20:55:03

Xitrum学习笔记03 - Action和View的相关文章

Android自定义View学习笔记03

Android自定义View学习笔记03 预备知识 BitMap类 BitMap位图类,其中有一个嵌套类叫Bitmap.Config,内部有四个枚举值.这个类的作用是定义位图存储质量,即存储一个像素的位数,以及是否能显示透明.半透明颜色(Possible bitmap configurations. A bitmap configuration describes how pixels are stored. This affects the quality (color depth) as w

Xitrum学习笔记12 - 范围

一.Request 参数种类 1. 文本参数:名为textParams,类型为 scala.collection.mutable.Map[Sting, Seq[String]] 1)queryParams:URL中 ? 后面的参数,例:http://example.com/blah?x=1&y=2 2)bodyTextParams:在POST请求体里的参数 3)pathParams:嵌入到URL的参数,例:GET("articles/:id/:title") 从1)到3),同名

C++ GUI Qt4学习笔记03

C++ GUI Qt4学习笔记03 qtc++spreadsheet文档工具resources 本章介绍创建Spreadsheet应用程序的主窗口 1.子类化QMainWindow 通过子类化QMainWindow可以创建一个窗口 图形用户界面(GUI)应用程序通常会使用很多的图片,最常见的为应用程序提供图片的方法是使用Qt的资源机制(resource mechanism) 使用Qt资源系统,必须创建一个资源文件,并且在识别该资源文件的.pro文件中添加一行代码. RESOURCES = spr

python学习笔记(03):函数

默认参数值:   只有在行参表末尾的哪些参数可以有默认参数值,即 def func(a, b=5 )#有效的 def func( a=5,b )#无效的 关键参数: #!/usr/bin/python # Filename: func_key.py def func(a, b=5, c=10): print 'a is', a, 'and b is', b, 'and c is', c func(3, 7) func(25, c=24) func(c=50, a=100) #输出: $ pyth

HTTP 学习笔记03

通用信息头 Cache-Control : no-cache(不缓存当前请求) [*] Connection:close(返回当前请求后立即断开)[*] Date:...(HTTP消息产生的时间) Pragma:no-cache (不缓存) [*] Trailer:Date(哪些能放到实体内容后的头字段) Transfer-Encoding:chunked (指定传输编码方式)[*] Upgrade:HTTP/2.0,SHTTP/1.3 (支持的版本) Via:HTTP/1.1 Proxy1,H

mongodb 学习笔记 03 -- 查询表达式

mongodb 学习笔记 03 – 查询表达式 不等于,大于,小于 !=: db.stu.find({name:{$ne:'billvsme'}}) 名字不是'billvsme' > : db.stu.find({age:{$gt:18}}) 年纪大于18 < : db.stu.find({age:{$lt:18}}) 年纪小于18 >=: $gte <=: $lte in/not in/all $in :db.goods.find(stu_id:{$in:[93001,93002

SWIFT学习笔记03

1.断言 let age = -3 assert(age >= 0, "A person's age cannot be less than zero") // 因为 age < 0,所以断言会触发 2.Swift赋值符(=)不返回值,以防止把想要判断相等运算符(==)的地方写成赋值符导致的错误.数值运算符(+,-,*,/,%等)会检测并不允许值溢出. 3.在对负数b求余时,b的符号会被忽略.这意味着 a % b 和 a % -b的结果是相同的,但-a是不一样的. 4.不同

HTML学习笔记03

HTML学习笔记03 一.HTML标题 HTML标题通过<h1>-<h6>等标签进行定义的,<h1>定义最大的标题,<h6>定义最小的标题. 二.HTML水平线 HTML水平线可以用<hr>标签. 三.HTML注释 HTML注释采用设置<!--注释-->进行注释. 四.HTML段落 HTML段落采用<p>标签,还可以使用<br>标签进行换行. 五.文本格式化 <b>定义粗体文本,<big>

【OpenGL 学习笔记03】点画多边形

1.点画多边形 //定义填充多边形的点画模式.mask为32 x 32 的位图指针,1画0不画,使用前必须启用多边形点画功能 void glPloygonStipple(const GLubyte* mask); //绘制一个矩形 void glRectf(GLfloat x1,GLfloat y1,GLfloat x2,GLfloat y2); 2.示例 #include <GL/glut.h> #include <stdlib.h> void display(void) { G