URL Router 和 Dispatcher 有啥区别?

Posted

技术标签:

【中文标题】URL Router 和 Dispatcher 有啥区别?【英文标题】:What is the difference between URL Router and Dispatcher?URL Router 和 Dispatcher 有什么区别? 【发布时间】:2012-07-26 21:18:03 【问题描述】:

我想知道URL Router 和Dispatcher 的区别,因为在网上搜索有一些有趣的东西,只是不知道是因为它们相似,还是因为它们的功能颠倒了。谁能告诉我它是什么,每个是什么,以及一个例子?

不知道 URL Router 和 Dispatcher 的区别,他们在网上的内容的问题,有时候看起来 Dispatcher 就是 Router,Router 又像是 Dispatcher,结果不知道各自的权限是什么,每个是什么,以及如何实现每个。

谢谢。

【问题讨论】:

你指的是哪个框架? 其实我问的是笼统的问题,即不是专门的框架,只是URL Router和Dispatcher的功能而已。 【参考方案1】:

框架和库如何解释 Router 和 Dispatcher 的职责将有所不同。我在下面详细说明的是如何解释这两个服务的职责。这并不是说这是解释它的唯一方法或其他解释是错误的。

概念

路由

这有点像在加油站或便利店问路。你正在穿过城镇,你需要弄清楚如何到达最近的酒店。你进去问服务员,他们会指出你正确的方向,或者至少你希望方向是正确的。路由就是这样。请求进入资源,路由器提供请求到达正确资源所需的方向。

在大多数主要框架中,您会将特定的请求 URL 路由到将被调用以完成请求的对象和方法。您经常会看到路由器还从 URL 中解析出动态参数。例如,如果您通过 /users/1234 访问用户,其中 1234 是用户 ID,路由器将解析出 ID 部分并将其作为资源方向的一部分提供。

调度

调度使用来自路由步骤的信息来实际生成资源。如果路由步骤是询问方向,那么调度是遵循这些方向的实际过程。 Dispatching 确切地知道要创建什么以及生成资源所需的步骤,但只有在从 Router 获得指示之后。

实现

这些示例实现故意非常简单和幼稚。如果没有大幅改进,您不会希望在任何类型的生产环境中使用它。

在这个例子中,我们只是路由到一个可调用函数,而不是路由到一个对象和方法。这也表明您不需要 路由到一个对象;只要调度程序可以正确获取正确的资源,您就可以路由到您想要的任何数据。

首先我们需要一些路由反对。让我们创建一个可以匹配的简单 Request 对象。

<?php

class Request 

    private $method;
    private $path;

    function __construct($method, $path) 
        $this->method = $method;
        $this->path = $path;
    

    function getMethod() 
        return $this->method;
    

    function getPath() 
        return $this->path;
    


现在我们可以匹配一些东西了,让我们看看一个简单的路由器实现。

<?php

class Router 

    private $routes = [
        'get' => [],
        'post' => []
    ];

    function get($pattern, callable $handler) 
        $this->routes['get'][$pattern] = $handler;
        return $this;
    

    function post($pattern, callable $handler) 
        $this->routes['post'][$pattern] = $handler;
        return $this;
    

    function match(Request $request) 
        $method = strtolower($request->getMethod());
        if (!isset($this->routes[$method])) 
            return false;
        

        $path = $request->getPath();
        foreach ($this->routes[$method] as $pattern => $handler) 
            if ($pattern === $path) 
                return $handler;
            
        

        return false;
    


现在我们需要一些方法来为给定的请求调用配置的$handler

<?php

class Dispatcher 

    private $router;

    function __construct(Router $router) 
        $this->router = $router;
    

    function handle(Request $request) 
        $handler = $this->router->match($request);
        if (!$handler) 
            echo "Could not find your resource!\n";
            return;
        

        $handler();
    


现在,让我们将它们放在一起,展示如何使用这些简单的实现。

<?php

$router = new Router();
$router->get('foo', function()  echo "GET foo\n"; );
$router->post('bar', function()  echo "POST bar\n"; );

$dispatcher = new Dispatcher($router);

$dispatcher->handle(new Request('GET', 'foo'));
$dispatcher->handle(new Request('POST', 'bar'));
$dispatcher->handle(new Request('GET', 'qux'));

您可以通过查看http://3v4l.org/gbsoJ 来查看此实现的示例。

总结

这个示例实现应该传达路由和调度的概念。实际上,执行这些操作比我的示例要多得多。路由器通常会使用正则表达式来匹配请求,并且在匹配时可能会查看其他请求属性。此外,您将看到一些库使用与路由器交互的解析器,以便您可以传递的不仅仅是可调用函数。基本上,解析器将确保匹配的$handler 可以转换为可调用函数。

此外,您应该考虑使用大量示例和实现。对于我的个人项目,我喜欢 FastRoute 的易用性和性能。但是,几乎所有主要框架都有自己的实现。你也应该检查一下。

【讨论】:

谢谢。你能给我一个代码中的示例实现吗?再次感谢。 解释得很好!! 很好的解释。喜欢这些例子 真的很简单,很有启发性。 @Daniele 你可以让你的 Dispatcher 更加健壮,并且能够执行的不仅仅是简单的匿名函数。想象一下 Dispatcher 可以接受作为构造函数依赖项的 CallableResolver 接口。 CallableResolver 上有一个resolve($routeData) : ?callable 方法,Dispatcher 将解析的路由数据传递给它;它总是返回一个可调用的或空值。 CallableResolverChain 可以循环通过一系列 CallableResolver 直到匹配。【参考方案2】:

Route 是对资源的引用,而 Dispatching 是获取所述资源的操作。

【讨论】:

以上是关于URL Router 和 Dispatcher 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

SpringMVC - dispatcher servler 的 url 模式样式

使用URL dispatcher的范例

分组匹配错误,django url dispatcher

在 Django Url Dispatcher 中获取 http 请求数据?这可能吗?如果是这样,怎么做?

react-router-dom中location.pathname和match.url之间的区别?

react-router中的URL参数问题