转载自如初博客:https://www.ziruchu.com/art/620
中间件原理
中间件的本质是一个 洋葱模型 。主要用于从 请求(Request) 到 响应(Response) 的整个流程,使数组的流动按照我们遇定的方式进行。
图中的顺序为按照 Middleware 1 -> Middleware 2 -> Middleware 3 的顺序组织着,我们可以注意到当中间的横线穿过 内核 即 Middleware 3 后,又回到了 Middleware 2,为一个嵌套模型,那么实际的顺序其实就是: Request -> Middleware 1 -> Middleware 2 -> Middleware 3 -> Middleware 2 -> Middleware 1 -> Response
重点放在 核心 即 Middleware 3,它是洋葱的分界点,分界点前面的部分其实都是基于 请求(Request) 进行处理,而经过了分界点时,内核 就产出了 响应(Response) 对象,也是 内核 的主要代码目标,在之后便是对 响应(Response) 进行处理了,内核 通常是由框架负责实现的,而其它的就由您来编排了。
从这个过程来看,其实有点像冒泡,把它当作冒泡来理解可能还简单些。
中间件类型
Hyperf 中,有全局中间件、局部中间件、方法级别的中间件。如果都定义了这些中间件,执行顺序为:全局中间件 -> 类级别中间件 -> 方法级别中间件。
全局中间件的使用
第一步:创建一个全局中间件
<?php
// App\Middleware\Api\ApiMiddleware.php
namespace App\Middleware\Api;
use PhpParser\Node\Stmt\Return_;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Hyperf\HttpServer\Contract\RequestInterface;
class ApiMiddleware implements MiddlewareInterface
{
public function __construct(
protected ContainerInterface $container,
protected \Hyperf\HttpServer\Contract\ResponseInterface $response,
protected RequestInterface $request
)
{
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
echo '全局中间间' . PHP_EOL;
// 业务逻辑处理
// $response = $handler->handle($request);
// 中间位置也可以处理
// return $response
return $handler->handle($request);
}
}
第二步:注册全局中间件
<?php
// config/autoload/middlewares.php
declare(strict_types=1);
return [
'http' => [
\App\Middleware\Api\ApiMiddleware::class
],
];
这样,中间件就定义完成了,
局部中间件的使用
方式一:路由中使用中间件
第一步:创建一个控制器
<?php
// App\Controller\Test\TestController.php
namespace App\Controller\Test;
class TestController
{
public function index()
{
echo 'Test 控制器' . PHP_EOL;
return 'test';
}
}
第二步:定义路由
Router::get('/test', [\App\Controller\Test\TestController::class, 'index'], ['middleware'=>[\App\Middleware\Api\RouterMiddleware::class]]);
方式二:通过注解使用中间件
<?php
// App\Controller\Test\PostController.php
namespace App\Controller\Test;
use App\Middleware\Api\PostMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
#[AutoController]
#[Middleware(PostMiddleware::class)]
class PostController
{
public function index()
{
echo 'Post 控制器' . PHP_EOL;
return 'post index';
}
}
方式三:通过注解方式定义方法界别的中间件
<?php
// App\Controller\Test\VideoController.php
namespace App\Controller\Test;
use App\Middleware\Api\VideoMiddleware;
use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Annotation\Middleware;
#[AutoController]
class VideoController
{
#[Middleware(VideoMiddleware::class)]
public function index()
{
echo 'Video 控制器' . PHP_EOL;
return 'Video 控制器';
}
public function show()
{
return 'show';
}
}