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

本文详细介绍了webx框架的MVC模式、表单处理机制及请求处理流程,包括action与screen的工作原理、参数传递方式、请求转发与重定向的实现方法,并展示了如何在页面上展示查询数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.youkuaiyun.com/cpf2016/article/details/45534527

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表单:

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

        (3)action

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

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

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

[plain]  view plain copy
  1. <input type="submit" name="event_submit_do_check"/>  
                  说明LoginAction的doCheck方法会被调用


2.具体流程

        (1)发出请求

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

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

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

[plain]  view plain copy
  1. <form action="$app1Link.setTarget("register.vm")" method="post">  

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

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

                  2)哪个action响应

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

[plain]  view plain copy
  1. <input type="hidden" name="action" value="RegisterAction"/>  
                       也就是说通过RegisterAction来响应

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

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

[plain]  view plain copy
  1. <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>分支

[html]  view plain copy
  1. <when>  
  2.      <pl-conditions:target-extension-condition extension="null, vm, jsp" />  
  3.       ......  
  4.  </when>  
                         如果target的后缀是空(null),或者vm,或者jsp时,执行这个分支

[html]  view plain copy
  1. <when>  
  2.     <pl-conditions:target-extension-condition extension="do" />  
  3.      ....  
  4. </when>  
                         如果target后缀是do,就执行下面的分支
                       2-<performActionValve>

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

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

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

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

[html]  view plain copy
  1. <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- 通过定义一个类,和表单中的数据来对应

[java]  view plain copy
  1. public class LoginObject {  
  2.     private String name;  
  3.     private String passwd;  
  4.   
  5.     public String getName() {  
  6.         return name;  
  7.     }  
  8.   
  9.     public void setName(String name) {  
  10.         this.name = name;  
  11.     }  
  12.   
  13.     public String getPasswd() {  
  14.         return passwd;  
  15.     }  
  16.   
  17.     public void setPasswd(String passwd) {  
  18.         this.passwd = passwd;  
  19.     }  
  20. }  
                   2-在Action的方法中使用注解

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


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

                      1- 前台

                          定义好参数的name

[html]  view plain copy
  1. <input type="text" name="userId" value="$!group.userId.value"/>  

                      2- 后台

                          使用@Param注解获得


                2)在Screen中

                      还是使用注解

[java]  view plain copy
  1. public void execute(@Param("name") String name, Context context)   

        (4)请求转发与重定向

                  1)重定向

                        使用传入的参数Navigator nav

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

                  2)请求转发

                        还是使用传入的参数Navigator  nav

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

                       app1Link在uris中已经定义了:

[html]  view plain copy
  1. <uri id="server" requestAware="true" />  
  2.   
  3.  <turbine-uri id="app1Link" exposed="true" extends="server">  
  4.      <componentPath>/</componentPath>  
  5.  </turbine-uri>  
                  所以完整的地址就是:域名:端口号/hello

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

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

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

                         直接使用  : $数据名称

[java]  view plain copy
  1. public class Register {  
  2.     public void execute(Context context) {  
  3.         context.put("name""xxxx");  
  4.     }  
  5. }  
                       页面中

[html]  view plain copy
  1. $name  
                  2)List数据显示

                        使用velocity的foreach标签即可

[java]  view plain copy
  1. public class Register {  
  2.     public void execute(Context context) {  
  3.         List<String> list = new ArrayList<String>(5);  
  4.         list.add("abc");  
  5.         list.add("bbc");  
  6.         list.add("cbc");  
  7.         list.add("dbc");  
  8.         list.add("ebc");  
  9.         context.put("myList", list);  
  10.     }  
  11. }  
                      页面中:

[html]  view plain copy
  1. #foreach( $elem in $myList)  
  2.     $elem</br>  
  3. #end  

        (6)在Screen中引用control

[html]  view plain copy
  1. $control.setTemplate("header.vm")  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值