如何在 Spring Boot 中为所有控制器指定前缀?
How to specify prefix for all controllers in Spring Boot?
我有控制器映射到 /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 引导中实现此目的?
您可以在自定义配置中提供 spring 引导应用程序到 /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;
}
}
或将此添加到 src\main\resources
文件夹中的 application.properties
server.contextPath=/api/*
编辑
As of Spring Boot 2.x the property has been deprecated 应替换为
server.servlet.contextPath=/api/*
您可以在这里找到更多 Spring Boot Context Root and here Add servlet mapping to DispatcherServlet
如果你只想为某些控制器添加前缀,我找到了另外两个解决方案
选项 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
如果您使用的是 spring 引导 2(spring 框架 5),application.properties
:
中的 属性 会被替换
server.contextPath
用于:
server.servlet.context-path=
对于那些感兴趣的人,这是 Kotlin 对 的看法,因为我无法在 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 注释导入。
在 application.properties
中添加您的默认路径为:
server.servlet.contextPath=/mainPath
此处/mainPath
将是所有控制器的前缀
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>
补充。如果你使用.yaml
,你可以写成:
server:
servlet:
context-path: /api
除了关于更改上下文路径的应用程序属性的其他注释外,您还可以使用应用程序属性单独设置调度程序servlet的前缀,在Spring 启动 2.3.1.
spring.mvc.servlet.path=/api
请求映射不会在您的控制器中更改。虽然上下文路径将整个应用程序移动到不同的路径,但 servlet 路径仅限制由调度程序 servlet 处理的 URLs。 servlet路径相当于web.xml中的servlet映射。其他不使用的资源
可以从任何其他 URL.
访问调度程序 servlet
如果您有其他未映射到 /api
前缀的控制器,那么这将不起作用,除非您为这些控制器声明具有不同前缀的第二个调度程序 servlet。
在 application.yml 中添加:
server:
servlet:
context-path: "/contextPath"
在 application.properties
添加这个
server.servlet.context-path=/api/v1/
我有控制器映射到 /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 引导中实现此目的?
您可以在自定义配置中提供 spring 引导应用程序到 /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;
}
}
或将此添加到 src\main\resources
文件夹中的 application.properties
server.contextPath=/api/*
编辑
As of Spring Boot 2.x the property has been deprecated 应替换为
server.servlet.contextPath=/api/*
您可以在这里找到更多 Spring Boot Context Root and here Add servlet mapping to DispatcherServlet
如果你只想为某些控制器添加前缀,我找到了另外两个解决方案
选项 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
如果您使用的是 spring 引导 2(spring 框架 5),application.properties
:
server.contextPath
用于:
server.servlet.context-path=
对于那些感兴趣的人,这是 Kotlin 对 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 注释导入。
在 application.properties
中添加您的默认路径为:
server.servlet.contextPath=/mainPath
此处/mainPath
将是所有控制器的前缀
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>
补充。如果你使用.yaml
,你可以写成:
server:
servlet:
context-path: /api
除了关于更改上下文路径的应用程序属性的其他注释外,您还可以使用应用程序属性单独设置调度程序servlet的前缀,在Spring 启动 2.3.1.
spring.mvc.servlet.path=/api
请求映射不会在您的控制器中更改。虽然上下文路径将整个应用程序移动到不同的路径,但 servlet 路径仅限制由调度程序 servlet 处理的 URLs。 servlet路径相当于web.xml中的servlet映射。其他不使用的资源 可以从任何其他 URL.
访问调度程序 servlet如果您有其他未映射到 /api
前缀的控制器,那么这将不起作用,除非您为这些控制器声明具有不同前缀的第二个调度程序 servlet。
在 application.yml 中添加:
server:
servlet:
context-path: "/contextPath"
在 application.properties
添加这个server.servlet.context-path=/api/v1/