zoukankan      html  css  js  c++  java
  • Xitrum学习笔记03

    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 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方法,把方法的结果返回给浏览器。如果当前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]() //将AppAction.jade中的内容作为页面内容的模板
    }

    src/main/scalate/mypackage/AppAction.jade

    !!! 5
    html
      head
        != antiCsrfMeta
        != xitrumCss
        != jsDefaults
        title Welcome to Xitrum
      body
        != renderedView  -#如果没有这一句,使用这个模板的其他View的内容不会呈现
        != 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")

    此示例验证成功,AppAction.jade中的body需要含有!=renderedView

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

    返回其他action的View

    使用respondView[ClassName]()和redirectTo[ClassName]()

    示例:

    package mypackage
    import xitrum.Action
    import xitrum.annotation.{GET, POST}
    @GET("login")
    class LoginFormAction extends Action {
      def execute() {
        // Respond scr/main/scalate/mypackage/LoginFormAction.jade
        respondView()
      }
    }
    @POST("login")
    class DoLoginAction extends Action {
      def execute() {
        val authenticated = ...
        if (authenticated)
          redirectTo[HomeAction]()  // 定向到HomeAction的View
        else
           // Reuse the view of LoginFormAction
           respondView[LoginFormAction]()  //定向到LoginForAction的View
        }
    }

    redirectTo和respondView的区别:

    redirectTo:不需要定向到的Action提供相应的模板;默认HttpResponseStatus是302

    respondView:需要定向到的Action提供相应的模板;HttpResponseStatus是200

    也可以从一个Action,定向到多个View

    package mypackage
    import xitrum.Action
    import xitrum.annotation.GET
    // These are non-routed actions, for mapping to view template files:
    // scr/main/scalate/mypackage/HomeAction_NormalUser.jade
    // scr/main/scalate/mypackage/HomeAction_Moderator.jade
    // scr/main/scalate/mypackage/HomeAction_Admin.jade
    trait HomeAction_NormalUser extends Action
    trait HomeAction_Moderator extends Action
    trait HomeAction_Admin extends Action
    @GET("")
    class HomeAction extends Action {
      def execute() {
        val userType = ...
        userType match {
          case NormalUser => respondView[HomeAction_NormalUser]() 
          case Moderator => respondView[HomeAction_Moderator]()
          case Admin => respondView[HomeAction_Admin]()
        }
      }
    }

    使用respondView[HomeAction_NormalUser]()这样的写法是 类型安全的 写法,也可以使用String参数把scalate的View的位置传给respondView方法

    respondView("mypackage/HomeAction_NormalUser")
    respondView("mypackage/HomeAction_Moderator")
    respondView("mypackage/HomeAction_Admin")

    Component

    Component是在各个View中复用的组件,和Action有些类似

    • Component没有routes(@GET("")括号中的内容就是route),因此不需要使用execute方法
    • 因为Component只是提交一个View的片段(fragment),而不是发出整个的响应内容,所以在Component要调用renderXXX来代替respondXXX
    • 一个Component可以没有、有一个 或 有多个关联的View模板

    示例:

    package mypackage
    import xitrum.{FutureAction, Component}
    import xitrum.annotation.GET
    class CompoWithView extends Component {
      def render() = {
        // Render associated view template, e.g. CompoWithView.jade
        // Note that this is renderView, not respondView!
        renderView()
      }
    }
    
    class CompoWithoutView extends Component {
       def render() = {
         "Hello World"
       }
    }
    
    @GET("foo/bar")
    class MyAction extends FutureAction {
       def execute() {
         respondView()
      }
    }

    MyAction.jade:

    - import mypackage._
    != newComponent[CompoWithView]().render()
    != newComponent[CompoWithoutView]().render()
  • 相关阅读:
    LeetCode1051. 高度检查器 Java
    LeetCode 面试题 16.04. 井字游戏 Java
    WPF 显示3D密集场景,堆场管理系统
    WPF 饼状图,柱形图,折线图 (3 饼状图)
    WPF 饼状图,柱形图,折线图 (2 折线图)
    WPF 饼状图,柱形图,折线图 (1 柱形图)
    wpf 实现控件拖拽(仿windows 桌面图标拖拽)
    设计模式-控制反转
    Socket 网络编程和IO模型
    wpf 滚动文字 跑马灯
  • 原文地址:https://www.cnblogs.com/sunspeedzy/p/6841353.html
Copyright © 2011-2022 走看看