Febit Wit 采用IoC的机制管理组件,也就是说只要是提供了setter的组件,随处都可以配置。当前现在支持属性值自动转换为以下类型:String, class, int/Integer, boolean/Boolean,以及他们的数组形式。 例如:
# 格式为 key = value # 设置输出编码 Engine.setEncoding(String) engine.encoding=UTF-8 # 设置默认面声明变量 Engine.setVars(String[]) engine.vars=request, response
这是一个开放的注入管理器,只要需要,就可以把配置写在这里面,然后通过Engine.get(type)得到配置的实例
组件如果标记了 `@org.febit.wit.Init 同时还会在配置注入完成之后执行
Engine.create("配置文件列表", 额外的参数Map)
,分割/default.wim,不需要另行设置缺省配置文件:default.wim
${}会生效+,例如engine.resolvers+# 以#开头的是行注释
# 设置了一个数值
DEFAULT_ENCODING=UTF-8
# @开头的一般都有特殊意义
# 依赖的模块列表
@modules=
# 设置一个参数: 类型.字段名=值
# 和 properties 一样
engine.looseVar=false
# 例如 @global 被用来声明哪些是全局组件
# IoC 会自动注入到需要这些组件的字段,例如 NativeFactory.nativeSecurityManager
@global='''
engine
logger
loader
resolverManager
textStatement
global
'''
# 这里先设置区段 [engine], 这样就可以简短书写了
# 区段中 : 用来定义类型继承自那个类型
# 也可以是定义过类型的区段(实例化的时候总得一层层找到他的类型, 对吧。)
[engine :org.febit.wit.Engine]
encoding=${DEFAULT_ENCODING}
# looseVar=false
# trimCodeBlockBlankLine=true
# vars=
# inits=
# shareRootData=true
# 这里就是个例子,loader 继承自routeLoader包括类型和其他参数
# 另外还记得前面 loader 被添加到全局组件了吧
# 不要担心会有多个 routeLoader, 如果没有`Engine.get("routeLoader")`, 它只是个配置,并不会被实例化
# 不过, Engine.get("loader") 和 Engine.get("routeLoader") 不是同一个实例
# 这个继承关系可以在以后被覆盖,无状态,不会有之前的继承参数
# 例如 改成 [loader :servletLoader]
[loader :routeLoader]
# 日志组件的实现
[logger :simpleLogger]
# 更改日志组件为 slf4j
[logger :slf4jLogger]
[textStatement :simpleTextStatement]
# 下面你可以当做是定义了别名, 以后就可以使用别名了,不用写包名,是不是很省劲
[simpleLogger :org.febit.wit.loggers.impl.SimpleLogger]
[slf4jLogger :org.febit.wit.loggers.impl.Slf4jLogger]
[commonLogger :org.febit.wit.loggers.impl.CommonLogger]
[pathLoader]
encoding=${DEFAULT_ENCODING}
assistantSuffixs+=.wit
suffix=.wit
# appendLostSuffix=false
# root=your/template/path
[classpathLoader :org.febit.wit.loaders.impl.ClasspathLoader]
# @extends 仅仅会把参数继承过来,不会继承类型,覆盖无状态,可以是个列表
@extends=pathLoader
[stringLoader :org.febit.wit.loaders.impl.StringLoader]
# 为了更直观可以使用 \ 转义看不见的换行符
# 当然不换行也是可以的
[resolverManager]
resolvers=\
org.febit.wit.resolvers.impl.LongOutResolver,\
org.febit.wit.resolvers.impl.IntegerOutResolver
# 这里 "DEFAULT_ENCODING" 又被使用了一次
# 先设置区段[]为空
[]
# 又可以使用完整的“类型.字段名”了
resolverManager.ignoreNullPointer=true
采用内置的Jodd-props, 文法类似于ini
.)DEFAULT_ENCODING'''开头 并在尾行以此结尾, 或者换行,并忽略首位空格
~~~~~
list += ‘’’
org.febit.wit.resolvers.impl.LongOutResolver
org.febit.wit.resolvers.impl.IntegerOutResolver
org.febit.wit.resolvers.impl.InternalVoidResolver
‘’’
~~~~~属性名 += 值的形式即可= 将会根据先来后到的规则覆盖掉最早设置的值,使用+=将会跨配置文件保留先前的值,并附加上当前的值,分割的[classpathLoader :org.febit.wit.loaders.impl.ClasspathLoader] @extends=pathLoader
这样将会使得 classpathLoader 继承所有以”pathLoader.”开头的所有配置
注意:这种继承之间的附加操作”+=” 是无效的,原生的将直接覆盖掉继承来的值
@modules=值 可以加载依赖的配置文件(或者叫模块)@modules +=''' lib-assert.wim lib-type.wim lib-cache.wim '''
| DEFAULT_ENCODING | 字符串 | 默认编码 |
| engine.encoding | 字符串 | 输出编码 |
| engine.looseVar | Boolean | 是否启用宽松的变量声明 |
| engine.trimCodeBlockBlankLine | Boolean | 是否删除指令所占行 |
| engine.textStatementFactory | 类型 | TextStatment生成器 |
| engine.vars | 列表 | 免声明变量名 |
| engine.inits | 列表 | 初始化模板 |
| engine.shareRootData | Boolean | 对子模版共享传入的参数 |
| routeLoader.defaultLoader | 类型 | 路由加载器的缺省加载器 |
| routeLoader.loaders | 路由规则 | 路由加载器的路由规则 |
| resolverManager.resolvers | 类型列表 | bean属性解释器 |
| resolverManager.ignoreNullPointer | Boolean | 是否忽略属性读取时bean为null的异常 |
| global.registers | 类型列表 | 全局变量/常量 注册器 |
| nativeSecurity.list | 列表 | Native黑白名单 |
classpathLoaderservletLoaderfileLoaderstringLoader## Classpath 资源加载 [classpathLoader] # 模板根路径 root=your/template/path ## Web 根目录 资源加载 [servletLoader] root=/your/template/path ## 普通文件系统 资源加载 [fileLoader] root=/your/template/path
# 新增两个 loader, 继承自 classpathLoader [classpathLoader-root :classpathLoader] [classpathLoader-root2 :classpathLoader] # 同上,还可以修改参数 [codeLoader :stringLoader] codeFirst=true # routeLoader 已经配置为全局 loader # [loader :routeLoader] # 改成其他的可以使用: # [loader :classpathLoader] # ^ 这样 所有资源直接使用 classpathLoader 来加载,不会走 routeLoader [routeLoader] # 缺省的Loader default=classpathLoader # 路由规则 loaders +=''' classpath: classpathLoader-root classpath2: classpathLoader-root2 /sub/path classpathLoader-root str: stringLoader code: codeLoader '''
以上面的配置为例:”classpath:/a.wit”,”/sub/path/a.wit” 都将会使用”classpathLoader”加载”/a.wit”; “code:var a =1;”将会作为字符串模版被加载为”var a =1;”;”classpath2:/b.wit” 将会使用”classpathLoader-root2”进行加载,其余的如 “/a.wit” “/b/sub/path/a.wit” 会使用缺省的”classpathLoader” 进行加载
可以包裹一个普通loader,并设置一定时间内不检查更新(使用一些检查成本较高的模板时非常有用)
可以包裹一个普通loader,并设置安全名单
首先,继承接口GlobalRegister
然后在方法
void regist(GlobalManager manager)中进行注册
//如:
public void regist(final GlobalManager manager) {
//全局变量
SimpleBag globalBag = manager.getGlobalBag();
globalBag.set("MY_GLOBAL", "MY_GLOBAL");
globalBag.set("MY_GLOBAL_2", "MY_GLOBAL_2");
//全局常量
SimpleBag constBag = manager.getConstBag();
constBag.set("MY_CONST", "MY_CONST");
constBag.set("MY_CONST_2", "MY_CONST_2");
//全局Native 函数
constBag.set("new_list", this.nativeFactory.createNativeConstructorDeclare(ArrayList.class, null));
constBag.set("list_size", this.nativeFactory.createNativeMethodDeclare(List.class, "size", null));
constBag.set("list_add", this.nativeFactory.createNativeMethodDeclare(List.class, "add", new Class[]{Object.class}));
constBag.set("substring", this.nativeFactory.createNativeMethodDeclare(String.class, "substring", new Class[]{int.class, int.class}));
//全局自定函数
constBag.set("is_bool", new MethodDeclare() {
public Object invoke(Context context, Object[] args) {
return ArrayUtil.get(args, 0, null) instanceof Boolean;
}
});
}
配置文件里注册该注册器
[global] registers+= my.pkg.MyGlobalRegister
TextStatment的作用是缓存模版文件中的文本片段,根据最终输出的类型不同可分别保存成不同的形式,如:char[]、byte[]。对于模版引擎的渲染,io以及编码消耗了很大一部分性能,选择一个更接近目标输出的形式有利于优化性能。
另外可以继承
TextStatementFactory提供更适合自己的TextStatement
,\r\n 分割,并自动删除前后空白字符+ 或者无修饰 为白名单- 为黑名单默认配置已经添加了基本类型为白名单 示例:
# 示例白名单: # com.dog # com.cat # com.mouse.jerry # 黑名单: # com.mouse # com.cat.tom [defaultNativeSecurity] list=''' com.dog com.cat com.mouse.jerry - com.mouse - com.cat.tom '''