try responsestatus responseentityexceptionhandler handling error custom controlleradvice catch spring spring-mvc spring-boot single-page-application catch-all

spring - responsestatus - Captura de primavera de todas las rutas para index.html



spring boot throw error (6)

Estoy desarrollando un backend de primavera para una aplicación de página única basada en la reacción en la que estoy utilizando el enrutador de reacción para el enrutamiento del lado del cliente.

Junto a la página index.html, el backend sirve datos en la ruta /api/** .

Para servir mi index.html desde src/main/resources/public/index.html en la ruta raíz / de mi aplicación, agregué un controlador de recursos

@Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/").addResourceLocations("/index.html"); }

Lo que quiero es servir la página index.html cuando no coincida ninguna otra ruta, por ejemplo, cuando llamo a una ruta que no sea /api .

¿Cómo configuro dicha ruta catch-all en primavera?


Encontré una respuesta mirando esta pregunta

@Bean public EmbeddedServletContainerCustomizer notFoundCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/")); } }; }


Para responder a su pregunta específica que involucra servir la aplicación de una sola página (SPA) en todos los casos, excepto la ruta / api aquí, es lo que hice para modificar la respuesta de Petri.

Tengo una plantilla llamada polímero que contiene el index.html para mi SPA. Así que el desafío se convirtió en un reenvío de todas las rutas excepto / api y / public-api a esa vista.

En mi WebMvcConfigurerAdapter, sobrescribí addViewControllers y usé la expresión regular: ^ ((?! / Api / | / public-api /).)*$

En su caso, desea la expresión regular: ^ ((?! / Api /).)*$

public class WebMvcConfiguration extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/{spring:^((?!/api/).)*$}").setViewName("polymer"); super.addViewControllers(registry); }

Esto se traduce en la posibilidad de acceder a http: // localhost o http://localhost/community para atender mi SPA y todas las demás llamadas que el SPA hace que se enruten con éxito a http://localhost/api/posts , http://localhost/public-api/posts , etc.


Tengo un PWA basado en polímero alojado dentro de mi aplicación Spring Boot, junto con recursos web estáticos como imágenes y una API REST en "/ api / ...". Quiero que la aplicación del lado del cliente maneje el enrutamiento de URL para el PWA. Esto es lo que yo uso:

@Configuration public class WebConfig extends WebMvcConfigurerAdapter { /** * Ensure client-side paths redirect to index.html because client handles routing. NOTE: Do NOT use @EnableWebMvc or it will break this. */ @Override public void addViewControllers(ViewControllerRegistry registry) { // Map "/" registry.addViewController("/") .setViewName("forward:/index.html"); // Map "/word", "/word/word", and "/word/word/word" - except for anything starting with "/api/..." or ending with // a file extension like ".js" - to index.html. By doing this, the client receives and routes the url. It also // allows client-side URLs to be bookmarked. // Single directory level - no need to exclude "api" registry.addViewController("/{x:[//w//-]+}") .setViewName("forward:/index.html"); // Multi-level directory path, need to exclude "api" on the first part of the path registry.addViewController("/{x:^(?!api$).*$}/**/{y:[//w//-]+}") .setViewName("forward:/index.html"); } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/webapp/"); } }

Esto también debería funcionar para las aplicaciones Angular y React.


Uso reaccionar y reaccionar-enrutador en mi aplicación Spring Boot, y fue tan fácil como crear un controlador que tiene mapeo a / y subárboles de mi sitio web como /users/** Aquí está mi solución

@Controller public class SinglePageAppController { @RequestMapping(value = {"/", "/users/**", "/campaigns/**"}) public String index() { return "index"; } }

Este controlador no captura las llamadas de Api y los recursos se manejan automáticamente.


Ya que mi aplicación de reacción podría usar la raíz como destino hacia adelante, esto terminó funcionando para mí.

@Configuration public class WebConfiguration extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/{spring://w+}") .setViewName("forward:/"); registry.addViewController("/**/{spring://w+}") .setViewName("forward:/"); registry.addViewController("/{spring://w+}/**{spring:?!(//.js|//.css)$}") .setViewName("forward:/"); } }

Para ser honesto, no tengo idea de por qué tiene que estar exactamente en este formato específico para evitar un bucle de reenvío infinito.


Evite @EnableWebMvc

Por defecto, Spring-Boot sirve contenido estático en src/main/resources :

  • / META-INF / recursos /
  • / recursos /
  • /estático/
  • /público/

Echa un vistazo a this y this ;

O mantenga @EnableWebMvc y anule addViewControllers

¿Especificaste @EnableWebMvc ? Eche un vistazo a esto: Java Spring Boot: ¿Cómo asignar la raíz de mi aplicación ("/") a index.html?

O elimina @EnableWebMvc, o puede volver a definir addViewControllers :

@Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/").setViewName("forward:/index.html"); }

O definir un controlador para atrapar /

Puede echar un vistazo a este proyecto de ejemplo spring-boot-reactjs en github :

Hace lo que quieras usando un controlador:

@Controller public class HomeController { @RequestMapping(value = "/") public String index() { return "index"; } }

Su index.html está en src/main/resources/templates