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进行修改。