1. 视图优先
在Asta4D中,遵循的是视图优先(View First)的原则,而不是传统的MVC架构,URL规则声明不需要声明Cotroller,一个URL可以直接映射一个模板文件--视图优先:)
Asta4D的URL映射规则不是通过配置文件来定义的,框架通过一组易于试用的API构建了一套DSL来帮助定义URL规则,也就是说,Asta4D的URL规则声明是可编程,相对于基于配置文件的声明方式,这提供了更多的弹性。
Asta4D提供了一个接口:UrlMappingRuleInitializer,用户通过实现该接口来声明自己的URL规则:
public class UrlRules implements UrlMappingRuleInitializer { @Override public void initUrlMappingRules(UrlMappingRuleHelper rules) { //@formatter:off rules.add(GET, "/") .redirect("/app/index"); rules.add(GET, "/redirect-to-index") .redirect("p:/app/index"); rules.add("/app/", "/templates/index.html"); rules.add("/app/index", "/templates/index.html"); rules.add("/app/{name}/{age}", "/templates/variableinjection.html"); ... //@formatter:on } }
2. 映射规则声明的语法与路径变量的声明
Asta4D的规则映射语法基本上是参照Spring MVC的URL映射规则实现的,声明的路径中,用花括号包起来的部分将被解释为路径变量,并在稍后的处理逻辑中可以引用到。
同时,在声明URL映射规则的时候,可以通过下面的语法声明额外的路径变量:
rules.add("/app/{name}/{age}", "/templates/variableinjection.html") .var("extraId", 1234);
3. 变量注入
Asta4D实现了跟Spring MVC及其类似的变量注入机制,在snippet class的实现中,实例变量以及方法的参数的值,都由框架自动注入。
在Asta4D中,snippet class的实例是在每一个request中单子化的,即无论一个snippet class被引用多少次,在一个request中只会维持一个实例。我们来看看下面的snippet class:
public class InitSnippet implements InitializableSnippet { @ContextData private String value; // (1) private long id; private String resolvedValue; private int count = 0; @Override public void init() throws SnippetInvokeException { //(2) resolvedValue = value + "-resolved"; count++; } @ContextData private void setId(long id) { //(3) this.id = id; } public Renderer render_1() { return Renderer.create(".value", resolvedValue) .add(".count", count); } public Renderer render_2() { return Renderer.create(".value", resolvedValue) .add(".count", count); } // (4) public Renderer getPathVarName( @ContextData(name = "count", scope = WebApplicationContext.SCOPE_PATHVAR) int count) { } // (5) public Renderer getQueryParamName( @ContextData(name = "var", scope = WebApplicationContext.SCOPE_QUERYPARAM) String name) { } // (6) public Renderer getDefaultName(String name) { } }
(1)声明了名为value的变量,@ContextData表明该变量需要在snippet类实例化时接受注入
(2)实现了InitializableSnippet接口的init方法,这个接口不是必须的,但实现了该接口的snippet class,在所有实例变量被注入结束后,init方法会被调用一次来实现自定义的初始化逻辑
(3)setter方法上同样可以通过@ContextData来声明实例变量的注入
(4)snippet方法上的变量注入声明,注意,这里用name和scope额外声明了该变量的查找名字以及查找scope:在路径变量中查找名为count的变量
(5)仍然是snippet方法上的变量注入声明:在request parameter中查找名为var的变量,注意,这里查找的变量名与实际声明的方法的参数名是不一致的。
(6)snippet方法上的简单变量注入声明,既没有名字,也没有scope,和(1),(3)的例子相同,在没有声明名字的时候,查找的变量名字将使用声明的变量的名字,而没有声明scope的时候,将按照下述的顺序进行查找:
- html tag属性,一直上溯到最外层的html tag(该scope只对snippet方法有效)
- 路径变量(path var)
- request parameter
- flash var(redirect时跨请求传递的变量)
- cookie
- request header
- request attribute
- session
- global(框架维护的一个全局静态变量池)
额外说明的是, 这个顺序可以在框架启动的时候通过WebApplicationConfiguration进行修改。