webx相关概念与具体处理流程

1.相关概念

        (1)webx中的MVC

                  在webx中control就是action,view和layout、control、screen、template等概念相关。

                  layout指页面布局;control指页头、页脚、左右边栏等呗多个页面共享的页面区域;screen指个性化的页面区域

                       

                   layout、control、screen具体的就用.vm文件来表示,这就是template,查看webapp的app1子目录,可以看到其中包含了templates子目录,之下有layout、control、screen三个子目录,里面包含了一系列的vm文件。

                      

        (2)form表单

                   各个子应用目录下有一个form.xml文件,定义了表单的相关信息。以WEB-INF\app1\form.xml为例,里面定义了app1子应用的相关表单

        

               上图是登录表单,name="login",可以看到其中定义了各表单字段field,包括一些校验器、校验模式和错误提示信息。所有这些都会被相关vm引用,例如webapp\app1\templates\screen\login.vm中通过以下语句引用了login表单:

#set ($group = $form.login.defaultInstance)
               之后就可以通过$group.field_name来引用form.xml中定义的各个字段值了

        (3)action

                   用来处理用户提交的表单。

                   在com\alibaba\webx\tutorial1\app1\module\action目录下有LoginAction.java,其中定义处理login相关请求的方法。在login.vm中有以下代码:

  <input type="hidden" name="action" value="LoginAction"/>
                   这里定义了这个form会提交由LoginAction处理
                   LoginAction包含多个方法,可以处理多个请求,具体调用哪个请求,可以根据按钮的name属性来确定,如login.vm中

<input type="submit" name="event_submit_do_check"/>
                  说明LoginAction的doCheck方法会被调用


2.具体流程

        (1)发出请求

                  首先思考发出请求必须有完整的路径,包括服务器地址、哪个component、target、哪个action响应、action中方法,下面依次对应

                  1)服务器地址、哪个component、target

                        这几个都是通过form中的action来定义的

<form action="$app1Link.setTarget("register.vm")" method="post">

                       表示请求路径为$app1Link/register.vm,其中$app1Link定义在uris.xml中

                       注意:这里如果和地址栏中完全相同的话,可以将action设为空

                  2)哪个action响应

                        通过表单中的隐藏字段来定义

  <input type="hidden" name="action" value="RegisterAction"/>
                       也就是说通过RegisterAction来响应

                 3)action中的哪个方法来响应

                       通过submit按钮的name属性的值来确定,name的格式为:event_submit_+响应函数名称(如果有多个单词则用下划线连接)

<input type="submit" name="event_submit_do_register" value="立即注册!"/>
                      表示通过doRegister方法来响应

        (2)分析请求如何找到处理类

                1)当用户发出请求,会被webx拦截到:WebxFrameworkFilter,然后调用WebxRootController

                      WebRootController对象存在于root context中,是所有子应用共享的。它会创建RequestContext实例,从而增强Request、Response、session功能。

                2)然后WebxController会被调用

                     WebxController对象是由每个子应用独享的,比如petstore中的子应用admin和user,可以有不同的WebxController实现。

                3)然后WebxController调用子应用自己的Pipeline

                      Pipeline也是各个子应用自己配置的。Pipeline中配置了多个valve,依次执行,下面说明几个比较重要的

                     1.<analyzeURL>

                        用来分析url获得target

                       比如url为:http://localhost:8081/user/register.htm,

/user:component path

/register.htm被称为servlet path。

根据默认的映射规则,/register.htm被转换成/register.vm,这个就是target

这个转换被定义在webx-component-and-root.xml中


                     2.<loop>

                        1-当<when>中的条件被满足时,就执行这个<when>的分支,如果所有的<when>都不满足,那么就执行<otherwise>分支

               <when>
                    <pl-conditions:target-extension-condition extension="null, vm, jsp" />
                     ......
                </when>
                         如果target的后缀是空(null),或者vm,或者jsp时,执行这个分支

                <when>
                    <pl-conditions:target-extension-condition extension="do" />
                     ....
                </when>
                         如果target后缀是do,就执行下面的分支
                       2-<performActionValve>

                           就是用来执行action的,实际上是这样写的

<valve class="com.alibaba.turbine.pipeline.PerformActionValve" actionParam="action"/>
                           可以看出是由提交请求的action参数的值来确定要执行的Action的名称

                           例如URL为:http://localhost:8081/user/register.htm?action=RegisterAction,那么就会执行RegisterAction
                      3-<performTemplateScreen>

                           用来执行screen和模板,实际写法为:

<valve class="com.alibaba.turbine.pipeline.PerformScreenTemplateValve"/>
                          假如target为:/xxx/yyy/register.vm,那么valve会:

                          A)依次在本模块screen下查找对应的类,查找顺序为:

                                  screen.xxx.yyy.register

                                  screen.xxx.yyy.Default

                                  screen.xxx.Default

                                  screen.Default

                                如果找到了就执行screen,screen的工嗯呢该,通常是读取数据库,然后把模板需要的对象放入context中;

                                如果找不到也没关系,因为有些页面本来就是静态页面

                          B)执行完screen中对应的类之后,在/templates/screen目录下,找到并绘制/xxx/yyy/register.vm模板,但是还是需要<renderTemplate>来渲染vm

                                所以一般<performTemplateScreen>后面都会有<renderTemplate>

                      4-<renderTemplate>

                           这里需要将vm渲染并将vm放入layout中,所以就需要两个映射关系:target到screen template;target到layout template

                           因为这里是将vm渲染,所以vm必须存在,如果不存在就会报404错误。查找方法同上

                           layout的查找规则为:

                                /templates/layout/xxx/yyy/zzz

                                /templates/layout/xxx/yyy/default

                                /templates/layout/xxx/default

                               /templates/layout/default

                           如果layout模板找到了,就把渲染后的screen模板嵌入到layout模板中;如果没有找到,那么就只渲染screen即可

                      5-<performScreen>

                          执行Screen下面的java类,不去渲染模板

                      注意:<performTemplateScreen>与<performScreen>的区别:

                                前者除了要执行screen中对应的.java还会执行screen中的.vm;后者只会执行screen中对应的.java


        (3)如何传递参数

                1)在Action中

                     方法一:通过类来封装参数(适用于表单参数比较多的情况)

                      1- 通过定义一个类,和表单中的数据来对应

public class LoginObject {
	private String name;
	private String passwd;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPasswd() {
		return passwd;
	}

	public void setPasswd(String passwd) {
		this.passwd = passwd;
	}
}
                   2-在Action的方法中使用注解

	public void doCheck(@FormGroup("login") LoginObject param, Navigator nav) 
                     这样的话,直接使用对象的getter就可以获得表单中的值


                     方法二:通过@Param获得单个参数(适用于表单参数比较少的情况)

                      1- 前台

                          定义好参数的name

            <input type="text" name="userId" value="$!group.userId.value"/>

                      2- 后台

                          使用@Param注解获得


                2)在Screen中

                      还是使用注解

public void execute(@Param("name") String name, Context context) 

        (4)请求转发与重定向

                  1)重定向

                        使用传入的参数Navigator nav

nav.forwardTo("index").withParameter("name", name);
                        由于是内部的重定向,所以forwardTo中的参数直接设置为target就可以了

                  2)请求转发

                        还是使用传入的参数Navigator  nav

nav.redirectTo("app1Link").withTarget("hello").withParameter("name", name);
                        因为是请求转发,所以需要定义完整的地址。

                       app1Link在uris中已经定义了:

       <uri id="server" requestAware="true" />

        <turbine-uri id="app1Link" exposed="true" extends="server">
            <componentPath>/</componentPath>
        </turbine-uri>
                  所以完整的地址就是:域名:端口号/hello

        (5)如何将查询到的数据放到页面上

                   在Screen中使用context.put,将数据放入context中

                   1)单一数据在页面中显示

                         直接使用  : $数据名称

public class Register {
	public void execute(Context context) {
		context.put("name", "xxxx");
	}
}
                       页面中

$name
                  2)List数据显示

                        使用velocity的foreach标签即可

public class Register {
	public void execute(Context context) {
		List<String> list = new ArrayList<String>(5);
		list.add("abc");
		list.add("bbc");
		list.add("cbc");
		list.add("dbc");
		list.add("ebc");
		context.put("myList", list);
	}
}
                      页面中:

#foreach( $elem in $myList)
    $elem</br>
#end

        (6)在Screen中引用control

$control.setTemplate("header.vm")


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值