it-swarm.com.ru

Как установить базовый URL для отдыха при весенней загрузке?

Я пытаюсь смешать mvc и отдых в одном весеннем загрузочном проекте.

Я хочу установить базовый путь для всех остальных контроллеров (например, example.com/api) в одном месте (я не хочу аннотировать каждый контроллер с помощью @RequestMapping('api/products'), а просто @RequestMapping('/products')).

Контроллеры Mvc должны быть доступны для example.com/wh независимо

Является ли это возможным?

(Я не использую данные Spring, просто Spring MVC)

68
Teimuraz

В Spring Boot 1.2+ требуется только одно свойство в application.properties:

spring.data.rest.basePath=/api

ссылка на ссылку: https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri

33
Suroj

Немного поздно, но тот же вопрос привел меня сюда, прежде чем я получил ответ, поэтому я выложу его здесь . Создайте (если у вас его еще нет) application.properties и добавьте

server.contextPath=/api

Так что в предыдущем примере, если у вас есть RestController с @RequestMapping("/test"), вы получите к нему доступ, как localhost:8080/api/test/{your_rest_method}

источник вопроса: Как выбрать URL для моего весеннего загрузочного веб-приложения

83
OriolBG

Я не мог поверить, насколько сложен ответ на этот, казалось бы, простой вопрос. Вот несколько ссылок:

Есть много разных вещей, чтобы рассмотреть: 

  1. Установив server.context-path=/api в application.properties, вы можете настроить префикс для everything. (Его путь к server.context не server.contextPath!)
  2. Контроллеры Spring Data, аннотированные @RepositoryRestController, которые представляют репозиторий в качестве конечной точки отдыха, будут использовать переменную среды spring.data.rest.base-path в application.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\"}";
  }
}
21
Robert

Так как это первая проблема в Google, и я предполагаю, что больше людей будут искать это. После Spring Boot '1.4.0' ..__ появилась новая опция. Теперь можно определить пользовательский RequestMappingHandlerMapping, который позволяет определить другой путь для классов, аннотированных @RestController

Другая версия с пользовательскими аннотациями, которая сочетает @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);
                    }
                };
            }
        };
    }
}
21
mh-dev

Для весенней загрузки фреймворк версии 2.0.4.RELEASE+. Добавьте эту строку в application.properties

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

Для Boot 2.0.0+ это работает для меня: server.servlet.context-path =/api

8
Juan Carlos Vergara Santos

Я нашел чистое решение, которое касается только остальных контроллеров. 

@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 зарегистрирует два сервлета диспетчера - по умолчанию 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 в контексте покоя, они могут быть определены в родительском контексте
7
kravemir

Я могу немного опоздать, НО ... Я считаю, что это лучшее решение. Установите его в своем application.yml (или аналогичном конфигурационном файле):

spring:
    data:
        rest:
            basePath: /api

Насколько я помню, все - все ваши репозитории будут отображаться под этим URI.

7
thorinkor

Вы можете создать собственную аннотацию для ваших контроллеров:

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

Используйте его вместо обычного @RestController на ваших классах контроллеров и аннотируйте методы с помощью @RequestMapping.

Только что протестировал - работает весной 4.2!

5
Ilya Novoseltsev

Вы можете создать базовый класс с аннотациями @RequestMapping("rest") и расширить все остальные классы этим базовым классом.

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

Теперь все классы, которые расширяют этот базовый класс, будут доступны по адресу rest/**.

4
Saket Mehta

Spring-boot 2.x вы можете настроить в application.properties:

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

Для данных Spring REST docs , если используется 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 года для уточнения документов.)

0
J Woodchuck

Это решение применяется, если:

  1. Вы хотите добавить префикс RestController, но не Controller.
  2. Вы не используете 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);
        }
    }
    

    }

Это похоже на решение , опубликованное mh-dev, но я думаю, что это немного чище, и это должно поддерживаться в любой версии Spring Boot 1.4.0+, включая 2.0.0+.

0
The Gilbert Arenas Dagger