diff --git a/src/Framework/ZMBuf.php b/src/Framework/ZMBuf.php index d193ff22..8ebb3e92 100755 --- a/src/Framework/ZMBuf.php +++ b/src/Framework/ZMBuf.php @@ -46,8 +46,6 @@ class ZMBuf // Atomic:可跨进程读写的原子计数,任何地方均可使用 /** @var null|swoole_atomic */ static $info_level = null;//保存log等级的原子计数 - /** @var swoole_atomic $reload_time */ - public static $events = []; /** @var Atomic[] */ public static $atomics; diff --git a/src/Module/Example/Hello.php b/src/Module/Example/Hello.php index b5997ca4..f9163917 100644 --- a/src/Module/Example/Hello.php +++ b/src/Module/Example/Hello.php @@ -6,7 +6,6 @@ namespace Module\Example; use Framework\Console; use ZM\Annotation\CQ\CQCommand; -use ZM\Annotation\Http\Controller; use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Swoole\SwooleEventAt; use ZM\Connection\CQConnection; @@ -15,7 +14,6 @@ use ZM\ModBase; /** * Class Hello * @package Module\Example - * @Controller("/view") */ class Hello extends ModBase { @@ -34,17 +32,10 @@ class Hello extends ModBase } /** - * @RequestMapping("/test/{ping}") - */ - public function ping($param){ - return "You input id is: ".$param["ping"]; - } - - /** - * @RequestMapping("/test/pong") + * @RequestMapping("/test/ping") */ public function pong(){ - $this->response->end("ping"); + return "pong"; } /** diff --git a/src/ZM/Annotation/AnnotationParser.php b/src/ZM/Annotation/AnnotationParser.php index 163eddc5..236e87dc 100644 --- a/src/ZM/Annotation/AnnotationParser.php +++ b/src/ZM/Annotation/AnnotationParser.php @@ -10,7 +10,12 @@ use ReflectionClass; use ReflectionException; use ReflectionMethod; use ZM\Annotation\CQ\{CQAfter, CQBefore, CQCommand, CQMessage, CQMetaEvent, CQNotice, CQRequest}; +use ZM\Annotation\Http\After; +use ZM\Annotation\Http\Before; use ZM\Annotation\Http\Controller; +use ZM\Annotation\Http\HandleException; +use ZM\Annotation\Http\Middleware; +use ZM\Annotation\Http\MiddlewareClass; use ZM\Annotation\Http\RequestMapping; use ZM\Annotation\Interfaces\CustomAnnotation; use ZM\Annotation\Interfaces\Level; @@ -22,6 +27,7 @@ use ZM\Annotation\Swoole\SwooleEventAfter; use ZM\Annotation\Swoole\SwooleEventAt; use ZM\Annotation\Interfaces\Rule; use ZM\Connection\WSConnection; +use ZM\Http\MiddlewareInterface; use ZM\Utils\DataProvider; class AnnotationParser @@ -31,8 +37,7 @@ class AnnotationParser * @throws ReflectionException * @throws AnnotationException */ - public static function registerMods() - { + public static function registerMods() { self::loadAnnotationClasses(); $all_class = getAllClasses(WORKING_DIR . "/src/Module/", "Module"); ZMBuf::$req_mapping[0] = [ @@ -55,6 +60,26 @@ class AnnotationParser DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder); } elseif ($vs instanceof InitBuffer) { ZMBuf::set($vs->buf_name, []); + } elseif ($vs instanceof MiddlewareClass) { + $result = [ + "class" => "\\".$reflection_class->getName() + ]; + foreach ($methods as $vss) { + $method_annotations = $reader->getMethodAnnotations($vss); + foreach ($method_annotations as $vsss) { + if ($vss instanceof Rule) $vss = self::registerRuleEvent($vsss, $vss, $reflection_class); + else $vss = self::registerMethod($vsss, $vss, $reflection_class); + echo get_class($vsss).PHP_EOL; + if ($vsss instanceof Before) $result["before"] = $vsss->method; + if ($vsss instanceof After) $result["after"] = $vsss->method; + if ($vsss instanceof HandleException) { + $result["exception"] = $vsss->class_name; + $result["exception_method"] = $vsss->method; + } + } + } + ZMBuf::$events[MiddlewareClass::class]["\\".$reflection_class->getName()] = $result; + continue 2; } } foreach ($methods as $vs) { @@ -74,8 +99,9 @@ class AnnotationParser elseif ($vss instanceof CustomAnnotation) ZMBuf::$events[get_class($vss)][] = $vss; elseif ($vss instanceof CQBefore) ZMBuf::$events[CQBefore::class][$vss->cq_event][] = $vss; elseif ($vss instanceof CQAfter) ZMBuf::$events[CQAfter::class][$vss->cq_event][] = $vss; - elseif ($vss instanceof OnStart) { - ZMBuf::$events[OnStart::class][]=$vss; + elseif ($vss instanceof OnStart) ZMBuf::$events[OnStart::class][] = $vss; + elseif ($vss instanceof Middleware){ + ZMBuf::$events[MiddlewareInterface::class][$vss->class][$vss->method] = $vss->middleware; } } } @@ -84,7 +110,7 @@ class AnnotationParser ZMBuf::$req_mapping = $tree[0]; //给支持level的排个序 foreach (ZMBuf::$events as $class_name => $v) { - if ((new $class_name()) instanceof Level) { + if (is_a($class_name, Level::class, true)) { for ($i = 0; $i < count(ZMBuf::$events[$class_name]) - 1; ++$i) { for ($j = 0; $j < count(ZMBuf::$events[$class_name]) - $i - 1; ++$j) { $l1 = ZMBuf::$events[$class_name][$j]->level; @@ -100,8 +126,7 @@ class AnnotationParser } } - private static function getRuleCallback($rule_str) - { + private static function getRuleCallback($rule_str) { $func = null; $rule = $rule_str; if ($rule != "") { @@ -179,23 +204,20 @@ class AnnotationParser return $func; } - private static function registerRuleEvent(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) - { + private static function registerRuleEvent(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) { $vss->callback = self::getRuleCallback($vss->getRule()); $vss->method = $method->getName(); $vss->class = $class->getName(); return $vss; } - private static function registerMethod(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) - { + private static function registerMethod(?AnnotationBase $vss, ReflectionMethod $method, ReflectionClass $class) { $vss->method = $method->getName(); $vss->class = $class->getName(); return $vss; } - private static function registerRequestMapping(RequestMapping $vss, ReflectionMethod $method, ReflectionClass $class, string $prefix) - { + private static function registerRequestMapping(RequestMapping $vss, ReflectionMethod $method, ReflectionClass $class, string $prefix) { $array = ZMBuf::$req_mapping; $uid = count($array); $prefix_exp = explode("/", $prefix); @@ -263,8 +285,7 @@ class AnnotationParser ZMBuf::$req_mapping = $array; } - private static function loadAnnotationClasses() - { + private static function loadAnnotationClasses() { $class = getAllClasses(WORKING_DIR . "/src/ZM/Annotation/", "ZM\\Annotation"); foreach ($class as $v) { $s = WORKING_DIR . '/src/' . str_replace("\\", "/", $v) . ".php"; @@ -277,8 +298,7 @@ class AnnotationParser } } - public static function genTree($items) - { + public static function genTree($items) { $tree = array(); foreach ($items as $item) if (isset($items[$item['pid']])) diff --git a/src/ZM/Annotation/Http/After.php b/src/ZM/Annotation/Http/After.php new file mode 100644 index 00000000..ef24db54 --- /dev/null +++ b/src/ZM/Annotation/Http/After.php @@ -0,0 +1,19 @@ +response = $response; } + /** + * @return $this|SwooleEvent + * @throws Exception + */ public function onActivate() { ZMUtil::checkWait(); foreach (ZMBuf::globals("http_header") as $k => $v) { @@ -82,14 +89,44 @@ class RequestEvent implements SwooleEvent if (in_array(strtoupper($this->request->server["request_method"]), $node["request_method"] ?? [])) { //判断目标方法在不在里面 $c_name = $node["class"]; - /** @var ModBase $class */ - $class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST); - $r = call_user_func_array([$class, $node["method"]], [$params]); - if (is_string($r) && !$this->response->isEnd()) $this->response->end($r); - if ($class->block_continue) return $this; - if ($this->response->isEnd()) return $this; + if (isset(ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]])) { + $middleware = ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]]; + $middleware = ZMBuf::$events[MiddlewareClass::class][$middleware]; + $before = $middleware["class"]; + $r = new $before(); + $before_result = true; + if (isset($middleware["before"])) { + $before_result = call_user_func([$r, $middleware["before"]], $this->request, $this->response, $params); + if ($before_result !== false) $before_result = true; + } + if ($before_result) { + try { + /** @var ModBase $class */ + $class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST); + $result = call_user_func_array([$class, $node["method"]], [$params]); + if (is_string($result) && !$this->response->isEnd()) $this->response->end($result); + if (!$this->response->isEnd()) goto eventCall; + } catch (Exception $e) { + if (!isset($middleware["exception"])) throw $e; + if ($e instanceof $middleware["exception"]) { + call_user_func([$r, $middleware["exception_method"]], $e, $this->request, $this->response, $params); + return $this; + } else throw $e; + } + } + if (isset($middleware["after"])) { + call_user_func([$r, $middleware["after"]], $this->request, $this->response, $params); + return $this; + } + } else { + /** @var ModBase $class */ + $class = new $c_name(["request" => $this->request, "response" => $this->response, "params" => $params], ModHandleType::SWOOLE_REQUEST); + $r = call_user_func_array([$class, $node["method"]], [$params]); + if (is_string($r) && !$this->response->isEnd()) $this->response->end($r); + if (!$this->response->isEnd()) goto eventCall; + } } - + eventCall: foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) { if (strtolower($v->type) == "request" && $this->parseSwooleRule($v)) { $c = $v->class; @@ -127,7 +164,7 @@ class RequestEvent implements SwooleEvent } private function parseSwooleRule($v) { - switch (explode(":",$v->rule)[0]) { + switch (explode(":", $v->rule)[0]) { case "containsGet": case "containsPost": if ($v->callback instanceof Closure) return call_user_func($v->callback, $this->request); diff --git a/src/ZM/Http/MiddlewareInterface.php b/src/ZM/Http/MiddlewareInterface.php new file mode 100644 index 00000000..f8635563 --- /dev/null +++ b/src/ZM/Http/MiddlewareInterface.php @@ -0,0 +1,10 @@ +