1. 方便的Renderer
在Asta4D中,所有的渲染逻辑都通过一个叫做Renderer的类来声明,Renderer类提供了丰富的接口来帮助用户实现渲染逻辑:
Renderer render = new GoThroughRenderer(); render.add("#someIdForInt", 12345); render.add("#someIdForLong", 12345L); render.add("#someIdForBool", true); render.add("#someIdForStr", "a str"); render.add("#someIdForNull", (Object) null); render.add("#someIdForClear", Clear); Element newChild = ElementUtil.parseAsSingle("<div></div>"); render.add("#someIdForElementSetter", new ChildReplacer(newChild)); render.add("#someIdForElement", ElementUtil.parseAsSingle("<div>eee</div>")); render.add("#someIdForRenderer", Renderer.create("#value", "value"));
对于List数据,也可以轻松的渲染:
Renderer render = new GoThroughRenderer(); render.add("#someIdForInt", Arrays.asList(123, 456, 789)); render.add("#someIdForLong", Arrays.asList(123L, 456L, 789L)); render.add("#someIdForBool", Arrays.asList(true, true, false)); render.add("#someIdForStr", Arrays.asList("str1", "str2", "str3")); Element newChild1 = ElementUtil.parseAsSingle("<div>1</div>"); Element newChild2 = ElementUtil.parseAsSingle("<div>2</div>"); render.add("#someIdForElementSetter", Arrays.asList(new ChildReplacer(newChild1), new ChildReplacer(newChild2))); render.add("#someIdForElement", Arrays.asList(newChild1, newChild2)); render.add("#someIdForRenderer", Arrays.asList(123, 456, 789), new RowConvertor<Integer, Renderer>() { @Override public Renderer convert(int rowIndex, Integer obj) { return Renderer.create("#id", "id-" + obj).add("#otherId", "otherId-" + obj); } });
Dom元素的属性也可以简单的操作:
render.add("#id", "+class", "yyy"); render.add("#id", "-class", "zzz"); render.add("#id", "+class", "xxx"); render.add("#id", "value", "hg"); render.add("#id", "href", null); render.add("#X", "value", new Date(123456L));
2. 安全的Renderer
从前面的示例代码已经可以看到,除了引用"ElementUtil.parseAsSingle"从字符串自行构建Dom元素以外,其他所有对DOM的操作都是通过Renderer代理的,事实上,所有被Renderer代理的渲染操作都会被强制转义,这意味着如果你的代码中没有调用“ElementUtil.parseAsSingle”的话,你的系统对Cross-Site是天然免疫的,你不需要考虑用户是否在你的系统中提交了非法字符,所有的数据,在被render到页面的时候,都会被强制HTML转义。另一方面,从我们的实践经验来看,需要调“ElementUtil.parseAsSingle”来自行构建HTML的情况是非常少见的,因此,你只需要看管好你为数不多的“ElementUtil.parseAsSingle”调用,你就可以跟Cross-site漏洞说bye-bye了。
3. 可测试的渲染逻辑
Web页面的测试一直是个老大难问题,selenium是常见技术,用来测试页面的渲染是否正确。对于Asta4D来说,可测试的Renderer使得我们可以减少至少一半selenium测试用例而代之以简单的junit测试。
仔细考察前面的示例代码,所有的渲染逻辑都保存在Renderer类中,因此,很自然的,我们只需要对snippet方法返回的Renderer实例进行测试就足以确认大部分的渲染逻辑是否正确了:
RendererTester tester = RendererTester.forRenderer(render); Assert.assertEquals(tester.get("#someIdForInt"), 12345); Assert.assertEquals(tester.get("#someIdForLong"), 12345L); Assert.assertEquals(tester.get("#someIdForBool"), true); Assert.assertEquals(tester.get("#someIdForStr"), "a str"); Assert.assertEquals(tester.get("#someIdForNull"), null); Assert.assertEquals(tester.get("#someIdForClear"), Clear);
更多的例子可以参见代码: https://github.com/astamuse/asta4d/blob/develop/asta4d-core/src/test/java/com/astamuse/asta4d/test/unit/RenderTesterTest.java