如何移除Spring Boot MVC中已有映射?自定义404页面失效问题
问题描述
依赖库中存在如下配置:
@Bean public WebMvcConfigurer webMvcConfigurerAdapter() { return new WebMvcConfigurer() { public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/notFound").setViewName("forward:/index.html"); ... } } }
我希望为404错误创建独立的错误页面,目前除404外其他错误页面均可正常工作,但上述映射会将/notFound请求转发至index.html。尝试添加带有@Primary注解的配置类:
@Configuration @Primary public class SpringMvcConfiguration { @Bean @Primary public WebMvcConfigurer mywebMvcConfigurerAdapter() { return new WebMvcConfigurer() { public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/login").setViewName("login"); registry.addViewController("/error").setViewName("error"); registry.addViewController("/notFound").setViewName("notFound"); registry.addViewController("/").setViewName("forward:/index.html"); } }; } }
之后问题仍未解决,请求始终转发至index.html,请问该如何在应用中移除原有映射?
解决方案
@Primary注解在这里不生效,因为Spring会加载所有WebMvcConfigurer类型的Bean并逐一执行配置,不会因为你加了@Primary就忽略其他的。要覆盖原有/notFound的映射,可以用以下几种方式:
方式一:清空原有视图控制器后重新注册
创建配置类,在添加自己的视图控制器前,清空所有已注册的视图控制器映射:
@Configuration public class OverrideMvcConfig implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 清空所有已注册的视图控制器 registry.getViewControllerMappings().clear(); // 重新注册需要的视图控制器 registry.addViewController("/login").setViewName("login"); registry.addViewController("/error").setViewName("error"); registry.addViewController("/notFound").setViewName("notFound"); registry.addViewController("/").setViewName("forward:/index.html"); } }
此方式会完全接管视图控制器配置,适合需要替换所有视图映射的场景。
方式二:按优先级执行并移除指定映射
给你的配置类设置更高优先级,在添加新映射前移除原有/notFound的映射:
@Configuration @Order(1) // 优先级高于依赖库配置,数值越小优先级越高 public class SpringMvcConfiguration implements WebMvcConfigurer { @Override public void addViewControllers(ViewControllerRegistry registry) { // 移除原有/notFound的映射 registry.getViewControllerMappings().removeIf(mapping -> "/notFound".equals(mapping.getUrlPath())); // 注册自定义视图控制器 registry.addViewController("/login").setViewName("login"); registry.addViewController("/error").setViewName("error"); registry.addViewController("/notFound").setViewName("notFound"); registry.addViewController("/").setViewName("forward:/index.html"); } }
这种方式只修改目标映射,保留其他依赖库的配置,更灵活。
方式三:直接自定义ErrorController处理404
如果核心需求是给404设置独立页面,无需修改视图控制器映射,直接自定义错误控制器:
@Controller public class CustomErrorController implements ErrorController { @RequestMapping("/error") public String handleError(HttpServletRequest request) { Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); if (status != null) { Integer statusCode = Integer.valueOf(status.toString()); if (statusCode == HttpStatus.NOT_FOUND.value()) { return "notFound"; } } return "error"; } }
此方式绕开视图映射冲突,直接在错误处理逻辑中为404返回对应页面,更直接高效。
内容的提问来源于stack exchange,提问作者Burner
相关产品推荐
相关产品推荐

