【问题标题】:How to specify prefix for all controllers in Spring Boot?如何在 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/usershttp://localhost:8080/api/orders

如何在 Spring Boot 中实现这一点?

【问题讨论】:

标签: java spring spring-boot


【解决方案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.basePathserver.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
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-03-24
              • 1970-01-01
              • 2017-08-01
              • 2013-02-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多