J'essaie de mélanger du MVC et de rester dans un seul projet de bottes de printemps.
Je veux définir le chemin de base pour tous les contrôleurs de repos (par exemple, exemple.com/api)au même endroit (je ne veux pas annoter chaque contrôleur avec @RequestMapping('api/products')
, mais plutôt @RequestMapping('/products')
.
Les contrôleurs MVC doivent être accessibles à example.com/whats
C'est possible?
(Je n'utilise pas le reste des données de printemps, juste le printemps mvc)
Avec Spring Boot 1.2+, une seule propriété dans application.properties suffit:
spring.data.rest.basePath=/api
lien de référence: https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri
Un peu en retard mais la même question m’a amené ici avant d’arriver à la réponse, je la poste donc ici . Créez (si vous ne l’avez pas encore) un application.properties et ajoutez
server.contextPath=/api
Ainsi, dans l'exemple précédent, si vous avez un RestController avec @RequestMapping("/test")
, vous y accéderez comme localhost:8080/api/test/{your_rest_method}
.
source de question: comment puis-je choisir l'URL pour mon webapp de démarrage de printemps
Je ne pouvais pas croire à quel point la réponse à cette question apparemment simple était compliquée. Voici quelques références:
Il y a beaucoup de choses différentes à considérer:
server.context-path=/api
dans application.properties
, vous pouvez configurer un préfixe pour everything. (Son chemin.context-chemin n'est pas server.contextPath!)spring.data.rest.base-path
dans application.properties
. Mais @RestController
ne tiendra pas compte de cela. Selon la documentation des données restantes spring , vous pouvez utiliser une annotation @BasePathAwareController
pour cela. Mais j’ai des problèmes avec Spring-security lorsque j’essaie de sécuriser un tel contrôleur. Il n'est plus trouvé.Une autre solution est un truc simple. Vous ne pouvez pas préfixer une chaîne statique dans une annotation, mais vous pouvez utiliser des expressions telles que:
@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\"}";
}
}
Comme c'est le premier coup Google pour le problème et je suppose que plus de gens le rechercheront. Il y a une nouvelle option depuis Spring Boot '1.4.0' . Il est maintenant possible de définir un RequestMappingHandlerMapping personnalisé permettant de définir un chemin différent pour les classes annotées avec @RestController
Une version différente avec des annotations personnalisées combinant @RestController avec @RequestMapping est disponible à cet emplacement blog post
@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);
}
};
}
};
}
}
Pour la version du cadre de démarrage printanier 2.0.4.RELEASE+
. Ajouter cette ligne à application.properties
server.servlet.context-path=/api
Pour Boot 2.0.0+, cela fonctionne pour moi: server.servlet.context-path =/api
J'ai trouvé une solution propre, qui ne concerne que les contrôleurs de repos.
@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 va enregistrer deux servlets de répartiteur - dispatcherServlet
par défaut pour les contrôleurs et restApi
dispatcher pour @RestControllers
défini dans 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 [/]
L'exemple 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>
Mais vous êtes pas limité à:
XmlWebApplicationContext
, vous pouvez utiliser tout autre type de contexte disponible, c'est-à-dire. AnnotationConfigWebApplicationContext
, GenericWebApplicationContext
, GroovyWebApplicationContext
, ...jsonMessageConverter
, messageConverters
dans un contexte de repos, ils peuvent être définis dans un contexte parentJe pourrais être un peu en retard, MAIS ... Je pense que c'est la meilleure solution. Configurez-le dans votre application.yml (ou votre fichier de configuration analogique):
spring:
data:
rest:
basePath: /api
Si je me souviens bien, tous vos dépôts seront exposés sous cet URI.
Vous pouvez créer une annotation personnalisée pour vos contrôleurs:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}
Utilisez-le à la place de @RestController habituel sur vos classes de contrôleur et annotez les méthodes avec @RequestMapping.
Vient de tester - fonctionne au printemps 4.2!
Vous pouvez créer une classe de base avec des annotations @RequestMapping("rest")
et étendre toutes les autres classes avec cette classe de base.
@RequestMapping("rest")
public abstract class BaseController {}
Désormais, toutes les classes qui étendent cette classe de base seront accessibles à rest/**
.
Avec spring-boot 2.x, vous pouvez configurer dans application.properties:
spring.mvc.servlet.path=/api
serveur.contextPath travaillé =/chemin
Données par printemps REST docs , si vous utilisez application.properties , utilisez cette propriété pour définir votre chemin de base:
spring.data.rest.basePath=/api
Mais notez que Spring utilisereliure détendue , cette variante peut donc être utilisée:
spring.data.rest.base-path=/api
... ou celui-ci si vous préférez:
spring.data.rest.base_path=/api
Si vous utilisez application.yml , vous utiliseriez des deux points pour les séparateurs de clé:
spring:
data:
rest:
basePath: /api
(Pour référence, un ticket associé a été créé en mars 2018 pour clarifier la documentation.)
Cette solution s'applique si:
RestController
mais pas Controller
.Vous n'utilisez pas 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);
}
}
}
Ceci est similaire à solution posté par mh-dev, mais je pense que c'est un peu plus propre et que cela devrait être supporté par toute version de Spring Boot 1.4.0+, y compris 2.0.0+.