Java 如何在 Spring Boot 中设置用于休息的基本 url?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32927937/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to set base url for rest in spring boot?
提问by Teimuraz
I'm trying to to mix mvc and rest in a single spring boot project.
我正在尝试在一个 Spring Boot 项目中混合 mvc 和 rest。
I want to set base path for all rest controllers (eg. example.com/api)
in a single place (I don't want annotate each controller with @RequestMapping('api/products')
, instead, just @RequestMapping('/products')
.
我想在一个地方的所有其他控制器(例如,example.com/api)一套基本路径(我不想注释每个控制器@RequestMapping('api/products')
,而不是,只是@RequestMapping('/products')
。
Mvc controllers should be accessable by example.com/whatever
Mvc 控制器应该可以通过 example.com/whatever 访问
Is it possible?
是否可以?
(I don't use spring data rest, just spring mvc)
(我不使用spring data rest,只使用spring mvc)
采纳答案by Suroj
With Spring Boot 1.2+ (<2.0) all it takes is a single property in application.properties:
使用 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
For 2.x, use
对于 2.x,使用
server.servlet.context-path=/api
回答by Ilya Novoseltsev
You can create a custom annotation for your controllers:
您可以为控制器创建自定义注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}
Use it instead of the usual @RestController on your controller classes and annotate methods with @RequestMapping.
在控制器类上使用它而不是通常的 @RestController 并使用 @RequestMapping 注释方法。
Just tested - works in Spring 4.2!
刚刚测试 - 适用于 Spring 4.2!
回答by OriolBG
A bit late but the same question brought me here before reaching the answer so I post it here. Create (if you still don't have it) an application.properties and add
有点晚了,但同样的问题在得到答案之前就把我带到了这里,所以我把它贴在这里。创建(如果您还没有)一个 application.properties 并添加
server.contextPath=/api
So in the previous example if you have a RestController with @RequestMapping("/test")
you will access it like localhost:8080/api/test/{your_rest_method}
因此,在前面的示例中,如果您有一个 RestController,@RequestMapping("/test")
您将像这样访问它localhost:8080/api/test/{your_rest_method}
question source: how do i choose the url for my spring boot webapp
回答by kravemir
I found a clean solution, which affects only rest controllers.
我找到了一个干净的解决方案,它只影响休息控制器。
@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 will register two dispatcher servlets - default dispatcherServlet
for controllers, and restApi
dispatcher for @RestControllers
defined in rest.xml
:
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 [/]
The example rest.xml
:
例子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.MappingHymanson2HttpMessageConverter">
</bean>
</beans>
But, you're not limited to:
但是,您不仅限于:
- use
XmlWebApplicationContext
, you may use any else context type available, ie.AnnotationConfigWebApplicationContext
,GenericWebApplicationContext
,GroovyWebApplicationContext
, ... - define
jsonMessageConverter
,messageConverters
beans in rest context, they may be defined in parent context
- use
XmlWebApplicationContext
,您可以使用任何其他可用的上下文类型,即。AnnotationConfigWebApplicationContext
,GenericWebApplicationContext
,GroovyWebApplicationContext
, ... - 定义
jsonMessageConverter
,messageConverters
rest 上下文中的 bean,它们可以在父上下文中定义
回答by mh-dev
Since this is the first google hit for the problem and I assume more people will search for this. There is a new option since Spring Boot '1.4.0'. It is now possible to define a custom RequestMappingHandlerMappingthat allows to define a different path for classes annotated with @RestController
由于这是该问题的第一个谷歌命中,我认为更多的人会搜索这个。自 Spring Boot '1.4.0' 以来有一个新选项。现在可以定义一个自定义的RequestMappingHandlerMapping,它允许为用@RestController注释的类定义不同的路径
A different version with custom annotations that combines @RestControllerwith @RequestMappingcan be found at this blog post
可以在此博客文章中找到具有自定义注释的不同版本,该版本将@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);
}
};
}
};
}
}
回答by thorinkor
I might be a bit late, BUT... I believe it is the best solution. Set it up in your application.yml (or analogical config file):
我可能有点晚了,但是......我相信这是最好的解决方案。在 application.yml(或类似的配置文件)中进行设置:
spring:
data:
rest:
basePath: /api
As I can remember that's it - all of your repositories will be exposed beneath this URI.
我记得就是这样 - 您的所有存储库都将在此 URI 下公开。
回答by Robert
I couldn't believe how complicate the answer to this seemingly simple question is. Here are some references:
我无法相信这个看似简单的问题的答案是多么复杂。以下是一些参考:
- Spring JIRA Ticket
- Another SO question
- Yet another SO question
- Very nice GitRepository that showcases the problem
There are many differnt things to consider:
有许多不同的事情需要考虑:
- By setting
server.context-path=/api
inapplication.properties
you can configure a prefix for everything.(Its server.context-path not server.contextPath !) - Spring Data controllers annotated with @RepositoryRestController that expose a repository as rest endpoint will use the environment variable
spring.data.rest.base-path
inapplication.properties
. But plain@RestController
won't take this into account. According to the spring data rest documentationthere is an annotation@BasePathAwareController
that you can use for that. But I do have problems in connection with Spring-security when I try to secure such a controller. It is not found anymore.
- 通过设置
server.context-path=/api
,application.properties
您可以为所有内容配置前缀。(它的 server.context-path 不是 server.contextPath !) - 春季数据控制与@RepositoryRestController注释,揭露出一个仓库作为休息端点将使用环境变量
spring.data.rest.base-path
在application.properties
。但平原@RestController
不会考虑到这一点。根据spring 数据休息文档@BasePathAwareController
,您可以使用一个注释。但是当我尝试保护这样的控制器时,我确实遇到了与 Spring-security 相关的问题。已经找不到了。
Another workaround is a simple trick. You cannot prefix a static String in an annotation, but you can use expressions like this:
另一种解决方法是一个简单的技巧。您不能在注释中为静态字符串添加前缀,但可以使用如下表达式:
@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\"}";
}
}
回答by Saket Mehta
You can create a base class with @RequestMapping("rest")
annotations and extend all you other classes with this base class.
您可以创建带有@RequestMapping("rest")
注释的基类,并使用此基类扩展所有其他类。
@RequestMapping("rest")
public abstract class BaseController {}
Now all classes that extend this base class will be accessible at rest/**
.
现在所有扩展这个基类的类都可以在rest/**
.
回答by Juan Carlos Vergara Santos
For Boot 2.0.0+ this works for me: server.servlet.context-path = /api
对于 Boot 2.0.0+,这对我有用:server.servlet.context-path = /api
回答by The Gilbert Arenas Dagger
This solution applies if:
此解决方案适用于:
- You want to prefix
RestController
but notController
. You are not using 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); } }
}
- 你想要前缀
RestController
但不是Controller
. 您没有使用 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); } }
}
This is similar to the solutionposted by mh-dev, but I think this is a little cleaner and this should be supported on any version of Spring Boot 1.4.0+, including 2.0.0+.
这类似于mh-dev 发布的解决方案,但我认为这更简洁一些,任何版本的 Spring Boot 1.4.0+ 都应该支持,包括 2.0.0+。