我正在尝试混合mvc和在单个spring boot项目中休息。
我想在一个地方设置所有其余控制器(例如example.com/api)的基本路径(我不想用@RequestMapping('api/products')
,而只是用注释每个控制器@RequestMapping('/products')
。
Mvc控制器应可通过example.com/whatever访问
可能吗?
(我不使用spring数据休息,只是spring mvc)
我正在尝试混合mvc和在单个spring boot项目中休息。
我想在一个地方设置所有其余控制器(例如example.com/api)的基本路径(我不想用@RequestMapping('api/products')
,而只是用注释每个控制器@RequestMapping('/products')
。
Mvc控制器应可通过example.com/whatever访问
可能吗?
(我不使用spring数据休息,只是spring mvc)
Answers:
使用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
有点晚了,但是同样的问题使我来到这里才得到答案,所以我在这里发布了。创建(如果还没有的话)一个application.properties并添加
server.contextPath=/api
因此,在前面的示例中,如果您有RestController,@RequestMapping("/test")
则可以像这样访问它localhost:8080/api/test/{your_rest_method}
对于Spring Boot Framework版本2.0.4.RELEASE+
。将此行添加到application.properties
server.servlet.context-path=/api
spring.data.rest.basePath
不适用于Spring Boot 2
由于这是该问题的第一个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);
}
};
}
};
}
}
我不敢相信这个看似简单的问题的答案有多么复杂。以下是一些参考资料:
有许多不同的事情要考虑:
server.context-path=/api
,application.properties
您可以为所有内容配置一个前缀。(它的server.context-path不是server.contextPath!)spring.data.rest.base-path
在application.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\"}";
}
}
对于Boot 2.0.0+,这对我有效:server.servlet.context-path = / api
我找到了一个干净的解决方案,它只影响其余的控制器。
@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
,您可以使用任何其他可用的上下文类型,即。AnnotationConfigWebApplicationContext
,GenericWebApplicationContext
,GroovyWebApplicationContext
,...jsonMessageConverter
,messageConverters
bean在其余上下文中,它们可以在父上下文中定义您可以为控制器创建自定义注释:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}
在控制器类上使用它代替通常的@RestController,并使用@RequestMapping注释方法。
刚刚测试-在Spring 4.2中可以使用!
RequestMappingHandlerMapping
。Spring Data REST的映射器类似于您需要的- BasePathAwareHandlerMapping
。
我可能会晚一点,但是...我相信这是最好的解决方案。在application.yml(或类似的配置文件)中进行设置:
spring:
data:
rest:
basePath: /api
我记得就是这样-您的所有存储库都将显示在此URI下。
spring.data.rest.base-path
仅影响spring-data-rest和spring-hateoas。普通@RestController仍将位于根目录!
尝试使用PathMatchConfigurer(Spring Boot 2.x):
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.addPathPrefix("api", HandlerTypePredicate.forAnnotation(RestController.class));
}
}
您可以创建带有@RequestMapping("rest")
注释的基类,并使用此基类扩展所有其他类。
@RequestMapping("rest")
public abstract class BaseController {}
现在,所有扩展此基类的类都可以在访问rest/**
。
对于那些使用YAML配置(application.yaml)的用户。
注意:这仅适用于Spring Boot 2.x.x
server:
servlet:
contextPath: /api
如果您仍在使用 Spring Boot 1.x
server:
contextPath: /api
使用spring-boot 2.x,可以在application.properties中进行配置:
spring.mvc.servlet.path=/api
server.servlet.context-path=/api
我猜就是解决方案。我遇到了同样的问题,这使我解决了。我使用server.context-path。但是,这似乎已被弃用,我发现server.servlet.context-path
现在可以解决问题。我发现的另一个解决方法是在前端(H5)页面中添加基本标签。我希望这可以帮助某个人。
干杯
该解决方案适用于以下情况:
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);
}
}
}
这类似于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月创建了一个相关票证以澄清文档。)