如何在Spring Boot中设置基本URL以进行休息?


118

我正在尝试混合mvc和在单个spring boot项目中休息。

我想在一个地方设置所有其余控制器(例如example.com/api)的基本路径(我不想用@RequestMapping('api/products'),而只是用注释每个控制器@RequestMapping('/products')

Mvc控制器应可通过example.com/whatever访问

可能吗?

(我不使用spring数据休息,只是spring mvc)



server.servlet.contextPath = / api
Daniel T. Sobrosa

春季启动版本2.1.4.RELEASE,spring.mvc.servlet.path = / api和server.servlet.context-path = / api都有效
Prayag Sharma,

server.servlet.context-path = / api解决方案适用于APPLICATION,而不仅适用于REST。对于SOAP服务也有效。如果你想你的sperate SOAP和REST的服务路径,你应该使用@RequestMapping( 'API / ...')...... medium.com/@bm.celalkartal/...
bmck

Answers:


89

使用Spring Boot 1.2+(<2.0),只需在application.properties中使用一个属性即可:

spring.data.rest.basePath=/api

引用链接:https : //docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri

对于2.x,请使用

server.servlet.context-path=/api

4
这是thorinkor给出的确切答案。
让弗朗索瓦Beauchef

8
谢谢,但这在Spring Boot版本1.5.7.RELEASE中对我不起作用。另一个答案server.contextPath = / api起作用了
Jay

10
@Suroj该解决方案仅适用于带RepositoryRestController注释的控制器,不适用于RestController ...
纳米

jira.spring.io/browse/DATAREST-1211这个Jira票证提到它是“ Spring Boot 2.0.0的spring.data.rest.base-path”。可悲的是,两者都不适合我。
卡斯滕·哈格曼

6
对于SB 2+,它是server.servlet.context-path = / url
vicky

95

有点晚了,但是同样的问题使我来到这里才得到答案,所以我在这里发布了。创建(如果还没有的话)一个application.properties并添加

server.contextPath=/api

因此,在前面的示例中,如果您有RestController,@RequestMapping("/test")则可以像这样访问它localhost:8080/api/test/{your_rest_method}

问题来源:如何为Spring Boot Webapp选择URL


19
您如何执行此操作,使其仅与RestControllers一起使用并访问没有“ / api”的普通控制器
Siya Sosibo,2016年

@Stoan我找到了解决方法,请检查我的回答:-)
kravemir

不要这样!请参阅thorinkor的答案。
Stefan'9

Thorinkor的答案专门针对Spring Data REST。

8
现在不建议使用server.contextPath,而应使用server.servlet.context-path
DS。

46

对于Spring Boot Framework版本2.0.4.RELEASE+。将此行添加到application.properties

server.servlet.context-path=/api

1
这也确实会影响公用文件夹:-(
Michel的

5
这是Spring Boot 2+的正确答案。spring.data.rest.basePath不适用于Spring Boot 2
jackycflau

27

由于这是该问题的第一个Google搜索结果,我想会有更多人搜索该问题。从Spring Boot'1.4.0'开始有一个新选项。现在可以定义一个自定义的RequestMappingHandlerMapping,它允许为使用@RestController注释的类定义不同的路径。

可以在此博客文章中找到结合了@RestController@RequestMapping的具有自定义注释的不同版本。

@Configuration
public class WebConfig {

    @Bean
    public WebMvcRegistrationsAdapter webMvcRegistrationsHandlerMapping() {
        return new WebMvcRegistrationsAdapter() {
            @Override
            public RequestMappingHandlerMapping getRequestMappingHandlerMapping() {
                return new RequestMappingHandlerMapping() {
                    private final static String API_BASE_PATH = "api";

                    @Override
                    protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
                        Class<?> beanType = method.getDeclaringClass();
                        if (AnnotationUtils.findAnnotation(beanType, RestController.class) != null) {
                            PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_BASE_PATH)
                                    .combine(mapping.getPatternsCondition());

                            mapping = new RequestMappingInfo(mapping.getName(), apiPattern,
                                    mapping.getMethodsCondition(), mapping.getParamsCondition(),
                                    mapping.getHeadersCondition(), mapping.getConsumesCondition(),
                                    mapping.getProducesCondition(), mapping.getCustomCondition());
                        }

                        super.registerHandlerMethod(handler, method, mapping);
                    }
                };
            }
        };
    }
}

2
在Spring Boot 2.0.0+中,直接关闭WebMvcRegistrations接口。删除了WebMvcRegistrationsAdapter,以便向接口添加默认方法。
吉尔伯特·阿里纳斯·匕首'18

26

我不敢相信这个看似简单的问题的答案有多么复杂。以下是一些参考资料:

有许多不同的事情要考虑:

  1. 通过设置server.context-path=/apiapplication.properties您可以为所有内容配置一个前缀。(它的server.context-path不是server.contextPath!)
  2. 春季数据控制与@RepositoryRestController注释,揭露出一个仓库作为休息端点将使用环境变量spring.data.rest.base-pathapplication.properties。但是普通人@RestController不会考虑到这一点。根据spring数据其余文档,有一个注释@BasePathAwareController可用于此目的。但是,当我尝试保护这样的控制器时,在与Spring-security的连接方面确实存在问题。找不到了。

另一个解决方法是一个简单的技巧。您不能在注释中为静态字符串加上前缀,但可以使用如下表达式:

@RestController
public class PingController {

  /**
   * Simple is alive test
   * @return <pre>{"Hello":"World"}</pre>
   */
  @RequestMapping("${spring.data.rest.base-path}/_ping")
  public String isAlive() {
    return "{\"Hello\":\"World\"}";
  }
}

您将如何添加注释?
Teimuraz

2
嗯,那么您每次创建新控制器时都必须记住要添加此前缀
The Gilbert Arenas Dagger

13

对于Boot 2.0.0+,这对我有效:server.servlet.context-path = / api


4
这一切似乎都放在/ api下,而不仅仅是@RestController映射器。但是还是谢谢你。您的信息仍然有用。
eigil

9

我找到了一个干净的解决方案,它只影响其余的控制器。

@SpringBootApplication
public class WebApp extends SpringBootServletInitializer {

    @Autowired
    private ApplicationContext context;

    @Bean
    public ServletRegistrationBean restApi() {
        XmlWebApplicationContext applicationContext = new XmlWebApplicationContext();
        applicationContext.setParent(context);
        applicationContext.setConfigLocation("classpath:/META-INF/rest.xml");

        DispatcherServlet dispatcherServlet = new DispatcherServlet();
        dispatcherServlet.setApplicationContext(applicationContext);

        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(dispatcherServlet, "/rest/*");
        servletRegistrationBean.setName("restApi");

        return servletRegistrationBean;
    }

    static public void main(String[] args) throws Exception {
        SpringApplication.run(WebApp.class,args);
    }
}

Spring Boot将注册两个调度程序Servlet- dispatcherServlet控制器默认,restApi调度程序@RestControllers定义于rest.xml

2016-06-07 09:06:16.205  INFO 17270 --- [           main] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'restApi' to [/rest/*]
2016-06-07 09:06:16.206  INFO 17270 --- [           main] o.s.b.c.e.ServletRegistrationBean        : Mapping servlet: 'dispatcherServlet' to [/]

例子rest.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
  http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

    <context:component-scan base-package="org.example.web.rest"/>
    <mvc:annotation-driven/>

    <!-- Configure to plugin JSON as request and response in method handler -->
    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonMessageConverter"/>
            </list>
        </property>
    </bean>

    <!-- Configure bean to convert JSON to POJO and vice versa -->
    <bean id="jsonMessageConverter" class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
    </bean>
</beans>

但是,您不仅限于

  • 使用XmlWebApplicationContext,您可以使用任何其他可用的上下文类型,即。AnnotationConfigWebApplicationContextGenericWebApplicationContextGroovyWebApplicationContext,...
  • define jsonMessageConvertermessageConvertersbean在其余上下文中,它们可以在父上下文中定义

是否可以通过编程方式执行此操作而不使用xml?
阿里安

@ArianHosseinzadeh是的。可以通过编程来完成。有很多方法可以设置Spring上下文。在示例中,我展示了如何为REST API处理创建子上下文。只需学习如何在Java中设置上下文,然后将这种知识与该答案中的知识相结合即可。这就是所谓的编程。
克拉韦米尔'17

7

您可以为控制器创建自定义注释:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}

在控制器类上使用它代替通常的@RestController,并使用@RequestMapping注释方法。

刚刚测试-在Spring 4.2中可以使用!


谢谢。我已经试过了 但是现在我必须使用@RequestMapping(“ / products”),@ RequestMapping(“ / products / {id}”)来注释每个方法。相反,我需要使用@RequestMapping(“ / products”)注释Controller和使用@RequestMapping,@RequestMapping(“ /:id”)的方法。并且产品控制器应可访问api / products(例如,在单个位置设置api前缀)
Teimuraz 2015年

2
在这种情况下,没有,没有解决方案,即AFAIK。您可以尝试实现自己的RequestMappingHandlerMapping。Spring Data REST的映射器类似于您需要的- BasePathAwareHandlerMapping
Ilya Novoseltsev

@moreo,您找到合适的解决方案了吗?如果您可以将其发布为回复,我会很高兴。我在这里有相同的要求。
fischermatte 2015年

@fischermatte,不,我没有找到我想要的东西,我将@RequestMapping(“ / api / products”)或@RequestMapping(“ / api / users”)放在每个控制器类之前,然后在方法之前放置另一个@ RequestMapping(“ / {id}”)。但是我不认为这是个大问题,如果我想将“ api”更改为某些内容,我只会在每堂课的开始进行更改。
2015年

@IlyaNovoseltsev有一个解决方案,请参见我的回答:-)
kravemir

7

我可能会晚一点,但是...我相信这是最好的解决方案。在application.yml(或类似的配置文件)中进行设置:

spring:
    data:
        rest:
            basePath: /api

我记得就是这样-您的所有存储库都将显示在此URI下。


您能对此解释一下还是指向相关文档?
德米特里·谢尔迪克


11
environemnt变量 spring.data.rest.base-path 仅影响spring-data-rest和spring-hateoas。普通@RestController仍将位于根目录!
罗伯特

4
@thorinkor是基于您的意思,在大多数情况下,人们将构建Spring Data REST存储库?而OP显然是说他有其他的控制器......
让·弗朗索瓦·Beauchef

1
我认为,仅当您使用SpringDataRest时,它将起作用。
Jaumzera

6

尝试使用PathMatchConfigurer(Spring Boot 2.x):

@Configuration
public class WebMvcConfig implements WebMvcConfigurer  {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("api", HandlerTypePredicate.forAnnotation(RestController.class));
    }
}

1
谢谢,这正是我想要的!这允许您为通过此WebMvcConfig配置的所有RestController设置上下文路径元素,类似于spring.data.rest.base-path所做的。
布曼

您的答案就在@HaraldWendel上:+1:您可以通过扩展一点来进一步改进它,例如解释代码的确切功能(如我在评论中尝试过的)和/或链接到一些描述此用法的javadoc或文档。
布曼

这是我使用控制器接口时唯一对我
有用的

4

您可以创建带有@RequestMapping("rest")注释的基类,并使用此基类扩展所有其他类。

@RequestMapping("rest")
public abstract class BaseController {}

现在,所有扩展此基类的类都可以在访问rest/**


3
这不是正确答案,用户指的是控制器注释。如果扩展带有RequestMapping批注的抽象类,而新类也具有RequestMapping,则该最后一个类将覆盖第一个类,而不会将两者连接在一起。
马西莫

您是否知道Java不会继承注解,除非它已继承了元注解?检查一下:stackoverflow.com/a/21409651。@RequestMapping似乎没有:docs.spring.io/spring-framework/docs/current/javadoc-api/org/…–
Mashrur,

2

对于那些使用YAML配置(application.yaml)的用户。

注意:这仅适用于Spring Boot 2.x.x

server:
  servlet:
    contextPath: /api

如果您仍在使用 Spring Boot 1.x

server:
  contextPath: /api


1

server.servlet.context-path=/api我猜就是解决方案。我遇到了同样的问题,这使我解决了。我使用server.context-path。但是,这似乎已被弃用,我发现server.servlet.context-path现在可以解决问题。我发现的另一个解决方法是在前端(H5)页面中添加基本标签。我希望这可以帮助某个人。

干杯


0

该解决方案适用于以下情况:

  1. 您想添加前缀RestController而不是Controller
  2. 您没有使用Spring Data Rest。

    @Configuration
    public class WebConfig extends WebMvcConfigurationSupport {
    
    @Override
    protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
        return new ApiAwareRequestMappingHandlerMapping();
    }
    
    private static class ApiAwareRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    
        private static final String API_PATH_PREFIX = "api";
    
        @Override
        protected void registerHandlerMethod(Object handler, Method method, RequestMappingInfo mapping) {
            Class<?> beanType = method.getDeclaringClass();
            if (AnnotationUtils.findAnnotation(beanType, RestController.class) != null) {
                PatternsRequestCondition apiPattern = new PatternsRequestCondition(API_PATH_PREFIX)
                        .combine(mapping.getPatternsCondition());
    
                mapping = new RequestMappingInfo(mapping.getName(), apiPattern, mapping.getMethodsCondition(),
                        mapping.getParamsCondition(), mapping.getHeadersCondition(), mapping.getConsumesCondition(),
                        mapping.getProducesCondition(), mapping.getCustomCondition());
            }
            super.registerHandlerMethod(handler, method, mapping);
        }
    }

    }

这类似于mh-dev发布的解决方案,但我认为这更干净一些,任何版本的Spring Boot 1.4.0+(包括2.0.0+)都应支持。


如果我在RestControler中使用Pageable,则api / somethings不会为我提供接口org.springframework.data.domain.Pageable的主构造函数或默认构造函数
K. Ayoub,

0

对于Spring Data REST docs,如果使用application.properties,请使用此属性设置您的基本路径:

spring.data.rest.basePath=/api

但是请注意,Spring 使用 宽松的绑定,因此可以使用以下变体:

spring.data.rest.base-path=/api

...或者如果您愿意的话:

spring.data.rest.base_path=/api

如果使用application.yml,则将冒号用作键分隔符:

spring:
  data:
    rest:
      basePath: /api

(供参考,于2018年3月创建了一个相关票证以澄清文档。)



0

您可以为控制器创建自定义注释:

在控制器类上使用它代替通常的@RestController,并使用@RequestMapping注释方法。

在Spring 4.2中工作正常!

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.