基于 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();
}

转载于:https://www.cnblogs.com/mo3408/p/10979279.html

Laravel 底层是如何处理 HTTP 请求的?相关推荐

  1. Spring源码分析之SpringMVC的DispatcherServlet是如何处理Http请求的

    一般我们会在web.xml文件中配置DispatcherServlet,比如如下配置方式: <servlet><servlet-name>dispatcherServlet&l ...

  2. ajxs跨域 php_PHP项目中是如何处理Ajax请求与Ajax跨域的

    PHP项目中是如何处理Ajax请求与Ajax跨域的 发布时间:2020-12-14 16:35:47 来源:亿速云 阅读:98 这期内容当中小编将会给大家带来有关PHP项目中是如何处理Ajax请求与A ...

  3. ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?

    我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但是就具体的实现来说,由于其中涉及很多对象的交互,我想很少人能够地把它弄清楚.为了让读者 ...

  4. laravel 只要通过路由去请求数据库就会有延迟

    laravel 只要通过路由去请求数据库就会有延迟 laravel 只要通过路由去请求数据库就会有延迟 (大概1秒,本地试过 没有这种问题 Linux cenos6.8 ) 使用Artisan命令行就 ...

  5. laravel框架中文手册_laravel请求参数校验方法

    对于后端开发而言,前端request请求中的参数校验是一个必不可少的环节.无论传来的参数是id还是email还是其他的参数,我们都要对参数的类型.大小.格式等等做这样或者那样的校验,然后才进行逻辑处理 ...

  6. php如何处理查询请求,PHP如何处理Web请求流程

    PHP世界里涌现了很多开发框架,比如Laravel.ThinkPHP等,但不论何总框架,他们在处理Web请求时的模式都是一样的,本文首先阐述PHP开发Web应用的基本架构,然后分别分析Laravel和 ...

  7. Laravel 接受Ajax的POST请求

    Laravel 接受Ajax的请求: Laravel 框架接收Ajax的POST请求很简单,但是有弯路..... 不过 : 这个文章不是初学者看的,至少你们要会创建html界面,创建JS,引用JS库, ...

  8. php接口增加白名单,使用laravel中间件来添加指定请求的白名单

    这件事的需求是这样: 我们使用微信公众平台的开发模式搭建好了一个后台,这样就不得不把运营人员设置的关键词回复加进来.当然我们不希望每次运营人员想修改时,都让我们来直接改代码.于是我就为他们写了个关键词 ...

  9. 浅析 Laravel 底层原理:契约(Contracts)

    简介 Laravel 中的契约是指框架提供的一系列定义核心服务的接口(interface). 例如,Illuminate\Contracts\Queue\Queue 契约定义了队列任务所需的方法,而 ...

最新文章

  1. python爬虫基础(二)~工具包: 下载包requests、urllib和解析包BeautifulSoup(bs4)、lxml.etree.xpath
  2. SQL分类:DDL/DML/DQL/DCL以及作用
  3. ACE-Task结构介绍(二)——消息块ACE_Message_Block结构的分析
  4. win10中内置的Linux Bash启动闪退问题
  5. AngularJS 详解Directive(指令)机制
  6. 第4章 变量、作用域和内存问题
  7. C++类和new、delete操作符和堆和栈内存的分配
  8. 安装zsh-autosuggestions zsh-syntax-highlighting
  9. report machine实现报表分栏
  10. donet 微服务开发 学习-使用docker部署Asp.net core web应用程序
  11. D3D9利用顶点缓冲区绘制三角形
  12. input 获取焦点的情况
  13. 把VBA转换成JAVA_请教,我用Excel中生成了Java代码,用VBA生成Jav
  14. RK3328_LPDDR3D178P132SD4_Template_V11_20170726,RK3328模块原理图和PCB
  15. 手机端网站底部悬浮 广告代码 代关闭_只要是安卓手机就不能少这个APP
  16. Jenkins+Gitlab+Nginx实现自动发布与回退基于tag版本的静态项目(解决重复构建问题)
  17. 尚硅谷Java、HTML5前端、全栈式开发视频
  18. linux如何修改当前时间
  19. linux系统添加网卡驱动,linux系统怎么安装网卡驱动
  20. 解决Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com

热门文章

  1. 2022-2028年中国乳制品行业市场需求预测与投资战略规划分析报告
  2. Linux shell 学习笔记(5)— 文件权限(添加、修改、删除用户及创建、修改群组)
  3. 三层交换机原理:02怎么用三层交换机?
  4. SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断
  5. 完全理解Python迭代对象、迭代器、生成器
  6. LeetCode简单题之找出数组的最大公约数
  7. 计图(Jittor) 1.1版本:新增骨干网络、JIT功能升级、支持多卡训练
  8. 在NVIDIA A100 GPU上利用硬件JPEG解码器和NVIDIA nvJPEG库
  9. 激光雷达基础-光探测和测距-遥感
  10. 匹配算法:局部结构保留