example ejemplo java spring rest spring-boot spring-mvc

java - ejemplo - ¿Cómo configurar la URL base para descansar en el arranque de primavera?



spring rest json (14)

Estoy tratando de mezclar mvc y descansar en un solo proyecto de arranque de primavera.

Quiero establecer la ruta base para todos los controladores de descanso (por ejemplo, example.com/api) en un solo lugar (no quiero anotar cada controlador con @RequestMapping(''api/products'') , en cambio, solo @RequestMapping(''/products'') .

Los controladores de Mvc deben ser accesibles mediante example.com/whatever

¿Es posible?

(No uso el resto de datos de primavera, solo mvc de primavera)



Con spring-boot 2.x puede configurar en application.properties:

spring.mvc.servlet.path=/api


Dado que este es el primer hit de Google para el problema y supongo que más personas buscarán esto. Hay una nueva opción desde Spring Boot ''1.4.0''. Ahora es posible definir un RequestMappingHandlerMapping personalizado que permita definir una ruta diferente para las clases anotadas con @RestController

En esta publicación de blog se puede encontrar una versión diferente con anotaciones personalizadas que combina @RestController con @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); } }; } }; } }


Encontré una solución limpia, que afecta solo a los controladores de descanso.

@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 registrará dos servlets de despachador: el dispatcherServlet predeterminado restApi para controladores y el despachador @RestControllers para @RestControllers definidos en 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 [/]

El ejemplo 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>

Pero no estás limitado a :

  • use XmlWebApplicationContext , puede usar cualquier otro tipo de contexto disponible, es decir. AnnotationConfigWebApplicationContext , GenericWebApplicationContext , GroovyWebApplicationContext , ...
  • definir jsonMessageConverter , beans beans de jsonMessageConverter en contexto de reposo, pueden definirse en contexto primario

Esta solución se aplica si:

  1. Desea prefijar RestController pero no Controller .
  2. No estás utilizando 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); } }

    }

Esto es similar a la solution publicada por mh-dev, pero creo que esto es un poco más limpio y debería ser compatible con cualquier versión de Spring Boot 1.4.0+, incluida 2.0.0+.


No podía creer lo complicada que es la respuesta a esta pregunta aparentemente simple. Aquí hay algunas referencias:

Hay muchas cosas diferentes a considerar:

  1. Al configurar server.context-path=/api en application.properties , puede configurar un prefijo para todo (¡su server.context-path no server.contextPath!)
  2. Los controladores Spring Data anotados con @RepositoryRestController que exponen un repositorio como punto final de descanso utilizarán la variable de entorno spring.data.rest.base-path en application.properties . Pero el simple @RestController no tendrá esto en cuenta. De acuerdo con la documentación del resto de datos de Spring, hay una anotación @BasePathAwareController que puede usar para eso. Pero sí tengo problemas en conexión con Spring-security cuando intento asegurar dicho controlador. Ya no se encuentra.

Otra solución es un simple truco. No puede anteponer una cadena estática en una anotación, pero puede usar expresiones como esta:

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


Para Boot 2.0.0+, esto funciona para mí: server.servlet.context-path = / api


Para Spring Boot Framework versión 2.0.4.RELEASE+ . Agregue esta línea a application.properties

server.servlet.context-path=/api


Puede crear una anotación personalizada para sus controladores:

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

Úselo en lugar del habitual @RestController en sus clases de controlador y anote métodos con @RequestMapping.

Recién probado - ¡funciona en Spring 4.2!


Puede crear una clase base con anotaciones @RequestMapping("rest") y extender todas las demás clases con esta clase base.

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

Ahora todas las clases que extiendan esta clase base estarán accesibles en rest/** .


Puede que llegue un poco tarde, PERO ... Creo que es la mejor solución. Configúrelo en su application.yml (o archivo de configuración analógico):

spring: data: rest: basePath: /api

Como puedo recordar, eso es todo: todos sus repositorios estarán expuestos debajo de este URI.


Según los https://docs.spring.io/spring-data/rest/docs/current/reference/html/#getting-started.changing-base-uri REST de Spring Data, si usa application.properties , use esta propiedad para establecer su ruta base:

spring.data.rest.basePath=/api

Pero tenga en cuenta que Spring uses un enlace relajado , por lo que esta variación se puede usar:

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

... o este si prefieres:

spring.data.rest.base_path=/api

Si usa application.yml , usaría dos puntos para los separadores de clave:

spring: data: rest: basePath: /api

(Como referencia, se creó un jira.spring.io/browse/DATAREST-1211 relacionado en marzo de 2018 para aclarar los documentos).


Un poco tarde, pero la misma pregunta me trajo aquí antes de llegar a la respuesta, así que la publico aquí. Cree (si aún no lo tiene) una aplicación.propiedades y agregue

server.contextPath=/api

Entonces, en el ejemplo anterior, si tiene un RestController con @RequestMapping("/test") accederá como localhost:8080/api/test/{your_rest_method}

fuente de preguntas: ¿cómo elijo la url para mi aplicación web de arranque de primavera?


servidor trabajado.contextPath = / ruta