实现一个web框架需要哪些模块,需要包含什么样的功能,需要怎样分层。。。
针对不同领域开发的框架虽然侧重点会有区别(比如博客有typecho,emlog,开源CMS有wordpress,drupal,还有一些商城系统),但是一些基本的元素还是一致的。
本文简要分析了web框架中拦截器的php实现
不论是基于j2ee的struts、webwork,还是基于php的ThinkPHP,或者其他各类功能完善的web框架,都会引入拦截器机制。
![lj.jpg][1]
首先使用拦截器能够提高代码复用性。比如在执行某一类功能的多个action之前都需要对用户权限进行验证,或者需要给一系列action的输出加上一些特殊信息,虽然给每一个action前后都加上同样的处理可以实现此功能,但是会造成很多重复代码,一眼看上去就比较挫。
其次使用配置管理拦截器能够最大限度的减少代码耦合,可以对各种附加功能进行“可插拔式”的管理。在web应用中这样的机制毋庸置疑是极有优势的,比如应用发布后发现有一个功能的权限没有加保护,这个时候只要改一下对应的配置文件,甚至不需要重启服务器就可以将增加的功能部署到运行的应用中。
下面介绍具体在php中如何实现一个基本的拦截器机制。
还是从用户请求的action开始,假如用户现在请求一个action,我们的拦截器需要做的是验证用户的权限,并格式化返回的结果,加入这个拦截器之后应该是 |用户请求->拦截器处理请求参数->action处理->拦截器处理返回结果->返回结果给用户|,当然加入用户无权限的话,在第二步拦截器就会返回错误信息。首先将上一章的示例action封装成ActionInvoke对象,以便传递给拦截器处理:
class ActionInvoke {
private $params;
private $action;
private $interceptors;
public function __construct($action, $params) {
$this->action = $action;
$this->params = $params;
// 从配置文件中获取action对应的拦截器列表
$this->interceptors = $this->getInterceptors();
}
public function invoke() {
// 拦截处理
}
private function getInterceptors() {
// 示例数据:
return array("AuthInterceptor", "DisplayInterceptor");
}
private function execute() {
// 执行action处理,封装上一章action的处理过程
}
}
代码中真正执行用户action的是execute方法,invoke是给拦截器调用的代理方法,是拦截器机制的核心部分。具体实现如下:
public function invoke() {
if (! empty($this->interceptors)) {
$interceptor = array_shift($this->interceptors);
if (! class_exists($interceptor)) {
return $this->invoke();
}
$cls = new ReflectionClass($interceptor);
if (!$cls->hasMethod("intercept")) {
return $this->invoke();
}
$method = $cls->getMethod("intercept");
return $method->invoke($cls->newInstance(), $this);
} else {
return $this->execute();
}
}
首先判断拦截器在列表中是否存在,假如存在,从列表中取出第一个拦截器执行,并将其从列表中删除。所有拦截器执行的都是invoke方法,所以一般可以定义一个公共的接口。如果拦截器列表为空,则真正开始执行action的处理。下面定义一个验证权限的拦截器:
require_once("Interceptor.php");
class AuthInterceptor implements Interceptor {
public function intercept($action) {
echo "--begin auth intercept<br/>";
//处理输入
$ret = $action->invoke();
//处理输出
echo "<br>--end auth intercept<br>";
return $ret;
}
}
这个代码比较简单,就是实现了Interceptor接口的intercept方法,此处只打印了一些输出,然后直接调用action的invoke代理方法。继续看到上面action的invoke方法,假如action只定义了这一个拦截器,那么此时拦截器列表为空,则执行action处理。结果经过拦截处理后返回。假如有其他的拦截器,会按上述步骤依次执行,直到执行完所有的拦截器,然后从各个拦截器依次返回。其实这里的实现就是一个简单的递归调用。
然后在router中的调用方式也有一些变化,将具体处理action的代码段删除,请求交给ActionInvoke对象:
$action = $router["action"];
// 寻找到第一个匹配的路由即执行,然后返回
$actionInvoke = new ActionInvoke($action, $params);
echo $actionInvoke->invoke();
return;
再给这个action加入一个新的拦截器DisplayInterceptor测试一把,页面上返回的结果如下:
--begin auth intercept
----begin display intercept
==>call UserAction method and return result
----end display intercept
--end auth intercept
==>action result
可以看到请求依次经过拦截器处理并依次返回的过程。