Web 做事器对 HTTP 要求的处理流程大体上都是这样的:在某个端口监听要求,要求进入后运行程序,然后将程序运行结果以相应的形式发送出去。基于 Laravel 框架构建的 Web 运用场置 HTTP 要求的流程也是如此。所有 HTTP 要求都会被转发到单入口文件 public/index.php,处理 HTTP 要求的核心代码如下(忽略 HTTP 要求处理之外的代码):$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../')); // 绑定处理 HTTP 要求的接口实现到做事容器$app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class);// 从做事容器中解析处理 HTTP 要求的 Kernel 实例$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);// 处理 HTTP 要求的核心代码$response = $kernel->handle( $request = Illuminate\Http\Request::capture());// 发送相应$response->send();// 终止程序,做一些善后及清理事情$kernel->terminate($request, $response);
在上面这段程序中,首先会创建一个 Application 实例,作为全局的做事容器,然后将处理要求的核心类 Kernel 实现实例绑定到该容器中,以便后续通过它处理 HTTP 要求。我们通过做事器捕获要求并将其通报给 Kernel 实例进行处理,处理结果是准备好的相应实例,调用该相应实例的 send() 方法即可将其发送给发起要求的客户端。末了,我们实行 Kernel 实例上的 terminate() 终止程序,退出脚本。
以上便是 Laravel 框架处理 HTTP 要求的一样平常流程,所有核心逻辑都位于 $kernel->handle() 方法调用中。下面我们就来一探究竟。
做事容器
Laravel 框架供应了一个功能强大的做事容器,用于管理类之间的依赖关系,关于其底层事理还可以参考学徒到工匠系列中的先容,这里我们就不深入展开了。做事容器封装了绑定到某个接口的对应实现类的实例化过程,你可以在须要对应实现实例的时候通过接口从容器中获取。
在上面的代码中,$app 对应的便是做事容器实例,并且在我们获取到该实例后就注册了 Kernel 接口及实在现类到容器中:
$app->singleton( Illuminate\Contracts\Http\Kernel::class, App\Http\Kernel::class);
singleton 方法会以单例办法在做事容器中将 App\Http\Kernel 实例绑定到 Illuminate\Contracts\Http\Kernel 接口,后续我们要获取 App\Http\Kernel 实例,就可以通过 Illuminate\Contracts\Http\Kernel 接口从做事容器中获取,获取方法是 $app->make():
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
回到 Kernel
下面我们就正式进入 $kernel->handle() 方法内部看看 HTTP 要求是被如何处理的。打开 Illuminate\Foundation\Http\Kernel (App\Http\Kernel 的父类),查看 handle 方法,可以看到核心处理逻辑通过 sendRequestThroughRouter 方法实现:
protected function sendRequestThroughRouter($request){ $this->app->instance('request', $request); Facade::clearResolvedInstance('request'); $this->bootstrap(); return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter());}
在发送要求到路由之前,先调用 bootstrap() 方法利用运用的启动类:
protected $bootstrappers = [
\Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class, \Illuminate\Foundation\Bootstrap\LoadConfiguration::class, \Illuminate\Foundation\Bootstrap\HandleExceptions::class, \Illuminate\Foundation\Bootstrap\RegisterFacades::class, \Illuminate\Foundation\Bootstrap\RegisterProviders::class, \Illuminate\Foundation\Bootstrap\BootProviders::class,];
这些个启动类在路由解析之前实行,相称于对全体运用进行初始化。通过类名就能窥伺出对应的操作意图,分别是加载环境变量和全局配置、配置非常处理逻辑、注册门面和做事供应者(根据 config/app.php 中的 providers 和 alias配置值)、以及实行所有已注册做事供应者的 boot 方法,详细的实现逻辑我这里就不一一展开的,你可以自己去看下。
然后便是真正的 HTTP 要求处理了:
return (new Pipeline($this->app)) ->send($request) ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware) ->then($this->dispatchToRouter());
Laravel 框架以管道模式来处理 HTTP 要求,首先通过全局中间件对要求进行处理,如果返回 false 直接退出,不会做路由解析处理。
全局中间件都校验通过才会将要求分发到路由器进行处理,路由器会将要求 URL 路径与运用注册的所有路由进行匹配,如果有匹配的路由,则先网络该路由所分配的所有路由中间件,通过这些路由中间件对要求进行过滤,所有路由中间件校验通过才会运行对应的匿名函数或掌握器方法,实行相应的要求处理逻辑,末了准备好待发送给客户真个相应。
终止 Kernel
相应准备就绪后,就会通过 $response->send() 发送给发起要求的客户端,之后还要运行 $kernel->terminate() 做一些善后清理事情,并终极退出脚本。这些善后清理事情紧张包括运行终止中间件,以及注册到做事容器的一些终止回调:
public function terminate($request, $response){ $this->terminateMiddleware($request, $response); $this->app->terminate();}
好了,关于 Laravel 框架底层对 HTTP 要求的处理逻辑就先容到这里,希望看完这些,你能对 Laravel 要求的生命周期有一个更加清晰的认知。
点击理解更多去学习:非常利用的代码优化,怎么才能写好代码