wake-up-neo.net

Wie lege ich die Basis-URL für den Rest des Springboots fest?

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)

68
Teimuraz

Mit Spring Boot 1.2+ benötigen Sie lediglich eine einzige Eigenschaft in application.properties:

spring.data.rest.basePath=/api

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

33
Suroj

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

83
OriolBG

Ich konnte nicht glauben, wie kompliziert die Antwort auf diese scheinbar einfache Frage ist. Hier einige Referenzen:

Es gibt viele verschiedene Dinge zu beachten: 

  1. Durch Setzen von 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!)
  2. Mit @RepositoryRestController annotierte Spring Data-Controller, die ein Repository als Restendpunkt verfügbar machen, verwenden die Umgebungsvariable 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\"}";
  }
}
21
Robert

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);
                    }
                };
            }
        };
    }
}
21
mh-dev

Für die Version des Spring Boot Frameworks 2.0.4.RELEASE+. Diese Zeile zu application.properties hinzufügen

server.servlet.context-path=/api
20
shellhub

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 :

  • verwenden Sie XmlWebApplicationContext, können Sie jeden anderen verfügbaren Kontexttyp verwenden, z. AnnotationConfigWebApplicationContext, GenericWebApplicationContext, GroovyWebApplicationContext, ...
  • definieren Sie jsonMessageConverter, messageConverters-Beans im Ruhekontext. Sie können im übergeordneten Kontext definiert werden
7
kravemir

Ich 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.

7
thorinkor

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!

5

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.

4
Saket Mehta

Mit Spring-Boot 2.x können Sie in application.properties Folgendes konfigurieren:

spring.mvc.servlet.path=/api
1
Bulgar Sadykov

funktionierte server.contextPath =/path

0
Pravin

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

0
J Woodchuck

Diese Lösung gilt, wenn:

  1. Sie möchten RestController ein Präfix voranstellen, jedoch nicht Controller.
  2. 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.