Comment définir l'url de base pour le repos dans la botte de printemps?
j'essaie de mélanger mvc et rest dans un seul projet de botte.
je veux définir le chemin de base pour tous les contrôleurs rest (par ex. example.com/api)
dans un seul endroit (Je ne veux pas annoter chaque contrôleur avec @RequestMapping('api/products')
, à la place, juste @RequestMapping('/products')
.
devraient être accessibles par example.com/whatever
est-ce possible?
(Je n'utilise pas spring data rest, mais spring mvc)
11 réponses
avec une botte à ressort 1.2+, il suffit d'une seule propriété dans l'application.propriétés:
spring.data.rest.basePath=/api
Un peu en retard, mais la même question m'a amené ici avant d'atteindre la réponse donc je poste ici. Créer (Si vous ne l'avez toujours pas) une application.propriétés et ajouter
server.contextPath=/api
donc 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}
question source: Comment puis-je choisir l'url de ma webapp de démarrage de printemps
depuis qu'il s'agit du premier google hit pour le problème et je suppose que plus de gens vont chercher pour cela. Il y a une nouvelle option depuis le démarrage du ressort '1.4.0'. Il est maintenant possible de définir un chemin personnalisé RequestMappingHandlerMapping qui permet de définir un chemin différent pour les classes annotées avec @RestController 151960920"
une version différente avec des annotations personnalisées qui combine @RestController avec @RequestMapping peut être trouvé à ce post de blog
@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);
}
};
}
};
}
}
Je ne pouvais pas croire à quel point la réponse à cette question apparemment simple est compliquée. Voici quelques références:
- Printemps JIRA Billet
- un Autre DONC, la question
- encore une autre question
- très beau GitRepository qui présente le problème
il y a beaucoup de choses différentes à considérer:
- en positionnant
server.context-path=/api
dansapplication.properties
vous pouvez configurer un préfixe pour tout .(Son serveur.contexte-chemin pas de serveur.contextPath !) - les contrôleurs de données de printemps annotés avec @RepositoryRestController qui exposent un dépôt comme point de repos utiliseront la variable d'environnement
spring.data.rest.base-path
dansapplication.properties
. Mais la plaine@RestController
n'en tiendra pas compte. Selon la documentation de repos de données de ressort il y a une annotation@BasePathAwareController
que vous pouvez utiliser pour cela. Mais j'ai des problèmes avec la sécurité des ressorts lorsque j'essaie de sécuriser un tel contrôleur. Il n'est pas plus trouvée.
une autre solution est un tour simple. Vous ne pouvez pas préfixer une chaîne statique dans une annotation, mais vous pouvez utiliser des expressions comme celle-ci:
@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\"}";
}
}
j'ai trouvé une solution propre, qui affecte seulement 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 enregistrera deux servlets de répartiteur - défaut dispatcherServlet
pour les contrôleurs, et restApi
répartiteur 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é à :
- utilisez
XmlWebApplicationContext
, vous pouvez utiliser n'importe quel autre type de contexte disponible, c.-à-d.AnnotationConfigWebApplicationContext
,GenericWebApplicationContext
,GroovyWebApplicationContext
, ... - définir
jsonMessageConverter
,messageConverters
haricots en reste contexte, ils peuvent être définis dans le contexte parent
je suis peut-être un peu en retard, mais... Je crois que c'est la meilleure solution. Mis en place dans votre application.yml (ou fichier de configuration analogique):
spring:
data:
rest:
basePath: /api
comme je me souviens que c'est tout - TOUS vos dépôts seront exposés sous cette URI.
pour Boot 2.0.0+ cela fonctionne pour moi: server.servlet.context-path = / api
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 l'habituel @RestController sur vos classes de controller et annotez les méthodes avec @RequestMapping.
vient D'être testé-fonctionne au printemps 4.2!
vous pouvez créer une classe de base avec @RequestMapping("rest")
annotations et étendre toutes les autres classes avec cette classe de base.
@RequestMapping("rest")
public abstract class BaseController {}
maintenant toutes les classes qui étendent cette classe de base seront accessibles à rest/**
.
Pour le printemps de démarrage framework version 2.0.4.RELEASE+
. Ajouter cette ligne à application.properties
server.servlet.context-path=/api
Cette solution s'applique si:
- vous voulez préfixer
RestController
mais pasController
. -
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); } }
}
c'est similaire à la solution posté par mh-dev, mais je pense que c'est un peu plus propre et cela devrait être pris en charge sur n'importe quelle version de la botte à ressort 1.4.0+, y compris 2.0.0+.