Laravel 底层是如何处理 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(); }
转载于:https://www.cnblogs.com/mo3408/p/10979279.html
Laravel 底层是如何处理 HTTP 请求的?相关推荐
- Spring源码分析之SpringMVC的DispatcherServlet是如何处理Http请求的
一般我们会在web.xml文件中配置DispatcherServlet,比如如下配置方式: <servlet><servlet-name>dispatcherServlet&l ...
- ajxs跨域 php_PHP项目中是如何处理Ajax请求与Ajax跨域的
PHP项目中是如何处理Ajax请求与Ajax跨域的 发布时间:2020-12-14 16:35:47 来源:亿速云 阅读:98 这期内容当中小编将会给大家带来有关PHP项目中是如何处理Ajax请求与A ...
- ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?
我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但是就具体的实现来说,由于其中涉及很多对象的交互,我想很少人能够地把它弄清楚.为了让读者 ...
- laravel 只要通过路由去请求数据库就会有延迟
laravel 只要通过路由去请求数据库就会有延迟 laravel 只要通过路由去请求数据库就会有延迟 (大概1秒,本地试过 没有这种问题 Linux cenos6.8 ) 使用Artisan命令行就 ...
- laravel框架中文手册_laravel请求参数校验方法
对于后端开发而言,前端request请求中的参数校验是一个必不可少的环节.无论传来的参数是id还是email还是其他的参数,我们都要对参数的类型.大小.格式等等做这样或者那样的校验,然后才进行逻辑处理 ...
- php如何处理查询请求,PHP如何处理Web请求流程
PHP世界里涌现了很多开发框架,比如Laravel.ThinkPHP等,但不论何总框架,他们在处理Web请求时的模式都是一样的,本文首先阐述PHP开发Web应用的基本架构,然后分别分析Laravel和 ...
- Laravel 接受Ajax的POST请求
Laravel 接受Ajax的请求: Laravel 框架接收Ajax的POST请求很简单,但是有弯路..... 不过 : 这个文章不是初学者看的,至少你们要会创建html界面,创建JS,引用JS库, ...
- php接口增加白名单,使用laravel中间件来添加指定请求的白名单
这件事的需求是这样: 我们使用微信公众平台的开发模式搭建好了一个后台,这样就不得不把运营人员设置的关键词回复加进来.当然我们不希望每次运营人员想修改时,都让我们来直接改代码.于是我就为他们写了个关键词 ...
- 浅析 Laravel 底层原理:契约(Contracts)
简介 Laravel 中的契约是指框架提供的一系列定义核心服务的接口(interface). 例如,Illuminate\Contracts\Queue\Queue 契约定义了队列任务所需的方法,而 ...
最新文章
- python爬虫基础(二)~工具包: 下载包requests、urllib和解析包BeautifulSoup(bs4)、lxml.etree.xpath
- SQL分类:DDL/DML/DQL/DCL以及作用
- ACE-Task结构介绍(二)——消息块ACE_Message_Block结构的分析
- win10中内置的Linux Bash启动闪退问题
- AngularJS 详解Directive(指令)机制
- 第4章 变量、作用域和内存问题
- C++类和new、delete操作符和堆和栈内存的分配
- 安装zsh-autosuggestions zsh-syntax-highlighting
- report machine实现报表分栏
- donet 微服务开发 学习-使用docker部署Asp.net core web应用程序
- D3D9利用顶点缓冲区绘制三角形
- input 获取焦点的情况
- 把VBA转换成JAVA_请教,我用Excel中生成了Java代码,用VBA生成Jav
- RK3328_LPDDR3D178P132SD4_Template_V11_20170726,RK3328模块原理图和PCB
- 手机端网站底部悬浮 广告代码 代关闭_只要是安卓手机就不能少这个APP
- Jenkins+Gitlab+Nginx实现自动发布与回退基于tag版本的静态项目(解决重复构建问题)
- 尚硅谷Java、HTML5前端、全栈式开发视频
- linux如何修改当前时间
- linux系统添加网卡驱动,linux系统怎么安装网卡驱动
- 解决Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com
热门文章
- 2022-2028年中国乳制品行业市场需求预测与投资战略规划分析报告
- Linux shell 学习笔记(5)— 文件权限(添加、修改、删除用户及创建、修改群组)
- 三层交换机原理:02怎么用三层交换机?
- SpringCloud Alibaba微服务实战(五) - Sentinel实现限流熔断
- 完全理解Python迭代对象、迭代器、生成器
- LeetCode简单题之找出数组的最大公约数
- 计图(Jittor) 1.1版本:新增骨干网络、JIT功能升级、支持多卡训练
- 在NVIDIA A100 GPU上利用硬件JPEG解码器和NVIDIA nvJPEG库
- 激光雷达基础-光探测和测距-遥感
- 匹配算法:局部结构保留