# http 路由
路由支持注解和配置文件的方式来配置,虽然支持配制文件制定,但是我们强烈建议使用注解方式,因为简单,高效。
## 路由申明
## @RestController()
>[info] 由于路由需要框架启动前就进行解析,所以框架需要扫描标记了@RestController 的类进行注册路由规则。所以您如果没有在类上sh用该注解,以下相关注解均无效。
>[danger] 该注解只能作用域类上。
>[info] 需要设置路由的类,需要申明 `@RestController()` 注解
~~~
/**
* 声明这个类的方法有路由规则呀
* @RestController()
*/
class Index extends GoController {
/**
* 设置一个主页路由
* @GetMapping("/")
* @return string
*/
public function test()
{
return "hello";
}
}
~~~
如果,没有特殊问题,那么打开浏览器 `http://127.0.0.1:8080/` ,应该可以看到 `hello`。
好的,继续往下看。
## 注解方法
`@GetMapping`,顾名思义,只有是`get`请求才会处理,如果非`get`请求,会返回404。下面看下支持其他请求的注解。
| 注解名称 | 注解作用 |可用参数 |
| --- | --- |--- |
| @GetMapping | 申明一个GET路由 | value 自定义路由地址|
| @PostMapping | 申明一个POST路由 | value 自定义路由地址|
| @PutMapping | 申明一个PUT路由 | value 自定义路由地址|
| @DelMapping | 申明一个DELETE路由 | value 自定义路由地址|
| @AnylMapping | 申明一个任意路由(GET,POST,PUT,DELETE,POTIONS,HEAD,TRACE,CONNECT) | value 自定义路由地址|
| @RequestMapping | 申明一个路由 |value 自定义路由地址 , method 自定义请求方法|
框架默认提供了2种方法, 如果支持其他方法,比如PUT,DELETE,只需要添加参数`method`为需要支持的请求类型即可。看一下这个例子。
~~~
/**
* @RequestMapping("/putmethod", method={"put","delete"})
* @return string
*/
public function test5(){
return "hello";
}
~~~
如果没有特殊问题,那么打开浏览器 http://127.0.0.1:8080/putmethod ,应该可以看到 hello。如果没有,检查下是请求方法是否为 `put` 或 `delete` ,可以使用 `postman` 试一试。
~~~
/**
* @RequestMapping(method={"put","delete"})
* @return string
*/
public function test5(){
return "hello";
}
~~~
也可以不指定value,这样路由会直接访问 http://127.0.0.1:8080/test5
## 参数修饰方法
修饰方法的作用是对路由的参数进行一些处理再返回给方法。
>[info] 以下修饰方法不管是GET或者POST,均可使用
| 注解名称 | 注解作用 |
| --- | --- |--- |
| @PathVariable | 获取自定义路由{}部分参数,并导入到方法中(可以申明多个),如果增加参数required=true,获取不到该参数会抛出一个http400的 异常 |
| @RequestParam | 获取路由某个参数,并导入到方法中(可以申明多个)|
| @ResponseBody | 让返回的数据 Content-type 变成 json|
>[danger]
> *
> 参数修饰注释,只能在申明了 *Mapping()注解的方法上使用
> *
### 举个 @PathVariable 例子。
~~~
/**
* post 表单 请求
* @PostMapping("test4/{name}")
* @PathVariable("name", required=true)
* @param $name
* @return string
*/
public function test4($name){
var_dump($name);
return "test444";
}
~~~
访问 http://127.0.0.1:8080/test/hello 。那么`hell`o 就会传递到申明了`@PathVariable("name")`的变量中去,最终test4(`$name`) 被传递了 hello。如果没有传递{name},则会抛出 http 400 的异常。
~~~
/**
* post 表单 请求
* @PostMapping("test5[/{name}]")
* @PathVariable("name")
* @param $name
* @return string
*/
public function test5($name){
var_dump($name);
return "test444";
}
~~~
访问 http://127.0.0.1:8080/test5 , {name} 由于是可选的,所以会返回null。
### 举个@RequestParam 例子
~~~
/**
* get请求
* @GetMapping("test/{name2}/{name3}")
* @PathVariable("name2")
* @PathVariable("name3")
* @RequestParam("id")
* @param $name2
* @param $name2
* @param $id
* @return string
*/
public function test($name2, $name3, $id)
{
var_dump($name2, $name3, $id);
return "test222";
}
~~~
访问 http://127.0.0.1:8080/test/hello/world?id=99 。那么`hello`会传递到 `$name2`变量,`world`会传递到`$name3`的变量中,`99`被传递到了`$id`中。
>[info] RequestParam 还支持 required 参数,如果设置为true,那么当该参数不存在时会抛出异常
## POST修饰方法
POST修饰方法帮助我们在接收到参数的时候进行一次解析。
>[info] 以下修饰方法仅限在POST,PUT下使用。
| 注解名称 | 注解作用 |
| --- | --- |--- |
| @RequestBody | 从原始请求raw中解析json字符串,并转为数组。如果解析失败抛出异常。 |
| @RequestRawJson | 同上|
| @RequestRaw | 直接获取post的未编码raw数据|
| @RequestRawXml | 从从原始请求raw中解析xml字符串,并转为数组。如果解析失败抛出异常。|
| @ModelAttribute | 获获取POST数据,导入给model对象,或传给一个数组。|
| @RequestFormData | 获获取POST数据的一个参数,传给一个参数。|
>[danger]
> *
> POST修饰注释,只能在申明了 PostMapping()注解的方法上使用
> *
###** @RequestBody**
`POST`一个`raw`的 json 数据。`$body`收到的就为转化成数组的表单数据。
~~~
/**
* @PostMapping()
* @RequestBody("body")
* @ModelAttribute("model")
*/
public function test8($body){
print_r($body);
return 'test8';
}
~~~
### **@RequestRaw**
`POST`一个 raw数据,`$raw`收到的就为原始表单数据。
~~~
/**
* @PostMapping("test6/{name}")
* @RequestRaw("raw")
* @param $name
* @param $raw
* @return string
*/
public function test6($name,$raw){
var_dump($name, $raw);
return "test6";
}
~~~
### **@RequestRawXml**
`POST`一个xml raw,那么`$test`收到的就为转换成数组后的表单数据。
~~~
/**
* @PostMapping()
* @RequestRawXml("test")
* @param $name
* @param $test
* @return string
*/
public function test7($name, $test){
var_dump($test);
return 'test7';
}
~~~
### **@ModelAttribute**
>[danger] 如果使用 RequestBody,RequestRaw* 相关方法,则该注解不可用。
`POST`一个表单数据(form-data或www-form-urnecoded),testForm 类型的 $test 变量会被填充数据。
如果传递page=1,对象的属性就会被自动覆盖。如果不给变量传递类型,则该变量拿到post所有数据。
~~~
/**
* post 表单 请求
* @PostMapping("test3/{name}")
* @PathVariable("name")
* @ModelAttribute("test")
* @param $name
* @param $test
* @return string
* 实际上是 获取整个post表单的数据 到声明的变量里
*/
public function test3($name, testForm $test)
{
print_r($this->request->post());
var_dump($name, $test);
return "test444";
}
class testForm {
public $page = 1;
public $test = 0;
}
~~~
### RequestFormData
将表单的一个参数填充到类方法的变量中。
POST hhh=123,则 `$hhh` 为 123
~~~
/**
* post 表单 请求
* @PostMapping("test4/{name}")
* @PathVariable("name")
* @RequestFormData("hhh")
* @param $name
* @param $test
* @return string
* 知己上只能获取声明的字段
*/
public function test4($name, $hhh){
var_dump($name, $hhh);
return "test444";
}
~~~
## 路由分组
通过给 @RestController 指定默认参数,来设置路由分组,设置后该类下的*Mapping都会应用该前缀。
~~~
/**
* @RestController("Index")
* Class TestController
* @package ESD\Plugins\EasyRoute
*/
class Index extends GoController {
...
~~~
如果设置为如下案例 GetMapping("/"),那么该方法的路由为 http://127.0.0.1:8080/Index
~~~
/**
* @GetMapping("/")
* @return array
*/
public function http_inject(){
$id = $this->request->getGet('id',5);
return $this->cacheTest($id);
}
~~~
如果设置为如下案例 @GetMapping(),那么该方法的路由为 http://127.0.0.1:8080/Index/task
~~~
/**
* @GetMapping()
*/
public function task(){
$a = new test();
$a->test();
}
~~~
## 路由端口作用域
通过上面的文档,我们知道需要通过 @RestController 注解标记需要解析路由的类,那么该注解,还为我们提供了基于配置文件 esd.port.http.name 的作用域,看一下配置文件。
~~~
esd:
port:
http:
name: http
host: 0.0.0.0
port: 8080
sock_type: 1
open_http_protocol: true
~~~
也就是当前路由绑定在`name`为`http`的8080端口下,并且默认的访问方法为GET,如果您使用了@RequestMapping 但未指定 method 时,该类中的注解均已@RestController的默认方法GET使用。
同时 @RestController 还有几个参数可以配置。
| 参数名称 | 参数作用 |
| --- | --- |--- |
| value | 路由前缀,该参数默认可不写 |
| defaultMethod | 该类下的注解默认方法,默认为GET|
| portTypes | 端口访问类型,http,ws,tcp,udp 默认为 http|
| portNames | 端口名称,默认为配置文件中 esd.port.http.name 的值,如果不指定,会绑定所有端口|
如果您启用了多个端口,比如下面的配置,路由默认会作用在所有端口上。
~~~
esd:
port:
http:
name: http
host: 0.0.0.0
port: 8080
sock_type: 1
open_http_protocol: true
admin:
name: admin
host: 0.0.0.0
port: 8081
sock_type: 1
open_http_protocol: true
~~~
>[warning] 除非您 @RestController 设定参数为 @RestController(portNames={"admin"}),则路由会仅绑定在 8081 端口。
## 路由参数
默认情况下,`*Mapping`使用一种语法,其中`{foo}`指定一个名为`foo`的占位符并匹配正则表达式[^ /] +`。要调整占位符匹配的模式,可以通过编写`{bar:[0-9] +}`来指定自定义模式。一些例子:
~~~
// 匹配 /user/42, 不匹配 /user/xyz
@GetMapping("/user/{id:\d+}")
// 匹配 /user/foobar, 不匹配 /user/foo/bar
@GetMapping("/user/{name}")
// 匹配 /user/foo/bar as well
@GetMapping("/user/{name:.+}")
~~~
路径占位符的自定义模式无法使用捕获组。例如,`{lang:(en|de)}`不是有效的占位符,因为`()`是一个捕获组。相反,你可以使用`{lang:en|de}`或`{lang:(?:en|de)}`。
此外,`[...]`中包含的路径部分被认为是可选的,因此/ foo [bar]将匹配/ foo和/ foobar。可选部件仅支持在尾随位置,而不是在路径中间。
~~~
//比如这条规则
@GetMapping("/user/{id:\d+}[/{name}]")
// 相当于下面两条规则
@GetMapping("/user/{id:\d+}")
@GetMapping("/user/{id:\d+}/{name}")
// 也可以使用多个嵌套的可选部件
@GetMapping("/user[/{id:\d+}[/{name}]]")
// 此路由无效,因为可选部件只能在最后发生
@GetMapping("/user[/{id:\d+}]/{name}")
~~~
## 异常处理
路由如果没有匹配到任何页面,会调用配置 error_controller_name 指定的异常处理类,默认throw RouteException,如果需要自定义,则手动指定error_controller_name参数。
## 手动配置
通过如下配置文件,可以手动指定路由规则,**由于手动配置比较繁琐**,**建议使用注解路由**形式。
~~~
route:
error_controller_name: ESD\Plugins\EasyRoute\NormalErrorController
route_roles:
get_/:
name: get_/
route: /
controller: app\Controller\Route
method: test0
type: get
port_types:
- http
get_/_index/testpost:
name: get_/Index/testpost
route: /Index/testpost
controller: app\Controller\Index
method: testpost
type: get
port_types:
- http
~~~
- 前言
- 捐赠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插件