配置spring boot以将404重定向到单个页面应用程序

问题描述 投票:9回答:5

我想配置我的Spring Boot应用程序,将任何404未找到的请求重定向到我的单页应用程序。

例如,如果我调用不存在的localhost:8080/asdasd/asdasdasd/asdasd,它应该重定向到localhost:8080/notFound

问题是我有一个单页反应应用程序,它运行在根路径localhost:8080/。所以春天应该重定向到localhost:8080/notFound,然后转发到/(保持路线)。

spring spring-mvc spring-boot single-page-application
5个回答
17
投票

这应该可以解决这个问题:添加404路由到/notFound的错误页面,并将其转发到SPA(假设条目位于/index.html上):

@Configuration
public class WebApplicationConfig extends WebMvcConfigurerAdapter {

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


    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return container -> {
            container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
                    "/notFound"));
        };
    }

}

12
投票

这是完整的Spring Boot 2.0示例:

@Configuration
public class WebApplicationConfig implements WebMvcConfigurer {

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


@Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> containerCustomizer() {
    return container -> {
        container.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND,
                "/notFound"));
    };
  }

}

3
投票

如果有人在这里偶然发现如何处理Spring Boot应用程序中的Angular / React /其他路由和路径 - 但并不总是返回任何404的index.html - 它可以在标准的Spring控制器RequestMapping中完成。这可以在不添加视图控制器和/或自定义容器错误页面的情况下完成。

RequestMapping支持通配符,因此您可以使其与应用程序中的一组众所周知的路径(即角度路径等)匹配,然后返回index.html:

@Controller 
public class Html5PathsController { 

    @RequestMapping( method = {RequestMethod.OPTIONS, RequestMethod.GET}, path = {"/path1/**", "/path2/**", "/"} )
    public String forwardAngularPaths() { 
        return "forward:/index.html"; 
    } 
}

另一种选择(借用旧的Spring文章:https://spring.io/blog/2015/05/13/modularizing-the-client-angular-js-and-spring-security-part-vii)是使用命名约定:

@Controller 
public class Html5PathsController { 

    @RequestMapping(value = "/{[path:[^\\.]*}")
    public String redirect() {
        return "forward:/index.html";
    } 
}

上述配置将匹配所有不包含句点且尚未映射到另一个控制器的路径。


1
投票

这里的安全配置(SecurityConfig.java)

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private Environment env;

    @Autowired
    private UserSecurityService userSecurityService;

    private BCryptPasswordEncoder passwordEncoder() {
        return SecurityUtility.passwordEncoder();
    }

    private static final String[] PUBLIC_MATCHERS = {
            "/css/**",
            "/js/**",
            "/data/**",
            "/sound/**",
            "/img/**",
            "/",
            "/login",
            "/logout,
            "/error",
            "/index2",
    };

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests().
        /*  antMatchers("/**").*/
            antMatchers(PUBLIC_MATCHERS).
            permitAll().anyRequest().authenticated();
        //.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");

        http
            .csrf().disable().cors().disable()
            .formLogin().failureUrl("/login?error")
            .defaultSuccessUrl("/index2")
            .loginPage("/login").permitAll()
            .and()
            .logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
            .logoutSuccessUrl("/?logout").deleteCookies("remember-me").permitAll()
            .and()
            .rememberMe()
            .and()
            .sessionManagement().maximumSessions(3600)
            .and().
            invalidSessionUrl("/login");
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userSecurityService).passwordEncoder(passwordEncoder());
    }
}

如果未找到任何资源重定向到错误页面

@Controller
public class IndexController implements ErrorController{

    private static final String PATH = "/error";

    @RequestMapping(value = PATH)
    public String error() {
        return PATH;
    }

    @Override
    public String getErrorPath() {
        return PATH;
    }
}

错误页面就像

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1000/xhtml"
    xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
    <meta http-equiv="refresh" content="5;url=/login" />
<body>
 <h1>Page not found please login the system!</h1>
</body>
</html>

0
投票

简单地实现org.springframework.boot.web.servlet.error.ErrorController就可以解决这个问题了。我将SpringBoot 2.0与React一起使用。 (如果您对如何做到这一点感兴趣,请参考我制作的样板项目:https://github.com/archangel1991/react-with-spring

@Controller
public class CustomErrorController implements ErrorController {

    @Override
    public String getErrorPath() {
        return "/error";
    }
}

我不知道为什么这会起作用。

© www.soinside.com 2019 - 2024. All rights reserved.