Webx学习笔记(四)Webx Turbine

Webx Turbine建立在Webx Framework的基础上,实现了页面渲染、布局、数据验证、数据提交等一系列工作。
Webx Turbine所遵循下面的设计理念包括:
页面驱动
约定胜于配置

页面布局:

Screen,代表页面的主体。
Layout,代表页面的布局。
Control,代表嵌在screen和layout中的页面片段

1.webx设计理念:

页面驱动:
         在程序员介入以前,让界面设计师可以直接创建模板,并展示模板的效果。页面驱动的反面,是程序驱动,或者是Action驱动 —— 这是多数WEB框架的模式。

页面驱动提高了开发的效率,也使界面设计师在早期可以利用框架所提供的工具,做一些页面跳转、简单的表单验证、字符串操作等工作。这些工具是通过Webx Turbine中的一个服务来完成的:pull tools。

约定胜于配置:

“约定”即规则。规则是预先定义的,工程师只需要按着规则来做事,就不需要额外的“配置”。对比其它一些框架 —— 往往每增加一个页面,都需要在配置文件中增加若干行内容。Webx Turbine的规则主要是指一系列映射规则。

Webx Turbine映射规则

映射规则 说明
将URL映射成target target是一个抽象的概念,指明当前请求要完成的任务。Target由pipeline来解释,它可能被解释成模板名,也可能被解释成别的东西。
将target转换成模板名 模板用来展现页面的内容。Velocity、Freemarker、JSP都可以作为模板的格式,但在Webx建议使用velocity模板。
将target转换成layout布局 你可以为一组页面选择相同的布局(菜单、导航栏、版权信息等),为另一组页面选择另一种布局。
将target转换成module 在Webx Turbine中,module是指screen、action、control等,大致相当于其它框架中的action或者controller。

工程师只需要根据上述规则,将模板放在指定的目录、按照预定的方式命名module(也就是screen、action、control等),就不再需要额外的配置。

2 页面布局

Webx Turbine的页面,由以下几个部分组成:

图 4.2. Webx Turbine页面的构成

其中:

  • Screen,代表页面的主体。
  • Layout,代表页面的布局。
  • Control,代表嵌在screen和layout中的页面片段。

3. 处理页面的基本流程

Webx Turbine的处理流程被定义在pipeline中。Webx Framework没有规定Pipeline的内容,但Webx Turbine却定义了一系列valves。下面是一个Webx Turbine推荐的pipeline配置:

Webx Turbine推荐的pipeline配置 - pipeline.xml

<services:pipeline xmlns="http://www.alibaba.com/schema/services/pipeline/valves">

    <!-- 初始化turbine rundata,并在pipelineContext中设置可能会用到的对象(如rundata、utils),以便valve取得。 -->
    <prepareForTurbine />

    <!-- 设置日志系统的上下文,支持把当前请求的详情打印在日志中。 -->
    <setLoggingContext />

    <!-- 分析URL,取得target。 -->
    <analyzeURL homepage="homepage" />

    <!-- 检查csrf token,防止csrf攻击和重复提交。假如request和session中的token不匹配,则出错,或显示expired页面。 -->
    <checkCsrfToken />

    <loop>
        <choose>
            <when>
                <!-- 执行带模板的screen,默认有layout。 -->
                <pl-conditions:target-extension-condition extension="null, vm, jsp" />
                <performAction />
                <performTemplateScreen />
                <renderTemplate />
            </when>
            <when>
                <!-- 执行不带模板的screen,默认无layout。 -->
                <pl-conditions:target-extension-condition extension="do" />
                <performAction />
                <performScreen />
            </when>
            <otherwise>
                <!-- 将控制交还给servlet engine。 -->
                <exit />
            </otherwise>
        </choose>

        <!-- 假如rundata.setRedirectTarget()被设置,则循环,否则退出循环。 -->
        <breakUnlessTargetRedirected />
    </loop>

</services:pipeline>

 

假设用户以URL:http://localhost:8081/来访问Webx应用。域名和端口不重要,取决于应用服务器的配置,这里假设为localhost:8081。Webx Framework的处理流程,从WebxFrameworkFilter接收请求,并且一路顺利到达pipeline。然后Pipeline开始依次执行它的valves。(下面的描述略过一些相对次要的步骤。)

  1. <analyzeURL> - 分析URL

    分析URL的目的是取得target。由于用户访问的URL中并没有提供path信息,通常被理解为:用户想要访问“主页”。AnalyzeURL valve提供了一个可选的参数“homepage”,即是在这种情况下起作用 —— http://localhost:8081/对应的target为“homepage”。

    需要注意的是,target不代表模板名,也不代表类名。Target只是一个抽象的概念 —— 当前页面需要达成的目标。Target可能被后续的valves解释成模板名、类名或者其它东西。

  2. 进入<choose> - 多重分支

    很明显,“homepage”满足了第一个<when>所附带的条件:<target-extension-condition extension="null, vm, jsp">,意思是target的后缀不存在(null)或为“jsp”或为“vm”。

  3. <performAction> - 执行action

    和其它框架中的action概念不同,在Webx Turbine中,action是用来处理用户提交的表单的。

    因为本次请求未提供action参数,所以跳过该步骤。

  4. <performTemplateScreen> - 查找并执行screen。

    这里要用到一个规则:target映射成screen module类名的规则。

    假设target为xxx/yyy/zzz,那么Webx Turbine会依次查找下面的screen模块:

    • screen.xxx.yyy.Zzz
    • screen.xxx.yyy.Default
    • screen.xxx.Default
    • screen.Default

    本次请求的target为homepage,因此它会尝试查找screen.Homepagescreen.Default这两个类。

    如果找到screen类,Webx Turbine就会执行它。Screen类的功能,通常是读取数据库,然后把模板所需要的对象放到context中。

    如果找不到,也没关系 —— 这就是“页面优先”:像homepage这样的主页,通常没有业务逻辑,因此不需要screen类,只需要有模板就可以了。

  5. <renderTemplate> - 渲染模板

    这里用到两个规则:target映射成screen template,以及target映射成layout template。

    假设target为xxx/yyy/zzz,那么Webx Turbine会查找下面的screen模板:/templates/screen/xxx/yyy/zzz。Screen模板如果未找到,就会报404 Not Found错误。 找到screen模板以后,Webx Turbine还会试着查找下面的layout模板:

    • /templates/layout/xxx/yyy/zzz
    • /templates/layout/xxx/yyy/default
    • /templates/layout/xxx/default
    • /templates/layout/default

    Layout模板如果找不到,就直接渲染screen模板;如果存在,则把渲染screen模板后的结果,嵌入到layout模板中。

    Layout模板和screen模板中,都可以调用control。每个页面只有一个screen,却可以有任意多个controls。

  6. <breakUnlessTargetRedirected> - 内部重定向

    在screen和action中,可以进行“内部重定向”。内部重定向实质上就是由<breakUnlessTargetRedirected>实施的 —— 如果没有重定向标记,就退出;否则循环到<loop>标签。

    和外部重定向不同,外部重定向是向浏览器返回一个302303 response,其中包含Location header,浏览器看到这样的response以后,就会发出第二个请求。而内部重定向发生在pipeline内部,浏览器并不了解内部重定向。

4 依赖注入

Spring原生注入手段

依赖注入是Spring的重要特性,Webx既然建立在Spring基础上,支持Spring原有的依赖注入手段,例如,可以在Screen/control/action module类中这样写:

通过@Autowired annotation注入(UserManager是在spring context中配置的bean)

public class LoginAction {
    @Autowired
    private UserManager userManager;
    ...
}

在使用Spring原生注入手段时,需要注意beans的scope。你只能注入相同scope或较大的scope中的bean。例如,screen/action/control的scope为singleton,因此用@Autowired注入时,只能注入singleton的对象,不能注入诸如request、session等较小的scope对象。

注入request、response和session对象

在Webx Framework中,你可以这样做:

注入request、response和session对象

public class LoginAction {
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private HttpSession session;
    ...
}

  虽说不能把request scope的对象,注入到singleton scope的对象中。但在Webx中,可以将HttpServletRequestHttpServletResponseHttpSession对象注入到singleton对象中,原因是<request-contexts>对这几个常用对象进行了特殊处理,将它们转化成了singleton对象。

参数注入

有一些对象,是无法通过Spring的bean来注入的,例如:用户提交的参数、表单等。好在Webx Turbine提供了一种可扩展的机制(DataResolver service),通过它,我们可以在screen/control/action的方法中注入任意对象。

参数注入

功能 代码示例 适用于module类型
注入一个query参数
void doGetInt(@Param("aaa") int i)
screen、 action、 control
将query参数注入bean properties
void doSetData(@Params MyData data) 
screen、 action、 control
注入框架对象
void doGetNavigator(Navigator nav)
screen、 action
void doGetContext(Context context) 
screen、 action、 control
void execute(ControlParameters params) 
control
注入context和control参数
void execute(@ContextValue("myvalue") int value) 
screen、 action、 control
注入表单对象
void doGetGroup(@FormGroup("myGroup1") Group group) 
action
void doGetGroups(@FormGroups("myGroup1") Group[] groups) 
action
将表单值注入bean properties
void doGetGroupsBeans(@FormGroups("myGroup1") MyData[] data) 
action

5. 定制Webx Turbine

通过改进pipeline中的valves改变webx turbine的行为。

最常见的一种需求,是要对页面进行授权 —— 只有符合条件的用户才能访问相应的页面。在pipeline中,很容易添加这样的逻辑:

改进pipeline,增加页面授权功能 - pipeline.xml,插入用于验证权限的valve。

<services:pipeline xmlns="http://www.alibaba.com/schema/services/pipeline/valves">
    <prepareForTurbine />
    <setLoggingContext />
    <analyzeURL homepage="homepage" />
    <checkCsrfToken />
    <valve class="com.mycompany.auth.PageAuthorizationValve" />
    ...
</services:pipeline>

   甚至可以重写整个pipeline,以实现另一种风格的WEB框架。 

Webx Turbine建立在pipeline的基础上,基于页面驱动和约定胜于配置的理念,定义了一组处理页面的流程。Webx Turbine的灵活性在于,你可以轻易定制pipeline,以改变它的任何一个方面。

http://blog.csdn.net/hollis_chuang/article/details/41120839

时间: 2024-10-11 12:41:47

Webx学习笔记(四)Webx Turbine的相关文章

Webx学习笔记(三)Webx Framework

Webx Framework的任务 系统初始化 响应请求 初始化Spring容器 增强request/response/session的功能 初始化日志系统 提供pipeline流程处理机制   异常处理   开发模式 1 Webx的初始化 //初始化Spring容器 - /WEB-INF/web.xml <?xml version="1.0" encoding="UTF-8"?> <web-app version="2.4"

webx学习笔记

Webx学习笔记周建旭 2014-08-01 Webx工作流程 图 3.2. Webx Framework如何响应请求 当Webx Framework接收到一个来自WEB的请求以后,实际上它主要做了两件事: 1. 首先,它会增强request.response.session的功能,并把它们打包成更易使用 的RequestContext对象. #macro (registerMessage $field) #if (!$field.valid) $field.message #end #end

Caliburn.Micro学习笔记(四)----IHandle&lt;T&gt;实现多语言功能

Caliburn.Micro学习笔记(四)----IHandle<T>实现多语言功能 说一下IHandle<T>实现多语言功能 因为Caliburn.Micro是基于MvvM的UI与codebehind分离, binding可以是双向的所以我们想动态的实现多语言切换很是方便今天我做一个小demo给大家提供一个思路 先看一下效果 点击英文  变成英文状态点chinese就会变成中文                          源码的下载地址在文章的最下边 多语言用的是资源文件建

代码管理工具 --- git的学习笔记四《重新整理git(1)》

1.创建版本库 mkdir  创建目录 cd  地址,到该地址下 pwd 显示当前目录 1.创建目录 $ mkdir startGit $ cd startGit $ pwd 显示当前目录 或者cd到桌面,然后再创建目录 2.初始化版本库 $ git init 初始化仓库 提示信息:Initialized empty Git repository in /Users/xingzai/Desktop/startGit/.git/ 建立一个空的git仓库在/Users/xingzai/Desktop

Linux学习笔记四:Linux的文件搜索命令

1.文件搜索命令  which 语法:which [命令名称] 范例:$which ls  列出ls命令所在目录 [[email protected] ~]$ which ls alias ls='ls --color=auto' /bin/ls 另外一个命令:whereis [名称名称],也可以列出命令所在目录. [[email protected] ~]$ whereis ls ls: /bin/ls /usr/share/man/man1/ls.1.gz /usr/share/man/ma

小猪的数据结构学习笔记(四)

小猪的数据结构学习笔记(四) 线性表之静态链表 --转载请注明出处:coder-pig 本章引言: 在二,三中中我们分别学习了顺序表中的线性表与单链表,线性表有点类似于 我们前面所学的数组,而单链表使用的最多的是指针,这里问个简单的问题, 如果是在以前没有指针的话,前辈先人们怎么实现单链表呢?大家思考下! 没有指针,那么用什么来代替呢?前辈先人们非常机智,想出了使用下标+游标的方式 来实现单链表的效果!也就是今天要讲的--静态链表! 当然你也可以直接跳过本章,因为有了单链表就没有必要用静态链表了

Swift学习笔记四:数组和字典

最近一个月都在专心做unity3d的斗地主游戏,从早到晚,最后总算是搞出来了,其中的心酸只有自己知道.最近才有功夫闲下来,还是学习学习之前的老本行--asp.net,现在用.net做项目流行MVC,而不是之前的三层,既然技术在更新,只能不断学习,以适应新的技术潮流! 创建MVC工程 1.打开Visual studio2012,新建MVC4工程 2.选择工程属性,创建MVC工程 3.生成工程的目录 App_Start:启动文件的配置信息,包括很重要的RouteConfig路由注册信息 Conten

NLTK学习笔记(四):自然语言处理的一些算法研究

自然语言处理中算法设计有两大部分:分而治之 和 转化 思想.一个是将大问题简化为小问题,另一个是将问题抽象化,向向已知转化.前者的例子:归并排序:后者的例子:判断相邻元素是否相同(与排序). 这次总结的自然语言中常用的一些基本算法,算是入个门了. 递归 使用递归速度上会受影响,但是便于理解算法深层嵌套对象.而一些函数式编程语言会将尾递归优化为迭代. 如果要计算n个词有多少种组合方式?按照阶乘定义:n! = n*(n-1)*...*1 def func(wordlist): length = le

Android学习笔记四:添加Source

问题描述 Source not foundThe JAR file D:\.....\sdk\platforms\android-20\android.jar has no source attachment. 问题原因及解决办法 1. 使用SDK Manager下载最新版本的Sources for Android SDK 一般文件下载目录默认在SDK下的sources文件中即 \adt-bundle-windows-x86_64-20130522\sdk\sources\android-20