如何在 Spring Boot 中为所有控制器指定前缀?
Posted
技术标签:
【中文标题】如何在 Spring Boot 中为所有控制器指定前缀?【英文标题】:How to specify prefix for all controllers in Spring Boot? 【发布时间】:2015-03-16 09:19:23 【问题描述】:我有到/user
和/order
的控制器映射:
@RestController
@RequestMapping("/users")
public class UserController
...
@RestController
@RequestMapping("/orders")
public class OrderController
...
我想通过 URL 分别访问 http://localhost:8080/api/users
和 http://localhost:8080/api/orders
。
如何在 Spring Boot 中实现这一点?
【问题讨论】:
Spring Boot Context Root的可能重复 【参考方案1】:您可以在自定义配置中提供到 Spring Boot 应用程序的根上下文路径到 /api/*
的映射。
import org.springframework.boot.autoconfigure.web.DispatcherServletAutoConfiguration;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
@Configuration
public class DispatcherServletCustomConfiguration
@Bean
public DispatcherServlet dispatcherServlet()
return new DispatcherServlet();
@Bean
public ServletRegistrationBean dispatcherServletRegistration()
ServletRegistrationBean registration = new ServletRegistrationBean(
dispatcherServlet(), "/api/");
registration.setName(DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME);
return registration;
或将其添加到您的application.properties
src\main\resources
文件夹中
server.contextPath=/api/*
编辑
As of Spring Boot 2.x the property has been deprecated 应替换为
server.servlet.contextPath=/api/*
您可以在此处Spring Boot Context Root 和此处Add servlet mapping to DispatcherServlet 找到更多信息
【讨论】:
这会将前缀添加到所有内容,而不仅仅是控制器 它应该只是 "server.contextPath=/api/" 。在 Spring Boot 版本 1.3.5 中有一个尾随 * 会导致错误 请注意,org.springframework.boot.context.embedded.ServletRegistrationBean 在 1.4 中已被弃用,并引入了它的替代品 org.springframework.boot.web.servlet.ServletRegistrationBean。在 1.5 中删除了已弃用的类 位于application.properties
文件中的server.servlet.context-path = /api/*
给了我Error registering Tomcat:type=TomcatEmbeddedWebappClassLoader,host=localhost,context=/api/* - ContextPath must start with '/' and not end with '/'
错误。不带引号的 server.servlet.context-path = /api
属性是应用程序启动所需的属性。
对于 Spring Boot 2.0,它必须像 server.servlet.context-path=/api
。【参考方案2】:
如果您只想为某些控制器添加前缀,我找到了另外两个解决方案
选项 1 - 使用 spring SpEL 为您的控制器添加前缀变量
@RestController
@RequestMapping(path = "$v1API/users")
public class V1FruitsController
@GetMapping(path = "")
@ResponseBody
public String list()
return "[\"Joe\", \"Peter\"]";
application.properties
v1API=/api/v1
选项 2 - 创建自定义控制器注释
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
@RequestMapping("/api/v1")
public @interface V1APIController
@AliasFor(annotation = Component.class)
String value() default "";
@V1APIController
public class UserController
@RequestMapping("/users")
@ReponseBody
public String index()
return "[\"Joe\", \"Peter\"]";
然后测试一下
curl -X GET localhost:8080/api/v1/users
【讨论】:
是的,但是如果你的 UserController 中有很多方法呢?现在你已经权衡了在类级别编写 @RequestMapping("/api/users") 来为每个方法的 RequestMapping 加上 "users" 前缀。 您使用@Component 作为注解和别名而不是@RestController 有什么原因吗? @JimBob 不,你也可以使用@RestController
【参考方案3】:
如果您使用的是spring boot 2(spring framework 5),则application.properties
中的属性有一个替换:
server.contextPath
为:
server.servlet.context-path=
【讨论】:
谢谢。我想添加 '/api' 前缀并由 server.servlet.context-path=/api 添加【参考方案4】:在application.properties
中添加您的默认路径为:
server.servlet.contextPath=/mainPath
这里/mainPath
是所有控制器的前缀
【讨论】:
在我当前版本的 spring boot 中,该属性名称是 context-path。【参考方案5】:除了关于更改上下文路径的应用程序属性的其他 cmets,您还可以在 Spring Boot 2.3.1 中使用应用程序属性单独设置调度程序 servlet 的前缀。
spring.mvc.servlet.path=/api
请求映射不会在您的控制器中更改。虽然上下文路径将整个应用程序移动到不同的路径,但 servlet 路径仅限制调度程序 servlet 处理的 URL。 servlet 路径相当于 web.xml 中的 servlet 映射。其他不使用的资源 可以从任何其他 URL 访问调度程序 servlet。
如果您有其他未映射到 /api
前缀的控制器,那么这将不起作用,除非您为这些控制器声明具有不同前缀的第二个调度程序 servlet。
【讨论】:
【参考方案6】:对于那些感兴趣的人,这里是 Kotlin 对 deFreitas' Option 2 Component 的看法,因为我无法在 application.yaml
中使用 spring.data.rest.basePath
或 server.servlet.contextPath
。 (这是 Spring Boot 2.1.2 和 Kotlin 1.13.11)
package com.myproject.controller
import org.springframework.core.annotation.AliasFor
import org.springframework.stereotype.Component
import org.springframework.web.bind.annotation.RequestMapping
import kotlin.annotation.MustBeDocumented
import kotlin.annotation.Retention
import kotlin.annotation.Target
import kotlin.annotation.AnnotationRetention
@Target(AnnotationTarget.CLASS, AnnotationTarget.FILE)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Component
@RequestMapping("/api/v1")
annotation class V1ApiController(
@get:AliasFor(annotation = Component::class)
val value: String = ""
)
如果您使用的是 IntelliJ,为简洁起见,优化导入可能会删除 Kotlin 注释导入。
【讨论】:
【参考方案7】:在 application.yml 中添加:
server:
servlet:
context-path: "/contextPath"
【讨论】:
【参考方案8】:将此添加到 application.properties
server.servlet.context-path=/api/v1/
【讨论】:
【参考方案9】:server.servlet.context-path
是正确的路径。不是server.servlet.contextPath
,不幸的是它似乎不支持您可以在 web.xml 中执行的列表,如下所示:
<servlet>
<description>Servlet used by Spring MVC to handle all requests into the application</description>
<servlet-name>spring</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/app1/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>spring</servlet-name>
<url-pattern>/app2/*</url-pattern>
</servlet-mapping>
【讨论】:
【参考方案10】:附加。如果你使用.yaml
,你可以写成:
server:
servlet:
context-path: /api
【讨论】:
以上是关于如何在 Spring Boot 中为所有控制器指定前缀?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 GET 方法中为 Spring Boot 控制器类传递多个路径变量?
忽略在 yaml 配置中为 Spring Boot 管理应用程序指定斜杠字符
如何在 Spring Boot 2 中为 Spring Batch 配置数据源以进行测试
你可以在 Spring Boot 中为多个模型设置一个控制器吗?
如何在 Spring Boot 中为 Spring LDAP 身份验证设置覆盖 BindAuthenticator handleBindException