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

<form action="" method="post">

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

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

//form.xml中加上<group name="register" extends="csrfTokenCheckGroup">

<p> 用户注册 </p>

<dl>

<dt> 用户名 </dt>

<dd>

<div>

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

</div>

<div class="errorMessage">

#registerMessage ($group.userId)

</div>

</dd>

<dt> 密码 </dt>

<dd>

<div>

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

</div>

<div class="errorMessage">

#registerMessage ($group.password)

</div>

</dd>

<dt> 再输一遍密码 </dt>

<dd>

<div>

<input type="password" name="$group.passwordConfirm.key" value="$!

group.passwordConfirm.value"/>

</div>

<div class="errorMessage">

#registerMessage ($group.passwordConfirm)

</div>

</dd>

</dl>

<p>

<input type="submit" name="event_submit_do_register" value= "立即注册!" />

//这个doRegister 方法写在了要提交的action中

</p>

</form>

HTML form的action值为空,意思是把表单提交给当前页面。

这样,当用户填写表单有错时,应用会停留在当前表单页面,将表单数据连同错误提示一

起显示给用户,要求用户修改。如果表单验证通过,应用必须通过重定向操作来转向下一

个页面。

创建一个register group的实例。其实就是在.vm页面中创建了一个register实例指向group,

不过不用像以前登陆注册那样必须写register类和login类,webx中不需要, 只要用户类即可.

利用新创建的group对象来生成表单字段,包括生成字段的名称$group.field.key,以及

字段的值为$!group.field.value。

定义velocity宏:仅当field验证通过时(即$group.field.valid=true),才显示错误信

息。

对于空白表单和通过验证的字段而言,$group.field.valid为true。

如果验证失败的话,显示验证出错消息。这里通过前面所定义的velocity宏来简化代码。

根据这参数,表单将会被交给UserAccountAction来处理。Action的职责是调用表单验证

过程。假如验证通过,就保存数据,并重定向到下一个页面。

根据这个参数,表单被提交以后,系统会调用当前action(即UserAccountAction)

的doRegister()方法。每个action类中,可以包含多个处理数据的动作,例

如doCreate、doUpdate、doDelete等。

上面的Velocity页面模板演示了怎样利用表单验证服务创建一个帐户注册的HTML表单。关键技

术解释如下:

创建group实例

$form.register.defaultInstance将会对register group创建一个默认的实例。绝大多

数情况下,只需要创建唯一的default instance就足够了。但后面我们会讲到创建多实例的

例子。

所创建的group instance(如register)必须先在规则配置文件(form.xml)中被定义。

9.3.1.3. 创建Java代码(action)

用户提交表单后,由服务器端的Java代码读取并验证用户的数据。

在Webx中,这个功能通常由action来完成。前文已经提到,在HTML表单中,设

置action字段,以及event_submit_do_register提交按钮,就可以让Webx框架调

用UserAccountAction.doRegister()方法。

下面是UserAccountAction类的实现代码:

表单验证服务指南

153

例 9.7. 创建用于处理提交数据的action代码

public class UserAccountAction {

@Autowired

//FormService是webx自带的接口, 你可以看源码

private FormService formService;

public void doRegister(Navigator nav) throws Exception {

Form form = formService.getForm();

if (form.isValid()) {

//获取表单 register 对象的数据, 即 group.field.key的value值

Group group = form.getGroup("register");MyUser user = new MyUser();

group.setProperties(user);//把表单数据装入bean

save(user);

//  跳转到注册成功页面

nav.redirectTo("registerSuccess");

}

}

}

注入form服务。

取得form对象,form对象中包含若干groups。

仅当表单验证成功时,才执行下去。

取得group对象。Group对象的名称必须和配置文件以及模板中的group名称相同。

将group中的数据灌入bean中。

处理完数据以后,利用Webx navigation接口跳转到“注册成功”页面。

例子中的MyUser对象是一个简单的Java Bean:

例 9.8. 被灌入group数据的Java Bean

public static class MyUser {

private String userId;

private String password;

public String getUserId() {

return userId;

}

public void setUserId(String userId) {

this.userId = userId;

}

public String getPassword() {

return password;

}

public void setPassword(String password) {

this.password = password;

}

}

Group.setProperties()方法将fields的值映射到同名的Java Bean properties中。然而这个

对应关系是可以改变的,后文会再次讲到该问题。

Webx的表单验证总结

• 验证表单,如果失败则不执行action,否则执行doRegister方法。

• 取得form和register group对象,并将group中的数据注入到MyUser对象中。

9.3.2. 修改老数据

在前面的例子中,我们利用表单创建了一个新数据 —— 注册新帐户。它是从一个空白表单开始

的,也就是说,在用户填写表单之前,表单是没有内容的,或只包含默认值的。另一种常见情况

是修改老数据。例如“修改帐户资料”。和创建新数据的例子不同,在用户填写表单之前,表单

里已经包含了从数据库中取得的老数据。

在创建新数据的模板和代码中,稍微添加一点东西,就可以实现修改老数据的功能。

9.3.2.1. 用screen来读取数据,在screen类中使用execute方法

/*

通过service层去掉用dao得到数据返回,

注意:为了方便我把当前登陆的用户直接与ThreadLocal绑定, 没有放到session中即通过session.setAttribute(“”, object);来实现, 具体的参见PetstoreUser类

*/

public class UserAccount {

@Autowired

private UserManager userManager;//这是我定义的接口,也是当前项目采用的命名规范

public void execute(Context context) throws Exception {

User user = userManager.getUser(getCurrentUser().getId());

//把所取得的user对象放到context中,就可以在.vm模板中用$user来引用它。

context.put("user", user);

}

}

用来修改数据的页面模板,这里我只解释$group.mapTo($user) 因为在前面“register表单”的页面上,加上和修改一点内容就多了$group.mapTo($user)这个

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

$group.mapTo($user)

...

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

...

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

...

#userAccountMessage ($group.lastName)

...

<input type="submit" name="event_submit_do_update" value= "修改" />

9.3.2.2 mapTo的功能是填充表单。说白了就是 表单数据回显

这行代码的意思是:用screen中所取得的user对象的值来填充表单,作为表单的初始值。

和Group.setProperties()方法相反,mapTo将Java Bean properties的值映射到同名的

fields中。

9.3.2.3. 用action来处理数据, 说白了就是保存修改后的页面, 注意webx中一切动作都要由action来完成, action中的方法名自己起, 编辑后保存, 所以我就起名 doUpdate

修改老数据的action代码和创建新数据的action代码几乎相同,而且它们可以共享同一

个UserAccountAction类:

用来保存提交数据的action

public class UserAccountAction {

public void doRegister(...) throws Exception {

...

}

//userAccount是.vm中传过来的并且封装好了数据

public void doUpdate(@FormGroup("userAccount") MyUser user,

Navigator nav) throws Exception {

save(user);

nav.redirectTo("updateSuccess");

}

}

下面介绍批量修改数据,注意一个screen类中只能有一个execute方法所一个方法要一个对应的screen类

思路:

1.从后台读取所有数据放到集合中, 然后将集合放入context对象中, 由screen类的 execute来完成

2.在.vm中foreach集合

#foreach($user in $users)//users是screen类中通过context对象传过来的

#set ($group = $form.userAccount.getInstance($user.id))

$group.mapTo($user)

注意$form.userAccount.getInstance($user.id) 不使用默认的创建而 使用getInstance方法 传入用户id修改不同表单

3.用action来处理数据

public class UserAccountAction {

@Autowired

//FormService是webx的接口

private FormService formService;

public void doBatchEdit(Navigator nav) throws Exception {

Form form = formService.getForm();

if (form.isValid()) {

//userAccount批量修改的.vm表单中的#set ($group = $form.userAccount.getInstance($user.id))

Collection<Group> groups = form.getGroups("userAccount");

for (Group group : groups) {

MyUser user = new MyUser();

group.setProperties(user);

save(user);

}

nav.redirectTo("success");

}

}

}

有关Form的API

Group API

9.4.5. 外部验证

表单验证服务是被设计成供一个应用的内部使用的服务。它所生成的压缩格式的field key,例

如“_fm.r._0.p”,是不稳定的。它和配置文件中的group、field的名称、排列顺序有关,可

能随着配置的变化而变化。即便是非压缩的格式,例如“_fm.register._0.password”,也

会因配置文件中group、field命名的改变而改变。如果需要让外界系统来提交并验证表单,最好

提供一个相对稳定的接口。所以外界系统最好不要依赖于这些内部的field keys。

如果真的需要让外界系统来提交并验证表单,可以做一个screen来转发这个请求。Screen的代

码像这个样子:

例 9.70. 转发外部表单请求

9.5. 本章总结

表单服务是一个比较复杂但也相当强大的服务。虽然目前它还不支持客户端验证和服务端异步验证功能,但下一步会加上这些功能。

表单服务最重要的设计思想是:将验证规则与页面以及业务逻辑完全分离(就是不在.vm中创建group实例即:#set ($group = $form.userAccount.defaultInstance),使验证规则的扩展和维护变得非常容易。

Webx开发时注意的部分:

Webx-模块名.xml 要加载 模块名包下的 form.xml

webx学习笔记

时间: 2024-10-13 05:36:22

webx学习笔记的相关文章

Webx学习笔记(八)Request Context之Session

1 Session概述 HTTP协议是无状态的,但通过session机制,就能把无状态的变成有状态的.Session的功能就是保存HTTP请求之间的状态数据.有了session的支持,就很容易实现诸如用户登录.购物车等网站功能.在Servlet API中,有一个HttpSession的接口. 在Java代码中访问session //在一个请求中,保存session的状态 // 取得session对象 HttpSession session = request.getSession(); // 在

Webx学习笔记(六)Pipeline服务

1. Pipeline工作原理 Pipeline的意思是管道,管道中有许多阀门(Valve),阀门可以控制水流的走向.在Webx中,pipeline的作用就是控制应用程序流程的走向. 图 6.4. Pipeline和Valves Pipeline的设计和filter非常相似,也是击鼓传花式的流程控制.但是有几点不同: Pipeline只能控制流程,不能改变request和response. Pipeline是轻量级组件,它甚至不依赖于WEB环境.Pipeline既可以在程序中直接装配,也可以由s

Webx学习笔记(四)Webx Turbine

Webx Turbine建立在Webx Framework的基础上,实现了页面渲染.布局.数据验证.数据提交等一系列工作.Webx Turbine所遵循下面的设计理念包括:页面驱动约定胜于配置 页面布局: Screen,代表页面的主体.Layout,代表页面的布局.Control,代表嵌在screen和layout中的页面片段 1.webx设计理念: 页面驱动:         在程序员介入以前,让界面设计师可以直接创建模板,并展示模板的效果.页面驱动的反面,是程序驱动,或者是Action驱动

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"

vector 学习笔记

vector 使用练习: /**************************************** * File Name: vector.cpp * Author: sky0917 * Created Time: 2014年04月27日 11:07:33 ****************************************/ #include <iostream> #include <vector> using namespace std; int main

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则

Caliburn.Micro学习笔记(一)----引导类和命名匹配规则 用了几天时间看了一下开源框架Caliburn.Micro 这是他源码的地址http://caliburnmicro.codeplex.com/ 文档也写的很详细,自己在看它的文档和代码时写了一些demo和笔记,还有它实现的原理记录一下 学习Caliburn.Micro要有MEF和MVVM的基础 先说一下他的命名规则和引导类 以后我会把Caliburn.Micro的 Actions IResult,IHandle ICondu

jQuery学习笔记(一):入门

jQuery学习笔记(一):入门 一.JQuery是什么 JQuery是什么?始终是萦绕在我心中的一个问题: 借鉴网上同学们的总结,可以从以下几个方面观察. 不使用JQuery时获取DOM文本的操作如下: 1 document.getElementById('info').value = 'Hello World!'; 使用JQuery时获取DOM文本操作如下: 1 $('#info').val('Hello World!'); 嗯,可以看出,使用JQuery的优势之一是可以使代码更加简练,使开

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓存,时间戳缓存

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

Activiti 学习笔记记录(三)

上一篇:Activiti 学习笔记记录(二) 导读:上一篇学习了bpmn 画图的常用图形标记.那如何用它们组成一个可用文件呢? 我们知道 bpmn 其实是一个xml 文件