Spring Boot整合JSP实现自定义404错误页面的问题求助
解决Spring Boot+JSP自定义404错误页面不生效问题
问题根源分析
当前无效URL被重定向到首页,核心原因是Spring Security拦截了未匹配的URL,将其判定为未认证请求,触发了UnauthenticatedRequestHandler的重定向逻辑,导致请求根本无法到达自定义错误控制器CustomErrorController。同时现有错误控制器的配置仅处理特定路径,未覆盖通用错误场景。
分步解决方案
1. 修正application.yml配置
移除ErrorMvcAutoConfiguration的排除,启用Spring MVC的异常抛出机制,确保未匹配URL直接进入错误处理流程:
server: port: 1207 error: whitelabel: enabled: false spring: mvc: throw-exception-if-no-handler-found: true # 无匹配处理器时抛出异常 view: prefix: /views/ # JSP视图前缀,根据实际路径调整 suffix: .jsp # JSP视图后缀 resources: add-mappings: false # 关闭静态资源自动映射(若需静态资源可开启,需确保不与业务URL冲突)
2. 重构CustomErrorController
让错误控制器处理通用的/error路径,覆盖所有错误场景,重点处理404:
@Controller public class CustomErrorController implements ErrorController { private static final String ERROR_PATH = "/error"; @Override public String getErrorPath() { return ERROR_PATH; } @RequestMapping(value = ERROR_PATH) public ModelAndView handleError(HttpServletRequest request) { ModelAndView modelAndView = new ModelAndView(); Object statusAttr = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); if (statusAttr != null) { Integer statusCode = Integer.valueOf(statusAttr.toString()); if (statusCode == HttpStatus.NOT_FOUND.value()) { // 指向自定义404页面 modelAndView.setViewName("page-not-found"); } else { // 其他错误可自定义对应的页面 modelAndView.setViewName("error"); } } else { // 默认错误页面 modelAndView.setViewName("error"); } return modelAndView; } }
3. 调整Spring Security配置
确保错误路径被允许访问,同时限制认证入口仅作用于存在的业务URL,避免拦截无效URL:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { private final JwtTokenProvider jwtTokenProvider; private final HandlerMapping handlerMapping; // 构造注入依赖 public SecurityConfig(JwtTokenProvider jwtTokenProvider, HandlerMapping handlerMapping) { this.jwtTokenProvider = jwtTokenProvider; this.handlerMapping = handlerMapping; } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(final HttpSecurity http) throws Exception { http .httpBasic().disable() .csrf().disable() .sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) .and() .authorizeRequests() .antMatchers("/public/**").permitAll() .antMatchers(WebUrl.index).permitAll() .antMatchers(WebUrl.about).permitAll() .antMatchers(WebUrl.pageNotFound).permitAll() .antMatchers("/error").permitAll() // 允许访问错误路径 .anyRequest().authenticated() .and() .apply(new JwtConfigurer(jwtTokenProvider)) .and() .exceptionHandling() // 仅对存在的URL触发未认证重定向 .defaultAuthenticationEntryPointFor(unauthenticatedRequestHandler(), existingUrlMatcher()) .accessDeniedPage("/403"); } // 自定义匹配器:仅匹配存在处理器的URL private RequestMatcher existingUrlMatcher() { return request -> { try { HandlerExecutionChain handler = handlerMapping.getHandler(request); return handler != null; } catch (Exception e) { return false; } }; } @Bean UnauthenticatedRequestHandler unauthenticatedRequestHandler() { return new UnauthenticatedRequestHandler(); } }
4. 保留UnauthenticatedRequestHandler逻辑(无需修改)
该类仅处理存在但未认证的业务URL,无效URL不会再触发这里的重定向:
public class UnauthenticatedRequestHandler implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { if(request.getServletPath().startsWith("/admin/")) { response.sendRedirect("/admin/login"); }else { response.sendRedirect("/"); } } }
验证逻辑
- 访问有效但未认证的URL(如
/admin/dashboard):会触发UnauthenticatedRequestHandler重定向到/admin/login。 - 访问无效URL(如
/about/random-unauthorized-url):Spring MVC检测到无匹配处理器,抛出异常后进入CustomErrorController,返回自定义404页面。 - 访问已授权的有效URL(如
/about):正常返回对应页面。
内容的提问来源于stack exchange,提问作者Rakhi
相关产品推荐
相关产品推荐

