# 路由
涉及到ClientData,PackTool,RouteTool
# ClientData
ClientData是ESD抽象出來的請求模型,這個模型針對任何協議。也就是說無論是TCP,HTTP,WS等等,所有的請求都必須封裝成ClientData。
~~~
/**
* @var string
*/
protected $controllerName;
/**
* @var string
*/
protected $requestMethod;
/**
* @var string
*/
protected $methodName;
/**
* @var ClientInfo
*/
protected $clientInfo;
/**
* @var Request
*/
protected $request;
/**
* @var Response
*/
protected $response;
/**
* @var int
*/
protected $fd;
/**
* @var string
*/
protected $path;
/**
* @var array
*/
protected $params;
/**
* @var array
*/
protected $data;
/**
* @var mixed
*/
protected $responseRaw;
~~~
其中比較重要的是
* controllerName 路由到的Controller類名
* methodName 理由到的方法名
* path 請求路徑(無論什么協議都得有請求路徑,即使是虛擬的)
* params 訪問方法時的參數
* data 數據內容
* requestMethod 請求方法,那么相對Http來說就是get,post之類的
還有些其他的方法一般是特定專用的。
# PackTool
PackTool是協議自動解包/壓包工具,目前提供的有NonJsonPack,LenJsonPack,EofJsonPack,具體的看代碼不一一介紹了。
上面說的ClientData是路由的關鍵信息,那么PackTool就是用來生成ClientData的。
這里以NonJsonPack為例,這個提供了WS下無包頭的json解析。
由于Websocket有自己的協議格式所以我們不需要定義包頭,我們來看看NonJsonPack。
~~~
public function encode(string $buffer)
{
return;
}
public function decode(string $buffer)
{
return;
}
~~~
encode和decode是解析包頭的,這里不需要直接返回。
~~~
/**
* @param $data
* @param PortConfig $portConfig
* @param string|null $topic
* @return false|string
*/
public function pack($data, PortConfig $portConfig, ?string $topic = null)
{
return json_encode($data, JSON_UNESCAPED_UNICODE);
}
/**
* @param int $fd
* @param string $data
* @param PortConfig $portConfig
* @return ClientData
* @throws \ESD\Core\Plugins\Config\ConfigException
*/
public function unPack(int $fd, string $data, PortConfig $portConfig): ?ClientData
{
$value = json_decode($data, true);
if (empty($value)) {
$this->warn('json unPack 失敗');
return null;
}
$clientData = new ClientData($fd, $portConfig->getBaseType(), $value['p'], $value);
return $clientData;
}
~~~
pack就是一個json打包的過程。
unpack是解包生成ClientData的過程,ClientData的構造方法如下:
~~~
public function __construct($fd, $requestMethod, $path, $data)
~~~
可以看出path源自請求時的json對象中的p字段。
# RouteTool
接下來就到了RouteTool了,默認框架是AnnotationRoute,其實里面是用FastRoute實現的。
那么剛才我們設置的ClientData的path字段在這里就要發揮作用了。
你可以把path當做http的url比如“test/abc”,這樣其實更好理解,那么下一步就是寫對應的Controller了,基本上和Http是一樣的。找到路由后,會自動設置ClientData的ControllerName和MethodName。
~~~
case Dispatcher::FOUND: // 找到對應的方法
$handler = $routeInfo[1]; // 獲得處理函數
$vars = $routeInfo[2]; // 獲取請求參數
$this->clientData->setControllerName($handler[0]->name);
$this->clientData->setMethodName($handler[1]->name);
~~~
關于WS的Controller怎么寫,看下面的例子:
~~~
/**
* @WsController()
* Class CUser
* @package ESD\Examples\Controller
*/
class WebSocket extends GoController
{
/**
* RequestMapping()
* @return string
*/
public function wsBindUid()
{
$this->bindUid($this->clientData->getFd(), "test1");
return "test";
}
/**
* @RequestMapping()
* @return mixed|null
*/
public function wsGetUid()
{
return $this->getFdUid($this->clientData->getFd());
}
/**
* @RequestMapping()
*/
public function send()
{
$this->sendToUid("test1", "hello");
}
/**
* @RequestMapping()
* @throws \ESD\Plugins\ProcessRPC\ProcessRPCException
*/
public function wsAddSub()
{
$this->addSub("sub", $this->getUid());
}
/**
* @RequestMapping()
* @throws \ESD\Plugins\ProcessRPC\ProcessRPCException
*/
public function wsPub()
{
$this->pub("sub", "sub");
}
}
~~~
和Http的區別在于注解使用了@WsController而不是@RestController,相對的方法上的注解使用了@RequestMapping。
下面是ws對應的請求json:
```json
{"p":"send","xxx":"xxx"}
```
# 總結
PackTool -> ClientData -> RouteTool
HTTP是不需要PackTool的,因為Swoole幫我們解析成了Request和Response。
- 前言
- 捐贈ESD項目
- 使用篇-通用
- 環境
- 安裝
- 規范
- 壓力測試
- 配置
- 如何設置YML配置
- server配置
- 端口配置
- 項目結構
- 事件派發
- 日志
- 注解
- DI容器
- 自定義進程
- 并發及協程池
- Console插件
- Scheduled插件
- Redis插件
- AOP插件
- Saber插件
- Mysql插件
- mysql事務
- Actuator插件
- Whoops插件
- Cache插件
- PHPUnit插件
- Security插件
- Session插件
- EasyRoute插件
- http路由
- ProcessRpc插件
- AutoReload插件
- AnnotationsScan插件
- Tracing-plugin插件
- MQTT插件
- Pack插件
- AMQP插件
- Validate插件
- Uid插件
- Topic插件
- Blade插件
- CsvReader插件
- hashed-wheel-timer-plugin插件
- 使用篇-HTTP
- 路由
- 靜態文件
- 路由定義
- 修飾方法
- 路由分組
- 資源路由
- 端口作用域
- 異常處理
- 跨域請求
- 路由緩存
- 控制器
- 控制器初始化
- 前置操作
- 跳轉和重定向
- 異常處理
- 請求
- 請求對象
- 請求信息
- request消息
- response消息
- stream消息
- url接口
- 驗證器
- 內置驗證器
- 內置過濾器
- 使用篇-WS
- 如何使用
- 路由
- 使用篇-TCP
- 插件篇-PluginSystem
- 微服務篇-ESDCloud
- CircuitBreaker插件
- SaberCloud插件
- 分布式鏈路追蹤系統
- Consul插件