You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Boot中实现类似Django的路由前缀复用?

在Spring Boot中实现类似Django的路由前缀复用配置

我之前做过Django项目,里面可以创建带前缀的路由集合,再通过include引入其他URL文件来定义端点的剩余部分,示例代码如下:

api_patterns= [
  url('foo/', include(foo.urls)),
  url('bar/', include(bar.urls)),
]

urlpatterns = [
  url(r'api/', include(api_patterns)),
]

这种方式会生成/api/foo/和/api/bar/端点,每个端点对应不同目录下的独立URL文件,无需重复编写前缀。

现在我在Spring Boot项目里,目前是给每个控制器的@RequestMapping添加前缀,但大量控制器都共用相同的前缀,比如下面的例子:

// Foo controller
@Controller
@RequestMapping(path = "api/foo")
public class FooController {

  @GetMapping(path = "")
  // 对应端点 /api/foo
}

// Bar controller
@Controller
@RequestMapping(path = "api/bar")
public class BarController {

  @GetMapping(path = "")
  // 对应端点 /api/bar
}

// Tar controller by foo
@Controller
@RequestMapping(path = "api/foo/tar")
public class TarController {

  @GetMapping(path = "")
  // 对应端点 /api/foo/tar
}

这样每个控制器都要重复写api/甚至更长的前缀,我认为这是不良实践,想优化这种重复写法,请问Spring Boot里有没有等价于Django那种路由前缀复用的实现方式?


解决方案

1. 控制器继承实现前缀复用

创建一个基础控制器类,定义公共前缀,同前缀的控制器继承该类,只需要编写剩余路径部分:

// 基础API控制器,定义公共前缀/api
@Controller
@RequestMapping("api")
public class BaseApiController {
    // 可在此添加公共逻辑,比如权限校验、通用响应处理
}

// Foo控制器,仅需编写子前缀foo
@Controller
@RequestMapping("foo")
public class FooController extends BaseApiController {

    @GetMapping("")
    // 对应端点 /api/foo
    public String fooEndpoint() {
        return "foo";
    }
}

// Bar控制器同理
@Controller
@RequestMapping("bar")
public class BarController extends BaseApiController {

    @GetMapping("")
    // 对应端点 /api/bar
    public String barEndpoint() {
        return "bar";
    }
}

// Tar控制器,编写子前缀foo/tar
@Controller
@RequestMapping("foo/tar")
public class TarController extends BaseApiController {

    @GetMapping("")
    // 对应端点 /api/foo/tar
    public String tarEndpoint() {
        return "tar";
    }
}

后续如果公共前缀需要修改,只需调整父类的@RequestMapping即可,无需逐个修改控制器。

2. 全局统一前缀配置(适用于所有API)

如果所有接口都需要统一的api/前缀,可通过配置类全局设置,无需在控制器上重复声明:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        // 给所有标注@Controller的类添加/api前缀
        configurer.addPathPrefix("api", c -> c.isAnnotationPresent(Controller.class));
    }
}

之后控制器只需编写自身路径:

@Controller
@RequestMapping("foo")
public class FooController {

    @GetMapping("")
    // 对应端点 /api/foo
    public String fooEndpoint() {
        return "foo";
    }
}

3. 按模块分组配置前缀(Spring Boot 2.6+)

如果需要给不同模块的控制器设置不同前缀,可使用@ControllerAdvice按包或类分组配置:

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RequestMapping;

// 给com.example.api.foo包下的所有控制器添加/api/foo前缀
@ControllerAdvice(basePackages = "com.example.api.foo")
@RequestMapping("api/foo")
public class FooApiAdvice {
}

该包下的控制器只需编写自身路径:

package com.example.api.foo;

@Controller
public class TarController {

    @GetMapping("tar")
    // 对应端点 /api/foo/tar
    public String tarEndpoint() {
        return "tar";
    }
}

这种方式适合按业务模块划分前缀的场景,不同模块的前缀可独立配置。

内容的提问来源于stack exchange,提问作者Arif Jehda-Oh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 23:01:23