Webx3学习笔记(2)——基本流程

Webx3项目是运行在jetty/tomcat这种Web应用容器中的,Web应用的模式都是请求-响应的。一个请求通过浏览器发出,封装为HTTP报文到达服务端,被容器接受到,封装为HttpRequest和HttpResponse等,然后进入Webx3的领域,通过Webx3的一套Pipeline机制到达指定的后台,调用Java类获取数据或处理,渲染Velocity模板并返回到客户端进行显示。简单示意图如下:

pipeline:

下面通过分析Webx3学习笔记(1)——Hello, World!中生成的源码来理解Webx3的基本流程:

以http://localhost:8081/?home 这个页面作为起点吧,通过观察源码可知这个页面是结合了app1/templates/layout/default.vm和app1/templates/screen/index.vm两个模板进行渲染出来的(怎么找到这两个页面的我暂时也不清楚)。这个页面就是一系列简单demo的集合,下面挑有代表性的几个进行分析:

无模板Screen

url: http://localhost:8081/simple/say_hi.do

先看一下pipeline.xml中比较重要的loop部分,除了作者本身的注释,也加上了我自己的理解:

帮助


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

<pl-valves:loop>

<pl-valves:choose>

<when>

<!-- 执行带模板的screen,默认有layout。 -->

<pl-conditions:target-extension-condition extension="null" />

  <!-- <strong>会去查找action包下面指定类的指定方法</strong> -->

  <pl-valves:performAction />

  <!-- <strong>会去模块的screen包下面寻找同名的Screen类</strong>-->

  <pl-valves:performTemplateScreen />

  <!-- <strong>会去app1/templates/screen下寻找同名的vm模板,然后再找app1/templates/layout下同名的layout模板,最后把layout和screen模板拼起来进行渲染并返回,要是实在找不到layout,就只渲染screen。</strong>

-->

  <pl-valves:renderTemplate />

</when>

<when>

<!-- 执行不带模板的screen,无layout。 -->

<pl-conditions:target-extension-condition extension="do" />

  <!-- 同上 -->

  <pl-valves:performAction />

  <!-- <strong>基本同上,不过这个步骤是必须的,无法跳过。而且这种Screen类是有输出的,类似Servlet</strong> -->

  <pl-valves:performScreen />

</when>

<when>

<!-- 创建JSON,无模板,无layout。 -->

  <pl-conditions:target-extension-condition extension="json" />

  <pl-valves:performScreen />

  <pl-valves:renderResultAsJson />

</when>

<otherwise>

<!-- 将控制交还给servlet engine。 -->

<pl-valves:exit />

</otherwise>

</pl-valves:choose>

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

<pl-valves:breakUnlessTargetRedirected />

</pl-valves:loop>

本例中请求的后缀是.do,所以会执行:

帮助


1

2

3

4

5

<when>

<pl-conditions:target-extension-condition extension="do" />

<pl-valves:performAction />

<pl-valves:performScreen />

</when>

performAction是表单提交才会执行的流程,所以这里直接略过,执行到了performScreen,因为target为simple/say_hi.do,所以该方法去寻找app1.module.screen.simple下寻找同名Java类,而且有一个命名转换规则:say_hi->SayHi。于是我们就找到了SayHi.java,并调用其execute()方法。

帮助


1

2

3

4

5

6

7

8

9

10

11

public class SayHi {

@Autowired

private HttpServletResponse response;

public void execute() throws Exception {

// 设置content type,但不需要设置charset。框架会设置正确的charset。

response.setContentType("text/plain");

// 如同servlet一样:取得输出流。

PrintWriter out = response.getWriter();

out.println("Hi there, how are you doing today?");

}

}

【注意对于第7个例子,say_hello_1.do中没有找到execute()方法,就默认去找了doPerform(),say_hello_1/chinese.do,则会去调用其doChinese()方法。这是种不太常用的方式。】

有模板Screen+表单处理

url:http://localhost:8081/form/register.htm

url后缀名为.htm,会被转换为无后缀的形式,进行如下处理流程:

帮助


1

2

3

<pl-valves:performAction />

<pl-valves:performTemplateScreen />

<pl-valves:renderTemplate />

这也不是一个表单请求,所以略过performAction,执行performTemplateScreen ,去app1.module.screen.form包下寻找Register.Java,并没有找到,但是也没关系【performTemplateScreen 情况下,Screen的Java类并不是必须的】,继续执行renderTemplate,去app1/templates/screen/form/下寻找register.vm,这次找到了,再结合app1/templates/layout/default.vm进行渲染,default.vm就是一个html骨架,主要使用register.vm进行填充。

register.vm:

帮助


1

2

3

4

5

6

7

8

9

10

11

12

13

14

$page.setTitle("Register")

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

 $csrfToken.hiddenField

 <input type="hidden" name="action" value="register_action"/>

 #set ($group = $form.register.defaultInstance)

 <p>Hello, what‘s your name?</p>

 #if (!$group.name.valid)

   <p>$group.name.message</p>

 #end

 <p>

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

   <input type="submit" name="event_submit_do_register"/>

 </p>

</form>

这样就在前端看到了这样的界面:

其中有很多细节值得注意,让我们来关注一下register.vm:

表单的主体部分:

帮助


1

2

3

4

5

6

7

8

</pre>

<pre>#set ($group = $form.register.defaultInstance)</pre>

<pre><p>Hello, what‘s your name?</p></pre>

<pre>#if (!$group.name.valid)

 <p>$group.name.message</p>

 #end

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

<pre>

$form.register是在WEB-INF/app1/form.xml里定义的:

帮助


1

2

3

4

5

6

7

8

9

</pre>

<pre><group name="register" extends="csrfCheck">

 <field name="name" displayName="你的名字">

 <fm-validators:required-validator>

 <message>必须填写 ${displayName}</message>

 </fm-validators:required-validator>

 </field>

 </group></pre>

<pre>

这个名为register的FormGroup有一个属性名为name,该属性还有一个erquired-validator,意思就是必填项。所以在表单内容填写完毕后就会把值付给register的对应属性传到action那里进行处理。

然后看action部分,如果我们把<from action=”…”>中的action属性给删除掉,按理说提交表单时就会报错,可是并没有发生这样的情况,原来Webx3中的表单action是在这里进行配置的:

帮助


1

2

3

4

5

6

</pre>

<pre>$csrfToken.hiddenField

 <input type="hidden" name="action" value="<strong>register_action</strong>"/>

 ……

 <input type="submit" name="event_submit_<strong>do_register</strong>"/></pre>

<pre>

加粗部分共同决定了这个表单提交时会去找app1.module.action包下面的RegisterAction.doregister()方法。让我们去看看这个方法:

帮助


1

2

3

4

5

6

</pre>

<pre>public void doRegister(@FormGroup("register") Visitor visitor, Navigator nav) {

 String name = visitor.getName();</pre>

<pre>nav.redirectTo("app1Link").withTarget("form/welcome").withParameter("name", name);</pre>

<pre>}</pre>

<pre>

@FormGroup就是刚刚说过的,这里会读取其属性并注入到Visitor中。Navigator是个内置的类,直接用就行了。
这里在接收到表单请求后会把应用重定向到form/welcome去,同时带一个参数name,就是刚刚表单中读取的值。

然后form/welcome会走同样的流程:

帮助


1

2

3

4

<pl-valves:performAction />

 <pl-valves:performTemplateScreen />

 <pl-valves:renderTemplate /></pre>

<pre>

action略过,performTemplateScreen会找到app1.module.screen.form.Welcome.java:

帮助


1

2

3

4

5

</pre>

<pre>public void execute(@Param("name") String name, Context context) {

 context.put("name", name);

 }</pre>

<pre>

@Param(“name”) String name 等价于String name = HttpRequest.getParameter(“name”); 这样写能省几行代码。
这个类的作用仅仅是把request里的name参数写进Velocity的context里面。

然后renderTemplate会找到app1/template/screen/form/welcome.vm:

帮助


1

2

3

4

</pre>

<pre>$page.setTitle("Welcome, $name")

 <p>Welcome, $name!</p></pre>

<pre>

同样是结合layout渲染输出。

最终展示的界面为:

至此一个表单的历程已经全部走完。

时间: 2024-10-05 04:55:43

Webx3学习笔记(2)——基本流程的相关文章

HTML5独家分享:原生JavaScript学习笔记2——程序流程控制

当当当当 .....楼主又来了!新一期的JS学习笔记2--程序流程控制更新了! 当当当当 .....楼主又来了!新一期的JS学习笔记2--程序流程控制更新了! 想一键获取全部JS学习笔记的可以给楼主留言哦! js中的程序控制语句 常见的程序有三种执行结构: 1. 顺序结构 2. 分支结构 3. 循环结构 顺序结构:程序从第一行开始执行,按顺序执行到最后一行 分支结构:就像一条岔路口,必须选择且只能选择其中一条道路继续走下去,不能同时执行两个分支里的代码. 我们可以使用如下三种方式来实现程序的分支

【疯狂Java讲义学习笔记】【流程控制与数组】

[学习笔记]1.switch语句后的expression表达式的数据类型只能是byte.short.char.int四个整数类型.String(Java 7后才支持)和枚举类型. 2.数组的长度不可变,定义数组时候不能指定数组的长度.为数组分配空间的时候一定要进行初始化,数组初始化的方法有两种,第一种是静态初始化,在数组中直接为每个数组元素赋上初值,另一种是动态初始化,在初始化的时候指定数组的长度,由系统来为每个元素指定初值.注意的是两种初始化不能够同时使用,即既指定数组的长度,同时又为每个元素

Shell 脚本学习笔记八:流程控制

一. if else      /// 如果else分支没有语句执行,就不要写这个else 1.if 语句 if condition then command1 command2 command3 ... fi /// 写成一行: if [ $(ps -ef | grep -c "ssh") -gt 1 ]; then echo "true"; fi 2.if else if condition then command1 command2 ... else com

redis学习笔记——命令执行流程

基础知识部分 如果需要掌握Redis的整个命令的执行过程,那么必须掌握一些基本的概念!否则根本看不懂,下面我就一些在我看来必备的基础知识进行总结,希望能为后面命令的整个执行过程做铺垫. 事件 Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件: 文件事件(file event):Redis服务器通过套接字与客户端(或者其他Redis服务器)进行连接,而文件事件就是服务器对套接字操作的抽象.服务器与客户端(或者其他服务器)的通信会产生相应的文件事件,而服务器则通过监听并处理这些事件来完

python学习笔记二:流程控制

一.if else: #!/usr/bin/python x = int(raw_input('please input:')) if x >= 90: if x >= 95: print 'a+' else: print 'a' elif x >= 80: if x >= 85: print 'b+' else: print 'b' elif x >= 70: if x >= 75: print 'c+' else: print 'c' else: if x >

[原创]java WEB学习笔记70:Struts2 学习之路-- struts2拦截器源码分析,运行流程

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

Dynamic CRM 2013学习笔记(四十三)流程6 - 自定义流程活动

当我们在流程里添加步骤时,有一些默认的步骤,像创建.更新.发邮件等,但如果你想加一个里面没有的步骤,比如发SMS消息,或者调用一个外部的web service,怎么办?这时就只能自定义一个流程活动了.下面将详细介绍如何创建一个自定义的流程活动.   1. 打开vs2012,新建一个项目:   需要引用CRM 的二个dll :  Microsoft.Xrm.Sdk;  Microsoft.Xrm.Sdk.Workflow;   2. 删除默认的 Activity1. xaml ,新建一个类: us

Dynamic CRM 2013学习笔记(三十八)流程1 - 操作(action)开发与配置详解

CRM 2013 里流程有4个类别:操作(action).业务流程(business process flow).对话(dialog)和工作流(workflow).它们都是从 setting –> Process 进入,然后点击New按钮来创建: 这篇主要介绍操作:什么是操作.什么时候使用操作.如何创建以及如何调用 一.什么是操作 操作是CRM 2013 新增加的一个功能,用来扩展系统的标准功能.业务人员可以用它来实现业务逻辑,然后开发人员可以在系统事件里(比如update,create)来使用

Dynamic CRM 2013学习笔记(四十二)流程5 - 实时/同步工作流(Workflow)用法图解

实时工作流跟插件一样,也是用事件执行管道来执行,能在pre,post或核心操作中执行.跟插件一样,不能在创建之前和删除之后执行.如果执行过程中有异常发生,会取消并回滚整个操作.实时工作流里所有的活动和子流程都是一个事务,不像异步工作流里,子流程是单独的一个事务.不能使用等待或并行等待条件步骤.如果执行成功,就看不到执行的log.实时工作流能被转到异步工作流,还能再转回实时工作流.下面详细介绍如何创建一个实时工作流.   一.创建实时工作流 1. 打开 Setting > Process, 点击N