Webx 的表单验证服务学习经验

说说

我曾经使用过 Tornado 框架以及 Spring MVC 框架的表单系统, 他们的表单系统相当轻量级, 于是我以为 webx 框架的表单服务也差不多. 今天仔细看了一下官方文档, 发现 webx 确实有其独特的地方.

学习了表单验证, 如何写一个表单页面就没有问题了. 也并不需要先学会写一个表单然后再学表单验证服务, 直接开始学这个就OK.

验证形式

表单验证就是对用户输入的信息是否规范进行检查. 检查有三种形式:

  1. 数据传到服务器, 服务器在后台检查
  2. 数据在前端通过 js 来检查
  3. 通过 js 异步请求, 实现服务器异步验证.

目前 webx 框架实现了第一种形式. 后两种形式均需要在前端编写相应 js 代码方能完成. 相比之下 Tornado 框架并不自带服务端检查表单的功能, 完全需要靠 js + 后台api 来编写.

学习 webx 的表单验证服务就是学习这里的第一种形式.

webx 表单验证的特色

  • **验证逻辑与表现逻辑分离

** 这就是说, 画表单的代码, 和对表单里面填的东西是否正确的验证代码, 是分开在不同的文件里面存放的. 这样可以多个表单共用一个验证器, 在修改验证器的时候也不会觉得两种代码杂糅在一起很烦. 我觉得这个特性非常棒!

  • **验证逻辑和应用代码分离

** 这就是说, 验证代码也不用写在 java 文件里面. 优点同上.**

**

这两个分离, 就是说验证代码完全独立, 既不存在于前端渲染代码中, 也不存在于后端应用的业务逻辑代码中, 而是单独出来成为一个独立的部分. 这种程度的解耦真是美好:)

 

极简例子

下面假设表单的 url 是 http://localhost:8080/ljw/test_1.htm, 工程基于 com.alibaba.webx.tutorial1 进行开发.

**1. src/main/java/com….app1/module/screen/ljw/Test1.java

** 当用户发起第一次请求的时候, 此处的out会显示到网页上, 此外 vm 文件上的内容也会跟着显示出来.

public class Test1 {
	@Autowired
	private HttpServletResponse response;

	public void execute() throws Exception {
		response.setContentType("text/html");
		PrintWriter out = response.getWriter();
		out.print("<h1>This is from Java</h1>");
	}
}

2. src/main/java/com….app1/User.java

public class User {
	private String id;
	private String pwd;

	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getPwd() {
		return pwd;
	}
	public void setPwd(String pwd) {
		this.pwd = pwd;
	}
}

**3. src/main/webapp/app1/templates/screen/ljw/Test1.vm

** 下面这段 vm 模板代码有好多个关键点:

  • #set ($group = $form.ljw.defaultInstance) 创建一个 group 实例
  • #registerMessage($group.id) 这个宏定义在用户输入错误需要返回提示的时候显示出 group.id.message 里面的内容
  • $!group.id.value 这个感叹号是用来让 value 忽略 null 错误的
  • 粗体部分 ljw_action 会由webx框架转为驼峰风格 LjwAction 并交由这个 Java 类进行表单处理
  • event_submit_do_ljw 这个最隐蔽, 粗体部分的下划线风格 do_ljw 会由 webx 框架转为驼峰的 doLjw 并由 LjwAction.doLjw() 处理.
#macro (registerMessage $field)
	#if (!$field.valid) $field.message #end
#end
<h2>From Template</h2>

<form action="$app1Link.setTarget("ljw/Test1")" method="post">
	$csrfToken.hiddenField
	<input type="hidden" name="action" value="ljw_action" />
	#set ($group = $form.ljw.defaultInstance)
	#registerMessage($group.id)
	#registerMessage($group.pwd)
	<input type="text" name="$group.id.key" value="$!group.id.value"/>
	<input type="password" name="$group.pwd.key" value="$!group.pwd.value"/>
	<input type="submit" name="event_submit_do_ljw"/>

	#if ($id)
		<p> $id </p>
	#end
</form>

4. src/main/webapp/WEB-INF/app1/form.xml

与其他的 group 并列, 加入一个新的 group, 这个一看就懂了, 什么 required 的已经自解释了. 当然除了必填项, 还支持各种各样的验证形式, 正则表达什么的, 交给 Java 判断等等. 详见官网文档.

<group name="ljw" extends="csrfCheck">
	<field name="id" displayName="你的账号">
		<fm-validators:required-validator>
			<message>必须填写 ${displayName}</message>
		</fm-validators:required-validator>
	</field>
	<field name="pwd" displayName="你的密码">
		<fm-validators:required-validator>
			<message>${displayName} 还是要填的</message>
		</fm-validators:required-validator>
	</field>
</group>

 

参考