文档站点
Skip to content

路由 ​

Laravel 把路由写在 routes/web.php 和 routes/api.php;Spring Boot 没有路由文件 —— 路由直接用注解写在控制器方法上。声明即注册,看到方法就知道它的 URL。

基本路由:@GetMapping 等 ​

php
// Laravel
Route::get('/posts', [PostController::class, 'index']);
java
// Spring Boot
@RestController
public class PostController {

    @GetMapping("/posts")
    public List<Post> index() {
        return ...;
    }
}

四种 HTTP 动词对应四个注解:

LaravelSpring Boot
Route::get@GetMapping
Route::post@PostMapping
Route::put@PutMapping
Route::delete@DeleteMapping
Route::patch@PatchMapping
Route::any / Route::match@RequestMapping(method = {GET, POST})

@RequestMapping 是最底层的,其他都是它的简写:

java
@RequestMapping(value = "/posts", method = RequestMethod.GET)
// 等价于 @GetMapping("/posts")

类上也可以加前缀

@RequestMapping 加在类上,就相当于 Laravel 的 Route::prefix('posts')->group(...):

java
@RestController
@RequestMapping("/posts")
public class PostController {

    @GetMapping("/{id}")   // 实际路径 /posts/{id}
    public Post show(@PathVariable Long id) { ... }
}

路径参数:{id} → @PathVariable ​

php
// Laravel
Route::get('/posts/{post}', [PostController::class, 'show']);

// 控制器
public function show(Post $post) { ... }
java
@GetMapping("/posts/{id}")
public Post show(@PathVariable Long id) { ... }

多个参数、正则约束:

java
@GetMapping("/posts/{id}/comments/{commentId}")
public Comment show(@PathVariable Long id,
                    @PathVariable Long commentId) { ... }
功能LaravelSpring Boot
单参数{post} + $post{id} + @PathVariable Long id
默认值路由参数必须有值同左
正则约束where('id', '[0-9]+')一般不校验格式,交给类型转换(Long id 自动强转)

类型转换

Laravel 里参数是字符串,靠 where 或模型绑定约束;Spring 里 @PathVariable Long id 的 Long 会自动做类型转换,URL 传非数字会抛类型异常(会被 异常处理 兜住)。

查询参数:?page=2 → @RequestParam ​

php
// Laravel
Route::get('/posts', [PostController::class, 'index']);
// 控制器里 $request->query('page', 1)
java
@GetMapping("/posts")
public List<Post> index(@RequestParam(defaultValue = "1") int page,
                        @RequestParam(required = false) String keyword) {
    ...
}
场景写法
必填参数@RequestParam Long id(缺了就 400)
可选参数@RequestParam(required = false) String keyword
带默认值@RequestParam(defaultValue = "1") int page
一次拿全部@RequestParam Map<String, String> params

对比

Laravel 里所有查询参数都从 $request 拿;Spring 里直接声明方法参数,框架自动解析填充 —— 这就是「参数绑定」,写起来更短,签名即文档。

统一前缀与版本化 ​

全局前缀(类似 Laravel Route::prefix('api')) ​

yaml
server:
  servlet:
    context-path: /api

所有路由自动带上 /api 前缀,相当于 Laravel 的 api.php 路由文件。

按模块分组前缀 ​

java
@RestController
@RequestMapping("/api/v1/posts")
public class PostController { ... }

控制器动态注册:RouterFunction ​

大多数项目用注解就够了,但知道有「编程式」的写法可以避免误解(对应 Laravel 的闭包路由):

java
@Configuration
public class RouterConfig {
    @Bean
    public RouterFunction<ServerResponse> routes() {
        return route()
            .GET("/health", req -> ServerResponse.ok().body("ok"))
            .build();
    }
}

路由相关常用技巧 ​

需求写法
多方法处理一个 URL@GetMapping + @PostMapping 标在类上,或 @RequestMapping
通配符@GetMapping("/files/**")(** 匹配多级路径)
跳转返回 ResponseEntity 或 redirect: 前缀视图
全局路由不存在处理全局异常处理兜 404(见 异常处理)

没有 REST 资源路由

Laravel 有 Route::resource() 一键生成 7 个 REST 路由;Spring Boot 没有对应的「一个注解生成全部」,每个方法都要显式声明(可以用 @RequestMapping 组合)。这是风格差异,不是缺陷 —— 显式更清晰。

路由注册的时机 ​

  • 注解路由:应用启动时由 RequestMappingHandlerMapping 扫描所有 @Controller 方法,构建路由表
  • 运行时不能再增减(与 Laravel 每次请求重建路由表不同,Spring 的路由表是启动时构建的静态结构)

启动即路由

这意味着 Spring Boot 的 URL 匹配非常快(内存 Map 查找),代价是改路由必须重启。Java 世界的主流就是「编译期/启动期固化 + 重启生效」,别和 PHP 的「每请求动态」思维混在一起。

接下来,深入控制器:控制器。

面向 PHP / Laravel 开发者的 Spring Boot 中文文档