Làm thế nào để đặt url cơ sở cho phần còn lại trong khởi động mùa xuân?


118

Tôi đang cố gắng kết hợp mvc và nghỉ ngơi trong một dự án khởi động mùa xuân duy nhất.

Tôi muốn đặt đường dẫn cơ sở cho tất cả các bộ điều khiển nghỉ (ví dụ: example.com/api) ở một nơi duy nhất ( @RequestMapping('api/products')thay vào đó, tôi không muốn chú thích từng bộ điều khiển bằng @RequestMapping('/products').

Bộ điều khiển Mvc phải có thể truy cập được bằng example.com/w Anything

Có khả thi không?

(Tôi không sử dụng phần còn lại dữ liệu mùa xuân, chỉ sử dụng mùa xuân mvc)



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

phiên bản khởi động mùa xuân 2.1.4.RELEASE, spring.mvc.servlet.path = / api và server.servlet.context-path = / api, cả hai đều hoạt động
Prayag Sharma

server.servlet.context-path = / api giải pháp dành cho ỨNG DỤNG, không chỉ REST. Nó cũng hợp lệ cho các dịch vụ SOAP. Nếu bạn muốn trình bày đường dẫn dịch vụ SOAP và REST của mình, bạn nên sử dụng @RequestMapping ('api / ...') ... medium.com/@bm.celalkartal/…
bmck

Câu trả lời:


89

Với Spring Boot 1.2+ (<2.0), tất cả những gì cần là một thuộc tính duy nhất trong application.properties:

spring.data.rest.basePath=/api

liên kết tham chiếu: https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.chacting-base-uri

Đối với 2.x, sử dụng

server.servlet.context-path=/api

4
Đây là câu trả lời chính xác mà thorinkor đã đưa ra.
Jean-François Beauchef

8
Cảm ơn, nhưng điều này không hiệu quả với tôi trong phiên bản Spring Boot v1.5.7.RELEASE. Câu trả lời khác server.contextPath = / api đã hoạt động
Jay

10
@Suroj giải pháp đó chỉ làm việc với RepositoryRestController chú thích các bộ điều khiển, không phải với RestController ...
Nano

jira.spring.io/browse/DATAREST-1211 Vé Jira này đề cập nó là "spring.data.rest.base-path cho Spring Boot 2.0.0". Đáng buồn thay, cả hai đều không hiệu quả với tôi.
Carsten Hagemann

6
cho SB 2+ đó là server.servlet.context-path = / url
vicky

96

Hơi muộn nhưng câu hỏi tương tự đã đưa tôi đến đây trước khi đạt được câu trả lời nên tôi đăng nó ở đây. Tạo (nếu bạn vẫn chưa có) một application.properties và thêm

server.contextPath=/api

Vì vậy, trong ví dụ trước nếu bạn có RestController bên @RequestMapping("/test")mình, bạn sẽ truy cập nó nhưlocalhost:8080/api/test/{your_rest_method}

nguồn câu hỏi: làm cách nào để chọn url cho ứng dụng web khởi động mùa xuân của tôi


19
Làm cách nào để bạn thực thi điều này để chỉ hoạt động với RestControllers và truy cập vào Bộ điều khiển bình thường mà không có "/ api"
Siya Sosibo

@Stoan tôi tìm thấy giải pháp, kiểm tra câu trả lời của tôi :-)
kravemir

Đừng làm điều này! Hãy xem câu trả lời của thorinkor.
Stefan

Câu trả lời của Thorinkor dành riêng cho Spring Data REST.

8
server.contextPath hiện không được dùng nữa, hãy sử dụng server.servlet.context-path để thay thế
DS.

46

Đối với phiên bản khung khởi động mùa xuân 2.0.4.RELEASE+. Thêm dòng này vàoapplication.properties

server.servlet.context-path=/api

1
Điều này cũng ảnh hưởng đến thư mục công cộng :-(
Michel

5
đây là câu trả lời chính xác cho Spring boot 2+. spring.data.rest.basePathkhông làm việc cho mùa xuân khởi động 2
jackycflau

27

Vì đây là lần đầu tiên google giải quyết vấn đề và tôi cho rằng sẽ có nhiều người tìm kiếm vấn đề này hơn. Có một tùy chọn mới kể từ Spring Boot '1.4.0'. Bây giờ có thể xác định một RequestMappingHandlerMapping tùy chỉnh cho phép xác định một đường dẫn khác cho các lớp được chú thích bằng @RestController

Bạn có thể tìm thấy một phiên bản khác với các chú thích tùy chỉnh kết hợp @RestController với @RequestMapping tại bài đăng trên blog này

@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
Trong Spring Boot 2.0.0+, hãy làm việc trực tiếp với giao diện WebMvcRegistrations. WebMvcRegistrationsAdapter đã bị loại bỏ để thêm các phương thức mặc định vào giao diện.
The Gilbert Arenas Dagger

27

Tôi không thể tin được câu trả lời cho câu hỏi tưởng chừng đơn giản này lại phức tạp đến mức nào. Dưới đây là một số tài liệu tham khảo:

Có nhiều điều khác nhau cần xem xét:

  1. Bằng cách cài đặt server.context-path=/apitrong application.propertiesbạn có thể định cấu hình tiền tố cho mọi thứ . (Server.context-path của nó không phải server.contextPath!)
  2. Bộ điều khiển Spring Data được chú thích bằng @RepositoryRestController để hiển thị một kho lưu trữ dưới dạng điểm cuối còn lại sẽ sử dụng biến môi trường spring.data.rest.base-pathtrong application.properties. Nhưng đơn giản @RestControllersẽ không tính đến điều này. Theo tài liệu phần còn lại dữ liệu mùa xuân, có một chú thích @BasePathAwareControllermà bạn có thể sử dụng cho việc đó. Nhưng tôi gặp sự cố liên quan đến Spring-security khi cố gắng bảo vệ một bộ điều khiển như vậy. Nó không được tìm thấy nữa.

Một cách giải quyết khác là một thủ thuật đơn giản. Bạn không thể đặt trước một Chuỗi tĩnh trong một chú thích, nhưng bạn có thể sử dụng các biểu thức như sau:

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

Bạn sẽ đưa vào Annotation như thế nào?
Teimuraz

2
meh, sau đó bạn luôn phải nhớ để thêm tiền tố này mỗi khi bạn tạo một bộ điều khiển mới
Các Gilbert Arenas Dagger

13

Đối với Boot 2.0.0+, điều này phù hợp với tôi: server.servlet.context-path = / api


4
Điều đó dường như đặt mọi thứ dưới / api, không chỉ @RestController mappers. Nhưng dù gì cũng cảm ơn. Thông tin của bạn vẫn hữu ích.
eigil

9

Tôi đã tìm thấy một giải pháp sạch, chỉ ảnh hưởng đến bộ điều khiển nghỉ.

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

Khởi động mùa xuân sẽ đăng ký hai servlet điều phối viên - mặc định dispatcherServletcho bộ điều khiển và trình restApiđiều phối cho @RestControllersđược xác định trong 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 [/]

Ví dụ 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>

Tuy nhiên, bạn không bị giới hạn ở :

  • sử dụng XmlWebApplicationContext, bạn có thể sử dụng bất kỳ loại ngữ cảnh nào khác có sẵn, tức là. AnnotationConfigWebApplicationContext, GenericWebApplicationContext, GroovyWebApplicationContext, ...
  • xác định jsonMessageConverter, messageConvertersbean trong ngữ cảnh nghỉ, chúng có thể được xác định trong ngữ cảnh mẹ

Có thể thực hiện việc này theo chương trình mà không cần sử dụng xml không?
Arian

@ArianHosseinzadeh Có. Có thể làm điều đó theo chương trình. Có nhiều cách để thiết lập bối cảnh mùa xuân. Trong ví dụ, tôi đã trình bày cách tạo ngữ cảnh con để xử lý API REST. Chỉ cần học cách thiết lập ngữ cảnh trong Java, sau đó kết hợp kiến ​​thức đó với kiến ​​thức trong câu trả lời này. Đó được gọi là lập trình.
kravemir

7

Bạn có thể tạo chú thích tùy chỉnh cho bộ điều khiển của mình:

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

Sử dụng nó thay vì @RestController thông thường trên các lớp bộ điều khiển của bạn và chú thích các phương thức với @RequestMapping.

Vừa được thử nghiệm - hoạt động trong Spring 4.2!


Cảm ơn bạn. Tôi đã thử cái này. Nhưng bây giờ tôi phải chú thích từng phương thức bằng @RequestMapping ("/ products"), @RequestMapping ("/ products / {id}"). Thay vào đó, tôi cần chú thích Bộ điều khiển với @RequestMapping ("/ products") và các phương thức với @RequestMapping, @RequestMapping ("/: id"). Và các sản phẩm điều khiển nên accesable tại api / sản phẩm (ví dụ như bộ api tiền tố trong một nơi duy nhất)
Teimuraz

2
Trong trường hợp đó, không, không có giải pháp nào khác, AFAIK. Bạn có thể thử thực hiện của riêng bạn RequestMappingHandlerMapping. Spring Data REST có một trình ánh xạ tương tự như những gì bạn cần - BasePathAwareHandlerMapping.
Ilya Novoseltsev

@moreo, bạn đã tìm ra giải pháp thích hợp chưa? Tôi rất vui nếu bạn có thể đăng nó như một phản hồi. tôi có cùng một yêu cầu ở đây.
fischermatte

@fischermatte, Không, tôi không tìm thấy chính xác thứ mình muốn, tôi đặt @RequestMapping ("/ api / products") hoặc @RequestMapping ("/ api / users") trước mỗi lớp bộ điều khiển và sau đó, trước phương thức chỉ khác @ RequestMapping ("/ {id}"). Nhưng tôi không nghĩ đây là một vấn đề lớn, nếu tôi muốn thay đổi "api" thành một cái gì đó, tôi sẽ chỉ thay đổi nó trong đầu mỗi lớp.
Teimuraz

@IlyaNovoseltsev Có một giải pháp, hãy xem câu trả lời của tôi :-)
kravemir

7

Tôi có thể đến muộn một chút, NHƯNG ... Tôi tin rằng đó là giải pháp tốt nhất. Thiết lập nó trong application.yml của bạn (hoặc tệp cấu hình tương tự):

spring:
    data:
        rest:
            basePath: /api

Như tôi có thể nhớ đó là nó - tất cả các kho của bạn sẽ được hiển thị bên dưới URI này.


Bạn có thể giải thích điều này một chút hoặc chỉ vào một tài liệu liên quan không?
Dmitry Serdiuk


11
biến environemnt spring.data.rest.base-path chỉ ảnh hưởng đến spring-data-rest và spring-hateoas. Plain @RestController vẫn sẽ nằm ở gốc!
Robert

4
@thorinkor dựa trên điều bạn đang nói rằng trong hầu hết các trường hợp, mọi người sẽ xây dựng kho lưu trữ Spring Data REST? Và OP đang nói rõ ông có bộ điều khiển phần còn lại ...
Jean-François Beauchef

1
Tôi nghĩ rằng nó sẽ chỉ hoạt động nếu bạn đang sử dụng SpringDataRest.
Jaumzera

6

Hãy thử sử dụng PathMatchConfigurer (Spring Boot 2.x):

@Configuration
public class WebMvcConfig implements WebMvcConfigurer  {

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

1
Cảm ơn, đây chính xác là những gì tôi đang tìm kiếm! Điều này cho phép bạn đặt phần tử đường dẫn ngữ cảnh cho tất cả các RestControllers được định cấu hình thông qua WebMvcConfig này, tương tự như những gì spring.data.rest.base-path thực hiện.
Buurman

Câu trả lời của bạn có trên @HaraldWendel: +1: Bạn có thể cải thiện nó một số chi tiết bằng cách mở rộng nó một chút, như giải thích chính xác mã của bạn làm gì (như tôi đã cố gắng làm trong nhận xét của mình) và / hoặc có thể liên kết đến một số javadoc hoặc tài liệu mô tả cách sử dụng này.
Buurman

Đây là giải pháp duy nhất phù hợp với tôi khi tôi đang sử dụng giao diện bộ điều khiển
Anatoly Yakimchuk

4

Bạn có thể tạo một lớp cơ sở với @RequestMapping("rest")các chú thích và mở rộng tất cả các lớp khác của bạn với lớp cơ sở này.

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

Bây giờ tất cả các lớp mở rộng lớp cơ sở này sẽ có thể truy cập được tại rest/**.


3
Đây không phải là câu trả lời chính xác, người dùng đang đề cập đến chú thích của Bộ điều khiển. Nếu bạn mở rộng một lớp trừu tượng với chú thích RequestMapping và lớp mới cũng có RequestMapping, lớp cuối cùng này sẽ ghi đè lớp đầu tiên, nó sẽ không nối hai lớp.
Massimo

Bạn có biết rằng chú thích không được kế thừa trong java trừ khi nó được kế thừa chú thích meta không? Kiểm tra cái này: stackoverflow.com/a/21409651 . Và @RequestMapping dường như không có điều đó: docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
Mashrur

3

Đối với những người sử dụng cấu hình YAML (application.yaml).

Lưu ý : điều này chỉ hoạt động choSpring Boot 2.x.x

server:
  servlet:
    contextPath: /api

Nếu bạn vẫn đang sử dụng Spring Boot 1.x

server:
  contextPath: /api

1

Với spring-boot 2.x, bạn có thể cấu hình trong application.properties:

spring.mvc.servlet.path=/api

1

server.servlet.context-path=/apisẽ là giải pháp tôi đoán. Tôi đã có cùng một vấn đề và điều này đã được tôi giải quyết. Tôi đã sử dụng server.context-path. Tuy nhiên, điều đó dường như không được dùng nữa và tôi thấy rằngserver.servlet.context-path giải quyết được vấn đề ngay bây giờ. Một giải pháp khác mà tôi tìm thấy là thêm thẻ cơ sở vào các trang giao diện người dùng (H5) của tôi. Tôi hy vọng giúp đỡ ai đó ngoài kia.

Chúc mừng


0

Giải pháp này áp dụng nếu:

  1. Bạn muốn tiền tố RestControllernhưng không được Controller.
  2. Bạn không sử dụng 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);
        }
    }

    }

Điều này tương tự như giải pháp được đăng bởi mh-dev, nhưng tôi nghĩ giải pháp này gọn gàng hơn một chút và điều này sẽ được hỗ trợ trên bất kỳ phiên bản nào của Spring Boot 1.4.0+, bao gồm cả 2.0.0+.


Nếu tôi đang sử dụng pageable trong RestControler tôi, api / cái gì đó mang lại cho tôi Không constructor chính hoặc mặc định tìm thấy cho giao diện org.springframework.data.domain.Pageable
K. Ayoub

0

Mỗi tài liệu REST dữ liệu mùa xuân , nếu sử dụng application.properties , hãy sử dụng thuộc tính này để đặt đường dẫn cơ sở của bạn:

spring.data.rest.basePath=/api

Nhưng lưu ý rằng Spring sử dụng liên kết thư giãn , vì vậy biến thể này có thể được sử dụng:

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

... hoặc cái này nếu bạn thích:

spring.data.rest.base_path=/api

Nếu sử dụng application.yml , bạn sẽ sử dụng dấu hai chấm cho các dấu phân tách chính:

spring:
  data:
    rest:
      basePath: /api

(Để tham khảo, một phiếu liên quan đã được tạo vào tháng 3 năm 2018 để làm rõ các tài liệu.)



0

Bạn có thể tạo chú thích tùy chỉnh cho bộ điều khiển của mình:

Sử dụng nó thay vì @RestController thông thường trên các lớp bộ điều khiển của bạn và chú thích các phương thức với @RequestMapping.

Hoạt động tốt trong Spring 4.2!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.