设计 REST 风格的 MVC 框架-4 设计拦截器
 
- UID
- 1066743
|

设计 REST 风格的 MVC 框架-4 设计拦截器
设计拦截器拦截器和 Servlet 规范中的 Filter 非常类似,不过 Filter 的作用范围是整个 HttpServletRequest 的处理过程,而拦截器仅作用于 Controller,不涉及到 View 的渲染,在大多数情况下,使用拦截器比 Filter 速度要快,尤其是绑定数据库事务时,拦截器能缩短数据库事务开启的时间。
拦截器接口 Interceptor 定义如清单 18 所示。
清单 18. 定义 Interceptor1
2
3
| public interface Interceptor {
void intercept(Execution execution, InterceptorChain chain) throws Exception;
}
|
和 Filter 类似,InterceptorChain 代表拦截器链。InterceptorChain 定义如清单 19 所示。
清单 19. 定义 InterceptorChain1
2
3
| public interface InterceptorChain {
void doInterceptor(Execution execution) throws Exception;
}
|
实现 InterceptorChain 要比实现 FilterChain 简单,因为 Filter 需要处理 Request、Forward、Include 和 Error 这 4 种请求转发的情况,而 Interceptor 仅拦截 Request。当 MVC 框架处理一个请求时,先初始化一个拦截器链,然后,依次调用链上的每个拦截器。请参考清单 20 所示的代码。
清单 20. 实现 InterceptorChain 接口1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| class InterceptorChainImpl implements InterceptorChain {
private final Interceptor[] interceptors;
private int index = 0;
private Object result = null;
InterceptorChainImpl(Interceptor[] interceptors) {
this.interceptors = interceptors;
}
Object getResult() {
return result;
}
public void doInterceptor(Execution execution) throws Exception {
if(index==interceptors.length)
result = execution.execute();
else {
// must update index first, otherwise will cause stack overflow:
index++;
interceptors[index-1].intercept(execution, this);
}
}
}
|
成员变量 index 表示当前链上的第 N 个拦截器,当最后一个拦截器被调用后,InterceptorChain 才真正调用 Execution 对象的 execute() 方法,并保存其返回结果,整个请求处理过程结束,进入渲染阶段。清单 21 演示了如何调用拦截器链的代码。
清单 21. 调用拦截器链1
2
3
4
5
6
7
8
9
10
| class Dispatcher {
...
private Interceptor[] interceptors;
void handleExecution(Execution execution, HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
InterceptorChainImpl chains = new InterceptorChainImpl(interceptors);
chains.doInterceptor(execution);
handleResult(request, response, chains.getResult());
}
}
|
当 Controller 方法被调用完毕后,handleResult() 方法用于处理执行结果。 |
|
|
|
|
|