如何设置基本网址休息在春季启动?

我试图混合 mvc 和休息在一个单一的春季启动项目。

我想为所有的休息控制器设置基本路径(例如 example.com/api) 在一个单独的位置(我不想用 @RequestMapping('api/products')来注释每个控制器,而是仅用 @RequestMapping('/products')

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

有可能吗?

(我不使用 spring data rest,只使用 spring mvc)

294743 次浏览

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

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

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

刚刚测试-工程在春天4.2!

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

server.contextPath=/api

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

问题来源: 如何为我的春季启动网页应用程序选择网址

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

@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 启动将注册两个调度器 servlet ——控制器默认为 dispatcherServletrest.xml中定义的 @RestControllersrestApi调度器:

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,您可以使用任何其他可用的上下文类型,即。
  • 在静止上下文中定义 jsonMessageConvertermessageConverters bean,它们可以在父上下文中定义

因为这是第一次谷歌点击的问题,我认为更多的人会搜索这一点。从 Spring Boot’1.4.0’开始有了一个新的选项。 现在可以定义一个定制的 RequestMappingHandlerMapping,它允许为用 < em >@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);
}
};
}
};
}
}

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

spring:
data:
rest:
basePath: /api

我记得就是这样——所有的存储库都将暴露在这个 URI 之下。

我简直不敢相信这个看似简单的问题的答案竟然如此复杂。以下是一些参考资料:

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

  1. 通过在 application.properties中设置 server.context-path=/api,可以为 一切配置前缀(其 server.context-path 不是 server.contextPath!)
  2. 使用@RepositoryRestController 注释的 Spring Data 控制器将使用 application.properties中的环境变量 spring.data.rest.base-path来公开一个存储库作为静止端点。但是普通的 @RestController不会考虑这一点。根据 弹簧数据休止文档,有一个注释 @BasePathAwareController,您可以使用它。但是,当我尝试保护这样一个控制器时,在与 Spring 安全性相关的方面确实存在问题。现在已经找不到了。

另一个变通方法是一个简单的技巧。不能在注释中给静态 String 加前缀,但是可以使用如下表达式:

@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\"}";
}
}

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

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

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

对于 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

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

如果:

  1. 您希望以 RestController为前缀,但不希望以 Controller为前缀。
  2. 您没有使用 Spring 数据休息。

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

对于弹簧启动框架版本 2.0.4.RELEASE+。将此行添加到 application.properties

server.servlet.context-path=/api

根据 Spring Data REST 医生,如果使用 应用性能,请使用此属性设置基本路径:

spring.data.rest.basePath=/api

但是请注意,Spring 用途 松散的约束力,因此可以使用这个变体:

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

或者这个,如果你喜欢的话:

spring.data.rest.base_path=/api

如果使用 应用,您将使用冒号作为键分隔符:

spring:
data:
rest:
basePath: /api

(作为参考,我们于2018年3月成立了相关的 罚单,以澄清有关文件。)

使用 spring-boot 2.x,您可以在 application.properties 中进行配置:

spring.mvc.servlet.path=/api

工作的 server.contextPath =/path

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

@Configuration
public class WebMvcConfig implements WebMvcConfigurer  {


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

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

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

在 Spring 4.2中工作正常!

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

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

server:
servlet:
contextPath: /api


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

server:
contextPath: /api

我想 server.servlet.context-path=/api是解决方案。我也遇到过同样的问题,这件事让我解决了。我使用了 server.context-path。然而,这似乎是不被推崇的,我发现 server.servlet.context-path现在解决了这个问题。我发现的另一个变通方法是在前端(H5)页面中添加一个基本标记。我希望这能帮到别人。

干杯

我做了一些关于这个帖子中提到的弹簧性能差异的研究。这是我的发现,如果有人想知道。

BasePath 属性

spring.data.rest.basePath=/api

这个属性是专门用于 春季数据休息项目的,它不适用于一般的 Spring MVC 项目。

要更改 MVC 项目中的上下文路径,可以使用下面提到的两个属性。让我也提一下它们的不同之处。

Context-path 属性

server.servlet.context-path=/api

这个函数设置 Web servlet 上的上下文路径。这个属性在 Spring mvc 和 spring data rest 项目中都可以很好地工作。不同之处在于请求 URL 在到达弹簧拦截器之前会被过滤掉。因此,如果请求不好,它将使用 HTML 进行响应。没有定义 Spring 或您自己的定制 JSON 响应(在@ResponseBodyAdvisory 注释类中)。为了克服这个问题,您应该使用下面的属性。

路径属性

spring.mvc.servlet.path=/api

这将在 Spring mvc 拦截器中过滤请求 URL,并在调用错误请求时响应 default/自定义 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))
}