İlkbahar açılışında dinlenme için temel URL nasıl ayarlanır?


118

Tek bir yaylı önyükleme projesinde mvc'yi karıştırmaya ve dinlenmeye çalışıyorum.

Tüm dinlenme denetleyicileri (örn. Example.com/api) için temel yolu tek bir yerde ayarlamak istiyorum ( @RequestMapping('api/products')bunun yerine her denetleyiciye yalnızca @RequestMapping('/products').

Mvc denetleyicilerine example.com/whatever adresinden erişilebilir olmalıdır.

Mümkün mü?

(Spring data rest kullanmıyorum, sadece spring mvc kullanıyorum)



server.servlet.contextPath = / api
Daniel T. Sobrosa

spring boot version 2.1.4.RELEASE, spring.mvc.servlet.path = / api ve server.servlet.context-path = / api, her ikisi de çalışır
Prayag Sharma

server.servlet.context-path = / api çözümü sadece REST için değil, UYGULAMA içindir. SOAP servisleri için de geçerlidir. SOAP ve REST hizmetleri yolunuzu ayırmak istiyorsanız, @RequestMapping ('api / ...') ... medium.com/@bm.celalkartal/…
bmck

Yanıtlar:


89

Spring Boot 1.2+ (<2.0) ile tek gereken, application.properties dosyasındaki tek bir özelliktir:

spring.data.rest.basePath=/api

ref bağlantısı: https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri

2.x için kullanın

server.servlet.context-path=/api

4
Thorinkor'un verdiği kesin cevap bu.
Jean-François Beauchef

8
Teşekkürler, ama bu Spring Boot sürüm v1.5.7.RELEASE'de benim için çalışmıyor. Diğer yanıt server.contextPath = / api çalıştı
Jay

10
@Suroj Bu çözüm yalnızca RepositoryRestController açıklamalı denetleyicilerle çalışır, RestController ile çalışmaz ...
Nano

jira.spring.io/browse/DATAREST-1211 Bu Jira Bileti, "Spring Boot 2.0.0 için spring.data.rest.base-yolu" olduğundan bahseder. Ne yazık ki ikisi de benim için çalışmıyor.
Carsten Hagemann

6
SB 2+ için server.servlet.context-path = / url
vicky

96

Biraz geç ama aynı soru beni cevaba ulaşmadan buraya getirdi, bu yüzden buraya postaladım. Bir application.properties oluşturun (hala sahip değilseniz) ve ekleyin

server.contextPath=/api

Dolayısıyla, önceki örnekte, bir RestController'ınız @RequestMapping("/test")varsa, ona aşağıdaki gibi erişeceksiniz.localhost:8080/api/test/{your_rest_method}

soru kaynağı: ilkbahar önyükleme web uygulamamın url'sini nasıl seçerim


19
Bunu yalnızca RestControllers ile çalışmak ve normal Denetleyicilere "/ api" olmadan erişmek için nasıl zorlarsınız
Siya Sosibo

@Stoan Çözüm buldum, cevabımı kontrol et :-)
kravemir

Bunu yapma! Thorinkor'un cevabına bakın.
Stefan

Thorinkor'un cevabı özellikle Spring Data REST içindir.

8
server.contextPath artık kullanımdan kaldırılmıştır, bunun yerine server.servlet.context-path'i kullanın
DS.

46

Yaylı önyükleme çerçeve sürümü için 2.0.4.RELEASE+. Bu satırı şuraya ekle:application.properties

server.servlet.context-path=/api

1
Bu aynı zamanda ortak klasörü de etkiler :-(
Michel

5
bu, Spring boot 2+ için doğru cevaptır. spring.data.rest.basePathSpring boot 2 için çalışmıyor
jackycflau

27

Bu, sorunun ilk Google isabeti olduğundan ve daha fazla insanın bunu arayacağını varsayıyorum. Spring Boot '1.4.0'dan beri yeni bir seçenek var. Artık, not verilen sınıflar için farklı bir yol tanımlamaya izin veren özel bir RequestMappingHandlerMapping tanımlamak mümkün. @RestController

Özel ek açıklamalarla farklı bir versiyonu birleştirir o @RestController ile @ RequestMapping bu adreste bulunabilir 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);
                    }
                };
            }
        };
    }
}

2
Spring Boot 2.0.0+ sürümünde, doğrudan WebMvcRegistrations arayüzünden çalışın. Arayüze varsayılan yöntemler eklemek adına WebMvcRegistrationsAdapter kaldırıldı.
Gilbert Arenas Hançer

27

Görünüşte basit olan bu sorunun cevabının ne kadar karmaşık olduğuna inanamadım. İşte bazı referanslar:

Dikkate alınması gereken birçok farklı şey var:

  1. Ayarlayarak server.context-path=/apiiçinde application.propertiessizin için bir önek yapılandırabilirsiniz her şeyi . (Onun server.context-yolu değil server.contextPath!)
  2. Bahar Veri kontrolörleri ortam değişkeni kullanacak dinlenme son nokta olarak bir depo maruz olduğunu @RepositoryRestController ile açıklamalı spring.data.rest.base-pathiçinde application.properties. Ama Plain @RestControllerbunu hesaba katmaz. Yay veri dinlenme belgelerine göre, bunun @BasePathAwareControlleriçin kullanabileceğiniz bir açıklama vardır. Ancak böyle bir denetleyicinin güvenliğini sağlamaya çalıştığımda Bahar güvenliği ile ilgili sorunlar yaşıyorum. Artık bulunamadı.

Başka bir geçici çözüm basit bir numaradır. Bir ek açıklamada statik bir Dizenin önüne ekleyemezsiniz, ancak aşağıdaki gibi ifadeler kullanabilirsiniz:

@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\"}";
  }
}

Ek Açıklamaya nasıl eklersiniz?
Teimuraz

2
meh, o zaman her yeni kontrolör oluşturduğunuzda bu öneki eklemeyi unutmamalısınız
The Gilbert Arenas Dagger

13

Boot 2.0.0+ için bu benim için çalışıyor: server.servlet.context-path = / api


4
Her şeyi / api'nin altına koyan, sadece @RestController haritacıları değil. Yinede teşekkürler. Bilgileriniz hala yararlıdır.
eigil

9

Sadece dinlenme kontrolörlerini etkileyen temiz bir çözüm buldum.

@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 iki dağıtıcı sunucu uygulamasını kaydeder - dispatcherServletdenetleyiciler için varsayılan ve restApişurada @RestControllerstanımlandığı üzere dağıtıcı 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 [/]

Örnek 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>

Ancak bunlarla sınırlı değilsiniz :

  • kullanım XmlWebApplicationContext, mevcut herhangi bir bağlam türünü kullanabilirsiniz, yani AnnotationConfigWebApplicationContext, GenericWebApplicationContext, GroovyWebApplicationContext, ...
  • tanımla jsonMessageConverter, messageConvertersdinlenme bağlamında fasulye, ebeveyn bağlamında tanımlanabilirler

Bunu xml kullanmadan programlı olarak yapmak mümkün mü?
Arian

@ArianHosseinzadeh Evet. Bunu programlı olarak yapmak mümkündür. Yay bağlamını kurmanın birçok yolu vardır. Örnekte, REST API işleme için alt bağlamın nasıl oluşturulacağını gösterdim. Sadece Java içinde bağlamı nasıl kuracağınızı öğrenin ve sonra bu bilgiyi bu cevapta bilgiyle birleştirin. Buna programlama denir.
kravemir

7

Denetleyicileriniz için özel bir açıklama oluşturabilirsiniz:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@RestController
@RequestMapping("/test")
public @interface MyRestController {
}

Denetleyici sınıflarınızda normal @RestController yerine kullanın ve @RequestMapping ile yöntemlere açıklama ekleyin.

Yeni test edildi - 4.2 Baharında çalışıyor!


Teşekkür ederim. Bunu denedim. Ama şimdi her yönteme @RequestMapping ("/ products"), @RequestMapping ("/ products / {id}") ile açıklama eklemem gerekiyor. Bunun yerine Denetleyiciye @RequestMapping ("/ products") ve @RequestMapping, @RequestMapping ("/: id") ile yöntemlere açıklama eklemem gerekiyor. Ve ürün denetleyicisi api / ürünlerde erişilebilir olmalıdır (ör. API ön ekini tek bir yerde ayarlayın)
Teimuraz

2
O halde hayır, kutudan çıkan bir çözüm yok, AFAIK. Kendinizinkini uygulamayı deneyebilirsiniz RequestMappingHandlerMapping. Spring Data REST, ihtiyacınız olana benzer bir eşleyiciye sahiptir - BasePathAwareHandlerMapping.
Ilya Novoseltsev

@moreo, uygun bir çözüm buldun mu? Bir cevap olarak gönderebilirseniz sevinirim. Burada da aynı gereksinime sahibim.
fischermatte

@fischermatte, Hayır, tam olarak istediğimi bulamadım, @RequestMapping ("/ api / products") veya @RequestMapping ("/ api / users") her denetleyici sınıfının önüne ve ardından yöntemden önce başka bir @ RequestMapping ( "/ {id}"). Ama bunun büyük bir sorun olduğunu sanmıyorum, "api" yi bir şeye değiştirmek istersem, her dersin başında değiştiririm.
Teimuraz

@IlyaNovoseltsev Bir çözüm var, cevabıma bakın :-)
kravemir

7

Biraz geç kalmış olabilirim, AMA ... Bunun en iyi çözüm olduğuna inanıyorum. Application.yml (veya analog yapılandırma dosyanızda) kurun:

spring:
    data:
        rest:
            basePath: /api

Hatırlayabildiğim kadarıyla bu kadar - tüm depolarınız bu URI'nin altında açığa çıkacak.


Bunu biraz açıklayabilir veya ilgili bir dokümantasyona işaret edebilir misiniz?
Dmitry Serdiuk


11
environemnt değişkeni spring.data.rest.base-path yalnızca bahar verilerini ve bahar nefretlerini etkiler. Düz @RestController hala kökte kalacak!
Robert

4
@thorinkor, çoğu durumda insanların Spring Data REST depolarını oluşturacağını söylediğinize dayanarak? Ve OP açıkça dinlenme kontrolörleri olduğunu söylüyor ...
Jean-François Beauchef

1
Sadece SpringDataRest kullanıyorsanız işe yarayacağını düşünüyorum.
Jaumzera

6

Bir PathMatchConfigurer (Spring Boot 2.x) kullanmayı deneyin:

@Configuration
public class WebMvcConfig implements WebMvcConfigurer  {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        configurer.addPathPrefix("api", HandlerTypePredicate.forAnnotation(RestController.class));
    }
}

1
Teşekkürler, tam olarak aradığım buydu! Bu, spring.data.rest.base-yolunun yaptığına benzer şekilde, bu WebMvcConfig aracılığıyla yapılandırılan tüm RestControllers için bir bağlam yolu öğesi ayarlamanıza olanak tanır.
Buurman

Cevabınız @HaraldWendel'de: +1: Kodunuzun tam olarak ne yaptığını açıklamak gibi (benim yorumumda yapmaya çalıştığım gibi) ve / veya belki de bağlantı oluşturarak onu biraz daha genişleterek onu biraz daha geliştirebilirsiniz. bu kullanımı açıklayan bazı javadoc veya belgeler.
Buurman

Denetleyici arayüzlerini kullandığım için benim için çalışan tek çözüm bu
Anatoly Yakimchuk

4

@RequestMapping("rest")Ek açıklamalarla bir temel sınıf oluşturabilir ve diğer tüm sınıflarınızı bu temel sınıfla genişletebilirsiniz.

@RequestMapping("rest")
public abstract class BaseController {}

Şimdi bu temel sınıfı genişleten tüm sınıflara adresinden erişilebilir rest/**.


3
Bu doğru cevap değil, kullanıcı Kontrolör ek açıklamasına atıfta bulunuyor. Soyut bir sınıfı bir RequestMapping ek açıklamasıyla genişletirseniz ve yeni sınıfın da bir RequestMapping'i varsa, bu sonuncusu ilkini geçersiz kılar, ikisini birleştirmez.
Massimo

Meta ek açıklamayı miras almadığı sürece ek açıklamaların java'da miras alınmadığını biliyor musunuz? Şunu kontrol edin: stackoverflow.com/a/21409651 . Ve @RequestMapping buna sahip görünmüyor: docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
Mashrur

3

YAML yapılandırmasını kullananlar için (application.yaml).

Not : bu yalnızcaSpring Boot 2.x.x

server:
  servlet:
    contextPath: /api

Hala kullanıyorsanız Spring Boot 1.x

server:
  contextPath: /api

1

Spring-boot 2.x ile application.properties içinde yapılandırabilirsiniz:

spring.mvc.servlet.path=/api

1

server.servlet.context-path=/apiçözüm olacağını tahmin ediyorum. Ben de aynı sorunu yaşadım ve bu beni çözdü. Server.context-path kullandım. Ancak, bu kullanımdan kaldırılmış gibi görünüyordu ve server.servlet.context-pathşimdi sorunu çözdüğünü gördüm . Bulduğum başka bir geçici çözüm, ön uç (H5) sayfalarıma bir temel etiket eklemekti. Umarım bu oradaki birine yardımcı olur.

Şerefe


0

Bu çözüm şu durumlarda geçerlidir:

  1. Önek istiyorsun RestControllerama istemiyorsun Controller.
  2. Spring Data Rest kullanmıyorsunuz.

    @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);
        }
    }

    }

Bu, mh-dev tarafından yayınlanan çözüme benzer , ancak bunun biraz daha temiz olduğunu ve 2.0.0+ dahil olmak üzere Spring Boot 1.4.0+ sürümünün herhangi bir sürümünde desteklenmesi gerektiğini düşünüyorum.


RestControler'ımda Pageable kullanıyorsam, api / something bana org.springframework.data.domain.Pageable arabirimi için birincil veya varsayılan kurucu bulunamadı
K.Ayoub

0

Spring Data REST belgelerine göre , application.properties kullanılıyorsa, temel yolunuzu ayarlamak için bu özelliği kullanın:

spring.data.rest.basePath=/api

Ancak Spring'in rahat ciltleme kullandığına dikkat edin , bu nedenle bu varyasyon kullanılabilir:

spring.data.rest.base-path=/api

... veya tercih ederseniz bu:

spring.data.rest.base_path=/api

Application.yml kullanıyorsanız , anahtar ayırıcılar için iki nokta üst üste kullanırsınız:

spring:
  data:
    rest:
      basePath: /api

(Referans için, belgeleri açıklığa kavuşturmak için Mart 2018'de ilgili bir bilet oluşturuldu.)



0

Denetleyicileriniz için özel bir açıklama oluşturabilirsiniz:

Denetleyici sınıflarınızda normal @RestController yerine kullanın ve @RequestMapping ile yöntemlere açıklama ekleyin.

Bahar 4.2'de iyi çalışıyor!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.