# 路由
涉及到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插件