easyswoole2.X源码解读-Dispatcher

easyswoole2.X源码解读-事件注册EventRegister我们知道,onRequest事件会通过Dispatcher分发到http的控制器

1. \easyswoole\vendor\easyswoole\easyswoole\src\Core\Http\Dispatcher.php

其实开启不同的服务,会调用对应服务的Dispatcher类;

例如socket服务easyswoole\vendor\easyswoole\easyswoole\src\Core\Socket\Dispatcher.php

我们先讨论http服务的Dispatcher类;

2. 在默认注册事件中,

$dispatcher = new Dispatcher($controllerNameSpace);

$request_psr,$response_psr 分别对应easyswoole的request对象和response对象
$dispatcher->dispatch($request_psr,$response_psr);

3.dispatch方法

如果有自定义路由,优先使用自定义的

public function dispatch(Request $request,Response $response):void
    {
        if($this->router === null){
            $router = $this->checkRouter();
            if($router){
                $this->routerMethodNotAllowCallBack = $router->getMethodNotAllowCallBack();
                $this->router = new GroupCountBased($router->getRouteCollector()->getData());
            }else{
                $this->router = false;
            }
        }
        if(!$response->isEndResponse()){
            $this->router($request,$response);
        };

        if(!$response->isEndResponse()){
            $this->controllerHandler($request,$response);
        };
    }

4.Router自定义路由,

先判断 App\HttpController命名空间下是否有Router类,有则返回这个实例;

若需要在EasySwoole使用自定义路由拦截功能,请在应用目录的Http控制器目录下(默认为HttpController)下,建立Router类, 井继承\EasySwoole\Core\Http\AbstractInterface\Router实现register方法

 private function checkRouter():?Router
    {
        $class = $this->controllerNameSpacePrefix.'\\Router';
        if(class_exists($class)){
            $router = new $class;
            if($router instanceof Router){
                return $router;
            }else{
                return null;
            }
        }else{
            return null;
        }
    }

5. 执行对应controller

最终(new $finalClass($actionName,$request,$response)); 通过类的构造方法来执行对应的action;

private function controllerHandler(Request $request,Response $response)
    {
        $pathInfo = ltrim(UrlParser::pathInfo($request->getUri()->getPath()),"/");
        $list = explode("/",$pathInfo);
        $actionName = null;
        $finalClass = null;
        $controlMaxDepth = Di::getInstance()->get(SysConst::HTTP_CONTROLLER_MAX_DEPTH);
        $currentDepth = count($list);
        $maxDepth = $currentDepth < $controlMaxDepth ? $currentDepth : $controlMaxDepth;
        while ($maxDepth >= 0){
            $className = '';
            for ($i=0 ;$i<$maxDepth;$i++){
                $className = $className."\\".ucfirst($list[$i] ?: 'Index');//为一级控制器Index服务
            }
            if(class_exists($this->controllerNameSpacePrefix.$className)){
                //尝试获取该class后的actionName
                $actionName = empty($list[$i]) ? 'index' : $list[$i];
                $finalClass = $this->controllerNameSpacePrefix.$className;
                break;
            }else{
                //尝试搜搜index控制器
                $temp = $className."\\Index";
                if(class_exists($this->controllerNameSpacePrefix.$temp)){
                    $finalClass = $this->controllerNameSpacePrefix.$temp;
                    //尝试获取该class后的actionName
                    $actionName = empty($list[$i]) ? 'index' : $list[$i];
                    break;
                }
            }
            $maxDepth--;
        }
        if(!empty($finalClass)){
            (new $finalClass($actionName,$request,$response));
        }else{
            if(in_array($request->getUri()->getPath(),['/','/index.html'])){
                $content = file_get_contents(__DIR__.'/../../Resource/welcome.html');
            }else{
                $response->withStatus(Status::CODE_NOT_FOUND);
                $content = file_get_contents(__DIR__.'/../../Resource/404.html');
            }
            $response->write($content);
        }
    }

5.1 可以看下controller构造方法

public function __construct(string $actionName,Request $request,Response $response)
    {
        $this->request = $request;
        $this->response = $response;
        $this->actionName = $actionName;
        if($actionName == '__construct'){
            $this->response()->withStatus(Status::CODE_BAD_REQUEST);
        }else{
            $this->__hook( $actionName);
        }
    }

 5.2 所有可以在控制器类添加onRequest($actionName)方法,通过返回bool来限制这个方法是否能够调用

 protected function __hook(?string $actionName):void
    {
        if($this->onRequest($actionName) !== false){
            //支持在子类控制器中以private,protected来修饰某个方法不可见
            try{
                $ref = new \ReflectionClass(static::class);
                if($ref->hasMethod($actionName) && $ref->getMethod( $actionName)->isPublic()){
                    $this->$actionName();
                }else{
                    $this->actionNotFound($actionName);
                }
            }catch (\Throwable $throwable){
                $this->onException($throwable,$actionName);
            }
            //afterAction 始终都会被执行
            try{
                $this->afterAction($actionName);
            }catch (\Throwable $throwable){
                $this->onException($throwable,$actionName);
            }
        }
    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

runtoweb3

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值