You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

验证逻辑

  1. 访问有效但未认证的URL(如/admin/dashboard):会触发UnauthenticatedRequestHandler重定向到/admin/login。
  2. 访问无效URL(如/about/random-unauthorized-url):Spring MVC检测到无匹配处理器,抛出异常后进入CustomErrorController,返回自定义404页面。
  3. 访问已授权的有效URL(如/about):正常返回对应页面。

内容的提问来源于stack exchange,提问作者Rakhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 07:36:20