Spring загружать одностраничное приложение - пересылать каждый запрос index.html
У меня есть одностраничное приложение Spring Boot (v1.3.6) (angular2), и я хочу перенаправить весь запрос на index.html
.
Выполняется запрос http://localhost:8080/index.html (200 и я получаю index.html), но http://localhost:8080/home не является (404).
Runner.class
@SpringBootApplication
@ComponentScan({"packagea.packageb"})
@EnableAutoConfiguration
public class Runner {
public static void main(String[] args) throws Exception {
ConfigurableApplicationContext run = SpringApplication.run(Runner.class, args);
}
}
WebAppConfig.class
@Configuration
@EnableScheduling
@EnableAsync
public class WebAppConfig extends WebMvcConfigurationSupport {
private static final int CACHE_PERIOD_ONE_YEAR = 31536000;
private static final int CACHE_PERIOD_NO_CACHE = 0;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.setOrder(-1);
registry.addResourceHandler("/styles.css").addResourceLocations("/styles.css").setCachePeriod(CACHE_PERIOD_ONE_YEAR);
registry.addResourceHandler("/app/third-party/**").addResourceLocations("/node_modules/").setCachePeriod(CACHE_PERIOD_ONE_YEAR);
registry.addResourceHandler("/app/**").addResourceLocations("/app/").setCachePeriod(CACHE_PERIOD_NO_CACHE);
registry.addResourceHandler("/systemjs.config.js").addResourceLocations("/systemjs.config.js").setCachePeriod(CACHE_PERIOD_NO_CACHE);
registry.addResourceHandler("/**").addResourceLocations("/index.html").setCachePeriod(CACHE_PERIOD_NO_CACHE);
}
}
styles.css
, /app/third-party/xyz/xyz.js
,.. работают (200 и я получаю правильный файл). Только /**
до index.html
не работает.
Ответы
Ответ 1
Вы также можете добавить контроллер пересылки, например:
@Controller
public class ForwardingController {
@RequestMapping("/{path:[^\\.]+}/**")
public String forward() {
return "forward:/";
}
}
Первая часть {path:[^\\.]+}
соответствует одному или нескольким символам, отличным от .
. Это гарантирует, что запрос для file.ext
не будет обработан этим RequestMapping. Если вам нужно поддерживать вспомогательные пути для пересылки, поместите /**
за пределы {...}
.
Ответ 2
Не глядя на журналы, я не совсем уверен, почему его неправильно сопоставили, однако, если вы хотите сопоставить URL-адреса с представлением (HTML), вам, вероятно, будет лучше использовать механизм viewController
spring. http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-config-view-controller. например.
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("home");
}
}
(взято из spring docs, связанного выше - вот как вы должны сопоставить URL-адрес для представления, а не переназначать сопоставление для статических ресурсов.)
Я не уверен, есть ли какая-либо фильтрация суффиксов для сопоставления ресурсов - например. Я не знаю, как spring решает сопоставить запросы ResourceHttpRequestHandler
- вы попробовали (просто подтвердить или опровергнуть), что-то вроде http://localhost:8080/home.html на что-нибудь?
Также возможно, что отображаемое вами html-сопоставление просто игнорируется, а index.html работает только из-за Spring -Boot по умолчанию: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ResourceProperties.java#L108
Ответ 3
У меня была такая же проблема, и для меня это работало. Мои html файлы находятся внутри src/main/resources/static/app
Ключ должен был удалить @EnableWebMvc и добавить "classpath:/static/app/" в addResourceLocations! Надеюсь это поможет.
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
"classpath:/META-INF/resources/", "classpath:/resources/",
"classpath:/static/","classpath:/static/app/", "classpath:/public/" };
@Bean
public WebMvcConfigurer webMvcConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/webjars/**")) {
registry.addResourceHandler("/webjars/**").addResourceLocations(
"classpath:/META-INF/resources/webjars/");
}
if (!registry.hasMappingForPattern("/**")) {
registry.addResourceHandler("/**").addResourceLocations(
CLASSPATH_RESOURCE_LOCATIONS);
}
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
// forward requests to /admin and /user to their index.html
registry.addViewController("/portal").setViewName(
"forward:/app/index.html");
}
};
}
Ответ 4
Этот не работал у меня:
return "forward:/";
Благодаря Spring MVC @RestController и перенаправлению я нашел красивое рабочее решение:
@RequestMapping(value = "/{[path:[^\\.]*}")
public void redirect(HttpServletResponse response) throws IOException {
response.sendRedirect("/");
}