🍖 变量引用
模板表达式最原始的目的就是各种各样的数据动态绑定到HTTP请求的各个属性中,要完成这一步就要实现对外部数据的引用。
Forest的模板表达式提供了两种最基本的数据引用方式: 变量名引用
、参数序号引用
如上面Hello World例子所示,表达式中可以直接引用@Var
或 @DataVariable
所标注的变量名。除此之外也可以直接引用全局配置中定义的全局变量名。
# 全局变量
全局变量名可以在 yaml
配置文件中定义
forest:
variables:
a: foo
b: bar
2
3
4
也可以在 properties
配置文件中定义
forest.variables.a=foo
forest.variables.b=bar
2
注意
无论是yaml
配置文件还是properties
配置文件,其定义的 Forest 全局变量必须定义在 forest.variables
之下,否则无法被引用到
我们在全局配置中定义了两个全局变量,分别为a
和b
。接着就可以在@Request
中同时引用这两个变量。
@Get(url = "http://localhost:8080/{a}/{b}")
String send();
2
调用send()
方法后产生的url
的值为:
http://localhost:8080/foo/bar
这里因为是全局变量,{a}
和{b}
的值分别来自全局配置中的变量a
和b
的值,也就是foo
和bar
,所以并不需要在方法中传入额外的参数。
也可以使用${a}
、${b}
来引用变量
@Get(url = "http://localhost:8080/${a}/${b}")
String send();
2
效果同上
友情提示
{a}
与${a}
的区别请参见《{表达式} 与 ${表达式}》
# 参数变量
变量同样可以设置在接口方法的参数上
通过标注在形参上的@Var
注解,来表示该参数是一个可以被字符串模板引用的 Forest 变量
@Var
注解的value
属性为变量名
@Get(url = "http://localhost:8080/{a}/{b}")
String send(@Var("a") String a, @Var("b") String b);
2
当调用send("xxx", "yyy")
时,产生的url
值为:
http://localhost:8080/xxx/yyy
# 变量作用域
[全局变量作用域] > [参数变量作用域]
全局变量作用域: 在整个项目都可以引用到
参数变量作用域: 只能在该变量所在的接口方法可以引用到
# 变量优先级
[参数变量优先级] > [全局变量优先级]
一般来说,变量作用域越大,则变量的优先级越小
如果在某个方法上有同名的参数变量和全局变量,则会取参数变量的值
# 变量与配置属性引用的异同
- 配置属性引用以井号(
#
)开头,如#{a}
。变量引用以花括号包裹或者以美元符号($
)开头的花括号包裹,如{a}
、${a}
- 配置属性只是简单的字符串,不能进行后续操作,而变量是可以当作类似java对象进行操作,某方法调用,和子属性访问
- 在配置文件(
application.yml
或application.properties
)中定义的变量,必须在forest.variables
下,否则引用不到
# 深度引用
Forest自v1.7.1
版本开始支持字符串模板的深度变量引用,即一个变量的值如果也是一个字符串模板并引用另一个变量,那么就会一层变量接着一层变量的解析,不管引用了多少层变量,都可以一直解析最后一个变量为止。
forest:
variables:
a: "{user.name}"
b: "{user.password}"
user:
name: foo
password: bar
2
3
4
5
6
7
在Java代码中直接引用
// 最终 URL 为: http://localhost:8080/foo/bar
@Get(url = "http://localhost:8080/{a}/{b}")
String send();
2
3
如果不想进行深度引用,可以使用深度引用停止语法,即在变量后加上!
符号,那么就只会引用一层该变量的值,无论该变量的值是否会包含其他字符串模板的内容,都不会再进行解析了,而是只当做字符串进行返回。
// 最终 URL 为: http://localhost:8080/{user.name}/{user.password}
// 变量 a 和 b 的值直接返回字符串,而不会进行任何解析
@Get(url = "http://localhost:8080/{a!}/{b!}")
String send();
2
3
4