在一个框架中,许多地方都要用到上下文(Context),可以说上下文的实现是否到位,直接关系到开发的便捷性及访问效率。
什么是上下文呢?上下文可以认为是在访问者和被访问者之间进行信息传递的纽带。一般的,我们函数之间调用时通过函数参数及返回值来做做数据的传入和传出,但是,这样就会出现不同访问之间的参数都是不同的,在程序中访问的时候,这当然没有问题。但是对于框架来说,它事件不知道你要用什么方式调用,提供的函数及返回值是什么也不知道,这个时候一般来说,会提供一个上下文(Context)来提供数据传入和传出,当然,也有的人叫它数据总线。
Tiny框架是一个SOA体系,因此,肯定要涉及上下文的问题;同时,还提供了流程编排的框架,这就更离不开上下文了。
我们来描述一次请求看看数据的流转,比如:我们有一个服务原型是:String sayHello(String name);这样,在页面请求时,需要输入一个name的参数,给控制层,控制层调用远程服务来访问sayHello服务,然后返回值,并让展现层进行展现:
浏览器端输入以下url:xxx.xxx/xxx/sayHello.do?name=abc,这个时候控制层从request中读到了name的值为abc,这个时候,去调用远程服务,就要构建服务调用上下文,在服务调用上下文中放置name:abc键值对,然后调用远程服务,远程服务处理,拿到上下文,根据调用的服务读出参数,并调用sayHello服务,这个服务可能是一个流程,那么这个参数又要传给流程的上下文进行执行,执行出结果之后,又要按照原路进行返回。
说得比较啰嗦,但是还是表明了数据需要在许多个上下文之间进行流转。虽然这个过程,对于普通开发人员及使用者来说,是看不到的,但是它就在那里,这个过程总是有的。
这时,如何让数据在上下文中传递就是非常困难的,最简单的方式就是数据复制,把上下文中的数据都复制到新的上下文中,但是这时有个问题,有时候,你复制了许多数据,但是真正用到的数据很少,当然结果返回也是要一路复制回去的,这就导致了浪费,同时也消耗了时间和空间。
为此我们提出了上下文嵌套模式,通过上下文互相嵌套来避免数据复杂带来的性能影响,从此数据不再需要复制。
基本的上下文接口如下,可以看出,它和Map的接口是非常相似的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
public
interface
BaseContext {
/**
* 添加到环境
*
* @param name
* @param object
*/
<T> T put(String name, T object);
/**
* 把环境中某键值的名字换成另外的名字
* @param key
* @param newKey
* @return
*/
boolean
renameKey(String key, String newKey);
/**
* 遍历所有删除及子环境并删除找到的第一个
*
* @param name
* @return
*/
<T> T remove(String name);
/**
* 获取对象,如果当前环境中没有,则到子环境当中寻找
*
* @param name
* @return
*/
<T> T get(String name);
/**
*
* @param name
* @param defaultValue
* 默认值
* @return
* @throws NotExistException
*/
<T> T get(String name, T defaultValue);
int
size();
/**
* 检测变量是否存在
*
* @param name
* @return 返回是否存在
*/
boolean
exist(String name);
/**
* 删除环境中的所有内容
*/
void
clear();
/**
* 返回环境中所有内容
*
* @return
*/
Map<String, Object> getItemMap();
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
/**
* 多层环境
*
* @author luoguo
*
*/
public
interface
Context
extends
BaseContext {
/**
* 创建子上下文
*
* @param contextName
* @return
*/
Context createSubContext(String contextName);
/**
* 从子环境删除
* @param contextName 子环境
* @param name 上下文变量名称
*/
<T> T remove(String contextName, String name);
/**
* 从指定子环境获取变量
*
* @param contextName 子环境
* @param name 上下文变量名称
* @return @
*/
<T> T get(String contextName, String name);
/**
* 添加到子环境
*
* @param contextName 子环境
* @param name 上下文变量名称
* @param object 要放入的数据
*
*/
<T> T put(String contextName, String name, T object);
/**
* 返回父亲
*
* @return
*/
Context getParent();
/**
* 设置父亲
*
* @param parent
*/
void
setParent(Context parent);
/**
* 添加子环境
*
* @param contextName 子环境
* @param context
* @return
*/
Context putSubContext(String contextName, Context context);
/**
* 删除子上下文
*
* @param contextName 子环境
*/
Context removeSubContext(String contextName);
/**
* 返回子环境
*
* @param contextName 子环境
* @return 子环境
*/
Context getSubContext(String contextName);
/**
* 删除所有子上下文
*/
void
clearSubContext();
/**
* 返回子环境MAP
*
* @return 子环境MAP
*/
Map<<span></span>String, Context> getSubContextMap();
}
|
于是我们构建了一个完美的死循环--这个是真的,实际上程序真的就陷入了死循环之中,接下来我们的注意力就集中在如何让死循环不死上,这个问题当然必须要解决,解决掉死循环之后,所有关系上下文之上的难题就都没有了,至此,我们拥有了高效的易用的上下文,下面看看测试用例:
1
2
3
4
5
6
7
8
9
10
11
|
public
void
testGetSubContextMap() {
Context context =
new
ContextImpl();
context.put(
"name1"
,
"value1"
);
Context testContext =
new
ContextImpl();
testContext.put(
"name3"
,
"value3"
);
context.putSubContext(
"test"
, testContext);
String value3=context.get(
"name3"
);
assertEquals(
"value3"
, value3);
String value1=testContext.get(
"name1"
);
assertEquals(
"value1"
, value1);
}
|
上下文的重要性在Tiny框架中是毫无置疑的,它大大简化了程序结构,提升了访问效率,在许多的子工程中都引用了上下文,可以说,没有上下文的良好实现,就不会有后续的高效与易用。