繁体   English   中英

如何在 spring 引导中将 base url 设置为 rest?

[英]How to set base url for rest in spring boot?

我正在尝试在单个 spring 引导项目中混合使用 mvc 和 rest。

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

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

是否可以?

(我没有使用spring数据rest,只是spring mvc)

使用 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.changed-base-uri

对于 2.x,使用

server.servlet.context-path=/api

有点晚了,但同样的问题在得到答案之前就把我带到了这里,所以我把它贴在这里。 创建(如果您还没有)一个 application.properties 并添加

server.contextPath=/api

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

问题来源: 如何为spring boot webapp选择url

对于 spring boot 框架版本2.0.4.RELEASE+ 将此行添加到application.properties

server.servlet.context-path=/api

我无法相信这个看似简单的问题的答案是多么复杂。 以下是一些参考:

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

  1. 通过在application.properties设置server.context-path=/api您可以为所有内容配置前缀。(它的 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\"}";
  }
}

由于这是该问题的第一个谷歌命中,我认为更多的人会搜索这个。 自 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);
                    }
                };
            }
        };
    }
}

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

@Configuration
public class WebMvcConfig implements WebMvcConfigurer  {

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

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

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

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

在控制器类上使用它而不是通常的 @RestController 并使用 @RequestMapping 注释方法。

刚刚测试 - 适用于 Spring 4.2!

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

@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);
    }
}

春天开机时会注册两个调度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 ,您可以使用任何其他可用的上下文类型,即。 AnnotationConfigWebApplicationContext , GenericWebApplicationContext , GroovyWebApplicationContext , ...
  • 在rest上下文中定义jsonMessageConvertermessageConverters bean,它们可以在父上下文中定义

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

spring:
    data:
        rest:
            basePath: /api

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

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

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

现在所有扩展这个基类的类都可以在rest/**访问。

使用 spring-boot 2.x 你可以在 application.properties 中配置:

spring.mvc.servlet.path=/api

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

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

server:
  servlet:
    contextPath: /api

如果你还在使用Spring Boot 1.x

server:
  contextPath: /api

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

干杯

我对这个线程中提到的弹簧特性的差异做了一些研究。 如果有人想知道,这是我的发现。

spring.data.rest.basePath 属性

spring.data.rest.basePath=/api

此属性专门用于Spring Data Rest项目。 它不会在通常的 Spring MVC 项目中工作。

要更改 MVC 项目中的上下文路径,您可以使用下面提到的这两个属性。 让我也提一下差异。

server.servlet.context-path 属性

server.servlet.context-path=/api

这将设置您的 web 小服务上的上下文路径。 这个属性在 spring mvc 和 spring data rest 项目中都能很好地工作。 但是,不同之处在于请求 url 将在到达 spring 拦截器之前被过滤掉。 所以它会在错误的请求中以 HTML 响应。 未定义 Spring 或您自己的自定义 JSON 响应(在 @ResponseBodyAdvice 注释类中)。 为了克服这个问题,您应该在下面使用此属性。

spring.mvc.servlet.path 属性

spring.mvc.servlet.path=/api

这将过滤 spring mvc 拦截器中的请求 URL,如果您调用错误的请求,它将响应默认/您的自定义 JSON 响应。

结论:

因此,作为 OP 的问题,我建议他应该使用spring.mvc.servlet.path来更改上下文路径。

对于 Spring WebFlux,方法类似于 Harald 的方法,但具有明显的 WebFlux 配置设置:

@Configuration
public class WebFluxConfig implements WebFluxConfigurer  {

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

对于 Kotlin,它是:

@Configuration
class WebFluxConfig : WebFluxConfigurer {
    override fun configurePathMatching(configurer: PathMatchConfigurer) {
       configurer.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(RestController::class.java))
}

此解决方案适用于:

  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+。

根据 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 月创建了一张相关票证以澄清文档。)

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

在控制器类上使用它而不是通常的 @RestController 并使用 @RequestMapping 注释方法。

在 Spring 4.2 中工作正常!

工作 server.contextPath=/path

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM