zoukankan      html  css  js  c++  java
  • illuminate/routing 源码分析之注册路由

    我们知道,在 Laravel 世界里,外界传进来一个 Request 时,会被 Kernel 处理并返回给外界一个 Response。Kernel 在处理 Request 时,会调用 illuminate/routing 包提供的路由功能,来根据当前的 Request,转发到对应的执行逻辑(执行逻辑的形式可以为 Closure 或 Controller@Action)。同时,在进入执行逻辑之前和之后,还会依次进入 Middlewares 的前置和后置处理。所以,一个 Request 由 Kernel 处理为一个 Response 的一个生命周期图如下:

    根据上面的流程,理解路由系统的内部工作原理是非常重要的!当然,它也是非常复杂的。想要深入理解一个工具的使用,学习它的内部设计原理才是画龙点睛。在理解 illuminate/routing 如何工作之前,先设想如何去设计一个路由系统呢?一起想个三分钟吧。

    • 注册路由 :想想一个 Request 进入程序时,携带的请求信息类似为 GET https://localhost/api/v2/peop...,所以我们需要定义一个 Route 对象来表示这个信息,同时还得定义 RouteCollection(Route 的集合)来添加、获取和匹配出一个 Route。程序启动时,开发者定义的所有路由(Route)列表都会被注册到 RouteCollection 内。
    • 查找路由 :有了整个程序的路由列表,这样当一个 Request 进来时,再根据当前 Request 的信息匹配出一个合适的 Route,所以可以设计一个类似 RouterManager 对象,作用类似开发经理 Manager 的总体统筹,来调用 $router->findRoute($request): Route 匹配出合适的 Route。
    • 运行路由 :既然匹配出了对应 Route,那可以调用 RouterManager->runRoute($route): Response 得到对应的 Response 返回给外界。

    所以,如果自己去设计一个路由系统,就可以按照上面三步去做,思路也很好理解。实际上,Laravel 的路由模块 illuminate/routing 也是按照这三个步骤来设计的。本文将会源码分析下 Laravel 是如何把开发者在 routes/*.php 中写的路由列表注册到 RouteCollection 对象内的。

    我们知道,Laravel 在启动时第一步会去实例化 IlluminateFoundationApplication 对象,这个容器对象会去调用 IlluminateRoutingRoutingServiceProvider::register() 往容器对象的 $bindings 数组属性key-value 形式注册进来,注册的对象主要包括 Router(就是上文的 RouterManager 角色,把它比作为开发小组的开发经理角色)等。

    然后会去调用 AppProvidersRouteServiceProvider::boot() 方法默认加载 routes/api.php 和 routes/web.php 文件中注册的路由列表,并且以 Facade 模式去注册路由列表:

    
    Route::prefix($prefix)->middleware($middleware)->group('xxx/web.php');
    

    实际上就是调用 IlluminateRoutingRouteRegistrar 类里的 attribute(key, value) 方法以 key-value 形式注册到 attributes 数组属性里。最主要的 group(string) 方法调用的是 Router::group() 方法,然后调用 loadRoutes(routes) 去执行在 routes/api.php 和 routes/web.php 文件中定义的路由。对于每一种方法(如 GET、POST 等等方法)的路由,Router 对象内都有对应的方法来添加 Route 注册到 RouteCollection 中,比如常见的 get(uri, action) 方法,就是调用的 RouteCollection::add(route) 方法把 Route 注册到 RouteCollection 中。而 route 的创建,调用的是 Router::createRoute(methods, uri, action),其中由于 $action 可能是 Closure 或者 Controller@Action,如果是 Controller@Action 形式,则需要把字符串切割为数组形式,再传入 Route 类的构造函数里。

    总结下注册路由所需要用到的对象:使用 Route 来表示路由信息,使用 RouteCollection 来表示路由集合列表,并且提供了添加删除方法来把 Route 注册到 RouteCollection 内,而 Router 才是纵览全局的角色,注册路由是通过该对象发起的,它会调用 RouteCollection 去注册路由,路由的元数据信息如路由名称等是用 RouteRegistrar 对象表示。从上文可知道,所有对象中,Router 才是画龙点睛的对象。

    通过以上的分析,就能对 illuminate/routing 路由系统的基本设计越来越清晰。一个 Request 进来后,Application 首先开始启动并按照以上逻辑开始注册路由列表,然后就是根据当前 Request 信息查找对应的 Route 对象。

    那如何根据当前 Request 信息查找出对应的 Route 的呢?见本系列第二篇文章。

    原文地址:https://segmentfault.com/a/1190000015862083

  • 相关阅读:
    Knockout应用开发指南 第八章:简单应用举例(2)
    微软ASP.NET站点部署指南(7):生产环境部署
    Knockout应用开发指南 第七章:Mapping插件
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(6)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(5)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(3)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(9)
    《Microsoft Sql server 2008 Internals》读书笔记第九章Plan Caching and Recompilation(8)
    Microsoft Visual Studio .NET 2003 引导程序插件下载地址(非官方)
    Vs2010在没有安装SQL Server 2005/2008 Express时如何连接MDF数据文件?
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9975548.html
Copyright © 2011-2022 走看看