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') .

Les contrôleurs Mvc

devraient être accessibles par example.com/whatever

est-ce possible?

(Je n'utilise pas spring data rest, mais spring mvc)

62
demandé sur M. Deinum 2015-10-04 01:02:50

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

ref link: https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri

25
répondu Suroj 2018-09-22 04:59:53

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

80
répondu OriolBG 2017-05-23 12:02:41

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);
                    }
                };
            }
        };
    }
}
19
répondu mh-dev 2016-10-07 00:34:45

Je ne pouvais pas croire à quel point la réponse à cette question apparemment simple est compliquée. Voici quelques références:

il y a beaucoup de choses différentes à considérer:

  1. en positionnant server.context-path=/api dans application.properties vous pouvez configurer un préfixe pour tout .(Son serveur.contexte-chemin pas de serveur.contextPath !)
  2. 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 dans application.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\"}";
  }
}
19
répondu Robert 2017-05-23 10:31:18

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
7
répondu kravemir 2016-06-07 14:06:45

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.

6
répondu thorinkor 2016-10-08 07:01:27

pour Boot 2.0.0+ cela fonctionne pour moi: server.servlet.context-path = / api

5
répondu Juan Carlos Vergara Santos 2018-06-17 23:26:59

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!

4
répondu Ilya Novoseltsev 2015-10-05 08:15:09

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/** .

4
répondu Saket Mehta 2016-12-28 13:49:22

Pour le printemps de démarrage framework version 2.0.4.RELEASE+ . Ajouter cette ligne à application.properties

server.servlet.context-path=/api
2
répondu shellhub 2018-09-03 06:43:04

Cette solution s'applique si:

  1. vous voulez préfixer RestController mais pas Controller .
  2. 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+.

0
répondu The Gilbert Arenas Dagger 2018-08-11 20:11:53