Ich versuche, mvc zu mischen und in einem einzigen Spring Boot-Projekt zu ruhen.
Ich möchte den Basispfad für alle Rest-Controller festlegen (z. B. example.com/api) an einer Stelle (Ich möchte nicht, dass jeder Controller mit @RequestMapping('api/products')
, statt nur @RequestMapping('/products')
, kommentiert wird.
Mvc-Controller sollten über example.com/whatever erreichbar sein
Ist es möglich?
(Ich verwende keine Feder-Datenruhe, nur Feder-MVC)
Mit Spring Boot 1.2+ benötigen Sie lediglich eine einzige Eigenschaft in application.properties:
spring.data.rest.basePath=/api
Ein bisschen spät, aber die gleiche Frage brachte mich hierher, bevor ich die Antwort erreichte, also poste ich sie hier . Erstellen Sie (falls Sie sie noch nicht haben) eine application.properties und fügen Sie sie hinzu
server.contextPath=/api
Wenn Sie also im vorherigen Beispiel einen RestController mit @RequestMapping("/test")
haben, greifen Sie wie localhost:8080/api/test/{your_rest_method}
darauf zu.
frage Quelle: Wie wähle ich die URL für meine Spring Boot Webapp
Ich konnte nicht glauben, wie kompliziert die Antwort auf diese scheinbar einfache Frage ist. Hier einige Referenzen:
Es gibt viele verschiedene Dinge zu beachten:
server.context-path=/api
in application.properties
können Sie ein Präfix für alles konfigurieren. (Sein server.context-Pfad ist nicht server.contextPath!)spring.data.rest.base-path
in application.properties
. Normalerweise wird @RestController
dies nicht berücksichtigen. Entsprechend der spring data rest Dokumentation gibt es eine Annotation @BasePathAwareController
, die Sie dafür verwenden können. Ich habe jedoch Probleme mit Spring-Security, wenn ich versuche, einen solchen Controller abzusichern. Es wird nicht mehr gefunden.Eine andere Problemumgehung ist ein einfacher Trick. Sie können einer Annotation keinen statischen String voranstellen, Sie können jedoch Ausdrücke wie folgt verwenden:
@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\"}";
}
}
Da dies der erste Google-Treffer für das Problem ist, gehe ich davon aus, dass mehr Leute danach suchen werden. Es gibt eine neue Option seit Spring Boot '1.4.0' . Es ist jetzt möglich, ein benutzerdefiniertes RequestMappingHandlerMapping zu definieren, mit dem ein anderer Pfad für mit @RestController kommentierte Klassen definiert werden kann
Eine andere Version mit benutzerdefinierten Anmerkungen, die @RestController mit @RequestMapping kombiniert, finden Sie unter diesem Blogbeitrag
@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);
}
};
}
};
}
}
Für die Version des Spring Boot Frameworks 2.0.4.RELEASE+
. Diese Zeile zu application.properties
hinzufügen
server.servlet.context-path=/api
Für Boot 2.0.0+ funktioniert das für mich: server.servlet.context-path =/api
Ich habe eine saubere Lösung gefunden, die nur Restcontroller betrifft.
@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 registriert zwei Dispatcher-Servlets - Standard dispatcherServlet
für Controller und restApi
Dispatcher für @RestControllers
in rest.xml
definiert:
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 [/]
Das Beispiel 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>
Aber du bist nicht beschränkt auf :
XmlWebApplicationContext
, können Sie jeden anderen verfügbaren Kontexttyp verwenden, z. AnnotationConfigWebApplicationContext
, GenericWebApplicationContext
, GroovyWebApplicationContext
, ...jsonMessageConverter
, messageConverters
-Beans im Ruhekontext. Sie können im übergeordneten Kontext definiert werdenIch bin vielleicht ein bisschen spät dran, ABER ... ich glaube, es ist die beste Lösung. Richten Sie es in Ihrer application.yml (oder der analogen Konfigurationsdatei) ein:
spring:
data:
rest:
basePath: /api
Wenn ich mich erinnern kann, ist das alles - alle Ihre Repositorys werden unter dieser URI angezeigt.
Sie können eine benutzerdefinierte Anmerkung für Ihre Controller erstellen:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}
Verwenden Sie sie anstelle des üblichen @RestController in Ihren Controller-Klassen und kommentieren Sie Methoden mit @RequestMapping.
Gerade getestet - funktioniert im Frühjahr 4.2!
Sie können eine Basisklasse mit @RequestMapping("rest")
-Anmerkungen erstellen und alle anderen Klassen mit dieser Basisklasse erweitern.
@RequestMapping("rest")
public abstract class BaseController {}
Jetzt sind alle Klassen, die diese Basisklasse erweitern, unter rest/**
verfügbar.
Mit Spring-Boot 2.x können Sie in application.properties Folgendes konfigurieren:
spring.mvc.servlet.path=/api
funktionierte server.contextPath =/path
Per Spring Data REST docs , wenn Sie application.properties verwenden, verwenden Sie diese Eigenschaft, um Ihren Basispfad festzulegen:
spring.data.rest.basePath=/api
Beachten Sie jedoch, dass Spring verwendetentspannte Bindung , so dass diese Variante verwendet werden kann:
spring.data.rest.base-path=/api
... oder dieses, wenn Sie es vorziehen:
spring.data.rest.base_path=/api
Bei Verwendung von application.yml würden Sie Doppelpunkte als Schlüsseltrennzeichen verwenden:
spring:
data:
rest:
basePath: /api
(Als Referenz wurde im März 2018 ein zugehöriges Ticket erstellt, um die Dokumente zu verdeutlichen.)
Diese Lösung gilt, wenn:
RestController
ein Präfix voranstellen, jedoch nicht Controller
.Sie verwenden Spring Data Rest nicht.
@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);
}
}
}
Dies ist ähnlich zu der Lösung , die von mh-dev veröffentlicht wurde, aber ich denke, dass dies ein wenig sauberer ist und dies sollte in jeder Version von Spring Boot 1.4.0+, einschließlich 2.0.0+, unterstützt werden.