스프링 부트에서 휴식을 위해 기본 URL을 설정하는 방법은 무엇입니까?


118

단일 스프링 부트 프로젝트에서 mvc와 휴식을 혼합하려고합니다.

난과 주석을 각 컨트롤러 싶지 않아 (모든 나머지 컨트롤러 (예. example.com/api) 하나의 장소에 대한 설정 기본 경로에 원하는 @RequestMapping('api/products')대신에, 단지를 @RequestMapping('/products').

Mvc 컨트롤러는 example.com/whatever에서 액세스 할 수 있어야합니다.

가능할까요?

(나는 spring data rest를 사용하지 않고 spring mvc 만 사용합니다)



server.servlet.contextPath = / API
다니엘 T. Sobrosa

스프링 부트 버전 2.1.4.RELEASE, spring.mvc.servlet.path = / api 및 server.servlet.context-path = / api, 둘 다 작동합니다
Prayag Sharma

server.servlet.context-path = / api 솔루션은 REST 전용이 아닌 APPLICATION 용입니다. SOAP 서비스에도 유효합니다. SOAP 및 REST 서비스 경로를 분할하려면 @RequestMapping ( 'api / ...') ... medium.com/@bm.celalkartal/…
bmck

답변:


89

Spring Boot 1.2 + (<2.0)에서는 application.properties의 단일 속성 만 있으면됩니다.

spring.data.rest.basePath=/api

참조 링크 : https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri

2.x의 경우

server.servlet.context-path=/api

4
이것은 thorinkor가 준 정확한 대답입니다.
Jean-François Beauchef

8
감사합니다.하지만 이것은 Spring Boot 버전 v1.5.7.RELEASE에서 작동하지 않습니다. 다른 대답은 server.contextPath = / api가 작동했습니다
Jay

10
@Suroj 그 솔루션은 RestController가 아닌 RepositoryRestController 주석이 달린 컨트롤러에서만 작동합니다 ...
Nano

jira.spring.io/browse/DATAREST-1211 이 Jira 티켓은 "Spring Boot 2.0.0 용 spring.data.rest.base-path"라고 언급합니다. 슬프게도 둘 다 나를 위해 작동하지 않습니다.
Carsten Hagemann

6
SB 2+의 경우 server.servlet.context-path = / url
vicky

96

조금 늦었지만 같은 질문이 답변에 도달하기 전에 여기로 왔으므로 여기에 게시합니다. application.properties를 만들고 (아직 가지고 있지 않은 경우) 추가합니다.

server.contextPath=/api

따라서 이전 예제에서 RestController가 @RequestMapping("/test")있으면 다음과 같이 액세스합니다.localhost:8080/api/test/{your_rest_method}

질문 출처 : 스프링 부트 웹 앱의 URL을 어떻게 선택합니까?


19
RestController로만 작동하고 "/ api"없이 일반 컨트롤러에 액세스하도록이를 강제하는 방법
Siya Sosibo

@Stoan 나는 :-) 내 대답을 확인 해결책을 발견
kravemir

이러지마! thorinkor의 답변을 참조하십시오.
스테판

Thorinkor의 대답은 특별히 SpringData REST에 대한 것입니다.

8
server.contextPath는 이제 더 이상 사용되지 않습니다
.

46

스프링 부트 프레임 워크 버전 2.0.4.RELEASE+. 이 줄 추가application.properties

server.servlet.context-path=/api

1
이것은 또한 공용 폴더에 영향을 미칩니다
Michel

5
이것은 Spring boot 2+에 대한 정답입니다. spring.data.rest.basePath봄 부팅이 작동하지 않습니다
jackycflau

27

이것이 문제에 대한 첫 번째 Google 히트이기 때문에 더 많은 사람들이 이것을 검색 할 것이라고 가정합니다. Spring Boot '1.4.0'이후 새로운 옵션이 있습니다. 이제 @RestController로 주석이 달린 클래스에 대해 다른 경로를 정의 할 수 있는 사용자 정의 RequestMappingHandlerMapping 을 정의 할 수 있습니다.

@RestController@RequestMapping 을 결합한 커스텀 어노테이션이있는 다른 버전 은이 블로그 게시물 에서 찾을 수 있습니다.

@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+에서는 WebMvcRegistrations 인터페이스에서 직접 작업합니다. WebMvcRegistrationsAdapter는 인터페이스에 기본 메소드를 추가하기 위해 제거되었습니다.
길버트 아레나스 대거

27

이 간단한 질문에 대한 답이 얼마나 복잡한 지 믿을 수 없었습니다. 다음은 몇 가지 참고 자료입니다.

고려해야 할 여러 가지 사항이 있습니다.

  1. server.context-path=/api에서 설정 application.properties하면 모든 것에 대한 접두사를 구성 할 수 있습니다 . (server.contextPath가 아닌 server.context-path!)
  2. 저장소를 나머지 끝점으로 노출하는 @RepositoryRestController 주석이 달린 SpringData 컨트롤러 spring.data.rest.base-pathapplication.properties. 그러나 평범한 @RestController것은 이것을 고려하지 않을 것입니다. 스프링 데이터 나머지 문서 에 따르면이를 위해 @BasePathAwareController사용할 수 있는 주석 이 있습니다. 그러나 그러한 컨트롤러를 보호하려고 할 때 Spring-security와 관련하여 문제가 있습니다. 더 이상 찾을 수 없습니다.

또 다른 해결 방법은 간단한 트릭입니다. 주석에서 정적 문자열을 접두사로 사용할 수는 없지만 다음과 같은 표현식을 사용할 수 있습니다.

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

Annotation에 어떻게 삽입 하시겠습니까?
Teimuraz

2
MEH, 당신은 항상이 접두사에게 새 컨트롤러를 만들 때마다 추가하는 것을 기억해야한다
길버트 아레나스 대거

13

Boot 2.0.0+의 경우 이것은 나를 위해 작동합니다 : server.servlet.context-path = / api


4
@RestController 매퍼뿐만 아니라 / api 아래에 모든 것을 넣습니다. 어쨌든 감사합니다. 귀하의 정보는 여전히 유용합니다.
eigil

9

나머지 컨트롤러에만 영향을 미치는 깨끗한 솔루션을 찾았습니다.

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

스프링 부트는 두 개의 디스패처 서블릿을 등록합니다- dispatcherServlet컨트롤러에 대한 기본값 과 restApi@RestControllers정의 된 디스패처 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 [/]

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>

그러나 다음으로 제한되지않습니다 .

  • 를 사용 XmlWebApplicationContext하면 사용 가능한 다른 컨텍스트 유형을 사용할 수 있습니다. AnnotationConfigWebApplicationContext, GenericWebApplicationContext, GroovyWebApplicationContext, ...
  • 정의 jsonMessageConverter, messageConverters나머지 컨텍스트의 빈, 부모 컨텍스트에서 정의 될 수 있음

xml을 사용하지 않고 프로그래밍 방식으로이 작업을 수행 할 수 있습니까?
Arian 2017

@ArianHosseinzadeh 네. 프로그래밍 방식으로 수행 할 수 있습니다. 스프링 컨텍스트를 설정하는 방법에는 여러 가지가 있습니다. 예제에서는 REST API 처리를위한 자식 컨텍스트를 만드는 방법을 보여주었습니다. Java 내에서 컨텍스트를 설정하는 방법을 배우고 이러한 지식을이 답변에서 지식과 결합하십시오. 이를 프로그래밍이라고합니다.
kravemir

7

컨트롤러에 대한 사용자 지정 주석을 만들 수 있습니다.

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

컨트롤러 클래스에서 일반적인 @RestController 대신 사용하고 @RequestMapping으로 메서드에 주석을 답니다.

방금 테스트-Spring 4.2에서 작동합니다!


감사합니다. 나는 이것을 시도했다. 하지만 이제 각 메서드에 @RequestMapping ( "/ products"), @RequestMapping ( "/ products / {id}") 주석을 추가해야합니다. 대신 @RequestMapping ( "/ products")을 사용하여 Controller에 주석을 달고 @RequestMapping, @RequestMapping ( "/ : id")를 사용하여 메서드를 주석 처리해야합니다. 그리고 제품 컨트롤러는 api / products에서 액세스 할 수 있어야합니다 (예 : 단일 위치에 api 접두사 설정)
Teimuraz

2
이 경우 기본적으로 AFAIK 솔루션이 없습니다. 자신의 RequestMappingHandlerMapping. SpringData REST에는 필요한 것과 유사한 매퍼가 BasePathAwareHandlerMapping있습니다.
Ilya Novoseltsev 2015 년

@moreo, 적절한 해결책을 찾았습니까? 답변으로 게시 해 주시면 기쁩니다. 여기에도 동일한 요구 사항이 있습니다.
fischermatte

@fischermatte, 아니요, 정확히 원하는 것을 찾지 못했습니다. @RequestMapping ( "/ api / products") 또는 @RequestMapping ( "/ api / users")를 각 컨트롤러 클래스 앞에 배치 한 다음 메서드 앞에 다른 @ RequestMapping ( "/ {id}"). 그러나 나는 이것이 큰 문제라고 생각하지 않습니다. "api"를 무언가로 변경하고 싶다면 각 수업의 시작 부분에서 변경하겠습니다.
Teimuraz

@IlyaNovoseltsev 솔루션은 내 대답 :-) 볼 수 있습니다
kravemir

7

조금 늦을 수도 있지만 ... 최선의 해결책이라고 생각합니다. application.yml (또는 유사 구성 파일)에서 설정하십시오.

spring:
    data:
        rest:
            basePath: /api

내가 기억할 수 있듯이 모든 저장소가이 URI 아래에 노출됩니다.


이것을 약간 설명하거나 관련 문서를 가리킬 수 있습니까?
Dmitry Serdiuk 2016


11
environemnt 변수 spring.data.rest.base-path 는 spring-data-rest 및 spring-hateoas에만 영향을 미칩니다. 일반 @RestController는 여전히 루트에 있습니다!
Robert

4
@thorinkor는 대부분의 경우 사람들이 SpringData REST 리포지토리를 빌드한다는 말을 기반으로합니까? 그리고 영업 이익은 분명 그가 나머지 컨트롤러가 말하는 ...
장 - 프랑수아 Beauchef

1
SpringDataRest를 사용하는 경우에만 작동한다고 생각합니다.
Jaumzera

6

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
고마워요, 제가 찾던 바로 그것입니다! 이를 통해 spring.data.rest.base-path가 수행하는 것과 유사하게이 WebMvcConfig를 통해 구성된 모든 RestController에 대한 컨텍스트 경로 요소를 설정할 수 있습니다.
Buurman

귀하의 답변은 @HaraldWendel에 있습니다. : +1 : 코드가 정확히 무엇을하는지 설명하는 것과 같이 조금 더 확장하여 (내 의견에서 시도한대로) 링크를 추가 할 수 있습니다. 이 사용법을 설명하는 일부 javadoc 또는 문서.
Buurman

이것이 컨트롤러 인터페이스를 사용하면서 저에게 도움이 된 유일한 솔루션입니다
Anatoly Yakimchuk

4

@RequestMapping("rest")주석이 있는 기본 클래스를 만들고이 기본 클래스를 사용하여 다른 모든 클래스를 확장 할 수 있습니다.

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

이제이 기본 클래스를 확장하는 모든 클래스는에서 액세스 할 수 있습니다 rest/**.


3
이것은 정답이 아니며 사용자가 컨트롤러 주석을 참조하고 있습니다. RequestMapping 주석을 사용하여 추상 클래스를 확장하고 새 클래스에도 RequestMapping이있는 경우이 마지막 클래스가 첫 번째 클래스를 재정의하고 두 클래스를 연결하지 않습니다.
Massimo

메타 주석을 상속하지 않으면 주석이 Java에서 상속되지 않는다는 것을 알고 있습니까? 이것을 확인하십시오 : stackoverflow.com/a/21409651 . 그리고 @RequestMapping에는 다음이없는 것 같습니다. docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
Mashrur

3

YAML 구성 (application.yaml)을 사용하는 사용자를 위해.

참고 : 이것은Spring Boot 2.x.x

server:
  servlet:
    contextPath: /api

아직 사용중인 경우 Spring Boot 1.x

server:
  contextPath: /api

1

spring-boot 2.x를 사용하면 application.properties에서 구성 할 수 있습니다.

spring.mvc.servlet.path=/api

1

server.servlet.context-path=/api내가 추측하는 해결책이 될 것입니다. 나는 같은 문제가 있었고 이것은 나를 해결하게했습니다. server.context-path를 사용했습니다. 그러나 그것은 더 이상 사용되지 않는 것처럼 보였고 server.servlet.context-path이제 문제 가 해결 된다는 것을 알았습니다 . 내가 찾은 또 다른 해결 방법은 프런트 엔드 (H5) 페이지에 기본 태그를 추가하는 것입니다. 나는 이것이 누군가를 돕기를 바랍니다.

건배


0

이 솔루션은 다음과 같은 경우에 적용됩니다.

  1. 접두사를 원 RestController하지만 Controller.
  2. SpringData 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);
        }
    }

    }

이것은 mh-dev가 게시 한 솔루션 과 유사 하지만 조금 더 깔끔하고 2.0.0+를 포함한 모든 버전의 Spring Boot 1.4.0+에서 지원되어야한다고 생각합니다.


난 내 RestControler, API / 뭔가 Pageable를 사용하고 있다면 아무런 기본 또는 기본 생성자는 인터페이스 org.springframework.data.domain.Pageable을 찾을 수 없습니다 나에게 준다
K. 아 유브

0

SpringData REST 문서에 따라 application.properties 를 사용하는 경우이 속성을 사용하여 기본 경로를 설정합니다.

spring.data.rest.basePath=/api

그러나 Spring 완화 된 바인딩을 사용 하므로이 변형을 사용할 수 있습니다.

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

... 또는 원하는 경우 다음 중 하나 :

spring.data.rest.base_path=/api

application.yml을 사용하는 경우 키 구분 기호로 콜론을 사용합니다.

spring:
  data:
    rest:
      basePath: /api

(참고로 문서를 명확히하기 위해 2018 년 3 월에 관련 티켓 이 생성되었습니다.)



0

컨트롤러에 대한 사용자 지정 주석을 만들 수 있습니다.

컨트롤러 클래스에서 일반적인 @RestController 대신 사용하고 @RequestMapping으로 메서드에 주석을 답니다.

Spring 4.2에서 잘 작동합니다!

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.