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