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 {@Autowiredprivate 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渲染输出。
最终展示的界面为:

至此一个表单的历程已经全部走完。
Webx3学习笔记(2)——基本流程的更多相关文章
- 【疯狂Java讲义学习笔记】【流程控制与数组】
[学习笔记]1.switch语句后的expression表达式的数据类型只能是byte.short.char.int四个整数类型.String(Java 7后才支持)和枚举类型. 2.数组的长度不可变 ...
- 吴裕雄--天生自然ShellX学习笔记:Shell 流程控制
和Java.PHP等语言不一样,sh的流程控制不可为空,如(以下为PHP流程控制写法): <?php if (isset($_GET["q"])) { search(q); ...
- redis学习笔记——命令执行流程
基础知识部分 如果需要掌握Redis的整个命令的执行过程,那么必须掌握一些基本的概念!否则根本看不懂,下面我就一些在我看来必备的基础知识进行总结,希望能为后面命令的整个执行过程做铺垫. 事件 Redi ...
- python学习笔记二:流程控制
一.if else: #!/usr/bin/python x = int(raw_input('please input:')) if x >= 90: if x >= 95: print ...
- NDK学习笔记-NDK开发流程
本文主要是说明一下在eclipse下如何对NDK进行配置 配置NDK 虽然现在基本上都使用Android Studio进行Android开发,但一些项目在eclipse中仍有运用,这里讲一讲eclip ...
- NDK学习笔记-JNI开发流程
JNI(Java Native Interface)Java本地化接口,Java调用C/C++,C/C++调用Java的一套API接口 实现步骤 在Java源文件中编写native方法 public ...
- Dynamic CRM 2013学习笔记(三十三)自定义审批流4 - 规则节点 -有分支的流程处理
上次介绍过节点的基本配置<Dynamic CRM 2013学习笔记(三十二)自定义审批流3 - 节点及实体配置>,这次介绍下规则节点,因为有时流程里会有一些分支.合并,这时就要用到规则节点 ...
- Dynamic CRM 2013学习笔记(三十八)流程1 - 操作(action)开发与配置详解
CRM 2013 里流程有4个类别:操作(action).业务流程(business process flow).对话(dialog)和工作流(workflow).它们都是从 setting –> ...
- Dynamic CRM 2013学习笔记(三十九)流程2 - 业务流程(Business Process Flows)用法详解
业务流程(Business Process Flows)是CRM 2013 里一个新的流程,它提供了可视化的流程表现.业务人员创建有效.流线型的业务流程让最终用户知道当前在哪.下一步要做什么,用户可以 ...
随机推荐
- java source map
Chrome 更新后出现了 jquery.min.map 404 (Not Found) 的信息 这个到底是什么东西?查询了一下,得到了以下资料 JQuery 官方解释 摘录一下內容 从 jQuer ...
- bat 常用命令
基础部分:======================================================================一.基础语法: 1.批处理文件是一个". ...
- ural1752 Tree 2
Tree 2 Time limit: 1.0 secondMemory limit: 64 MB Consider a tree consisting of n vertices. A distanc ...
- java类到底是如何加载并初始化的?
Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...
- [iOS Animation]-CALayer 变换
变换 很不幸,没人能告诉你母体是什么,你只能自己体会 -- 骇客帝国 在第四章“可视效果”中,我们研究了一些增强图层和它的内容显示效果的一些技术,在这一章中,我们将要研究可以用来对图层旋转,摆放或者扭 ...
- 使用USBASP给Arduino烧写bootloader教程
源:使用UsbAsp给UNO烧写bootloader ATMEGA16U2.ATMEGA328P固件烧写教程 arduino板由于操作不发导致固件损坏,或者想更新固件怎么办?今天给大家介绍一下如何使用 ...
- Android高斯模糊技术,实现毛玻璃效果(转)
本博客转自郭霖公众号:http://mp.weixin.qq.com/s?__biz=MzA5MzI3NjE2MA==&mid=2650235930&idx=1&sn=e328 ...
- linux命令学习6-dpkg命令
dpkg命令是Debian Linux系统用来安装.创建和管理软件包的实用工具. 1. 语法 dpkg (选项) (参数)2. 选项 -i:安装软件包: -r:删除软件包: -P:删除软件包的同时删除 ...
- LPC1768外部中断与GPIO中断
LPC1768的外部中断严格来说只有四个,分别是EINT0,EINT1,EINT2,EINT3,技术手册上有如下说明 控制这四个外部中断靠以下寄存器 这三个寄存器的0 1 2 3位分别代表中断的0 1 ...
- el5,6,7的ntpdate服务
在el5里没有ntpdate服务 在el6里有ntpdate服务 在el7里有ntpdate服务