# 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插件