🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 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 ~~~