【Springboot】解决问题 o.s.web.servlet.PageNotFound : No mapping for *

使用 cursor 进行老项目更新为 springboot 的 web 项目,发生了奇怪的问题,就是 html 文件访问正常,但是静态文件就是 404

检查了各种配置,各种比较,各种调试,最后放弃时候,清理没用的配置文件,发现了一个老的配置类

java 复制代码
@Configuration
public class DateTimeConfig extends WebMvcConfigurationSupport {

    Logger logger = LoggerFactory.getLogger(DateTimeConfig.class);

    @Bean
    public FormattingConversionService mvcConversionService() {
        logger.info("mvcConversionService 执行了");
        DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(false);

        DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
        dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        dateTimeRegistrar.registerFormatters(conversionService);

        DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
        dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd"));
        dateRegistrar.registerFormatters(conversionService);

        return conversionService;
    }
}

WebMvcConfigurationSupport 替换为 WebMvcConfigurerAdapter 解决了问题,原因在于两者在 Spring MVC 中的 行为差异配置优先级。以下是详细分析:


1. 行为差异

特性 WebMvcConfigurationSupport WebMvcConfigurerAdapter
作用 完全覆盖 Spring MVC 默认配置 扩展 Spring MVC 默认配置
影响范围 全局配置,优先级最高 局部配置,优先级较低
推荐使用场景 需要完全自定义 MVC 配置 仅需扩展默认配置

2. 问题根源

使用 WebMvcConfigurationSupport 的问题
  • 覆盖默认配置 :继承 WebMvcConfigurationSupport完全禁用 Spring Boot 的自动配置(如静态资源处理、视图解析器等)。
  • 静态资源失效 :默认的静态资源路径(classpath:/static/)会被覆盖,导致资源无法访问。
使用 WebMvcConfigurerAdapter 的优势
  • 扩展默认配置WebMvcConfigurerAdapter扩展 Spring MVC 配置,不会覆盖默认行为。
  • 保留自动配置:Spring Boot 的自动配置(如静态资源处理)仍然生效。

3. 解决方案

推荐使用 WebMvcConfigurer

WebMvcConfigurerAdapter 已被标记为 @Deprecated,建议直接实现 WebMvcConfigurer 接口:

java 复制代码
@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
            .addResourceHandler("/plugins/**")
            .addResourceLocations("classpath:/static/plugins/")
            .setCachePeriod(0);
    }
}
关键配置对比
配置项 WebMvcConfigurationSupport WebMvcConfigurer
静态资源处理 需手动配置所有资源路径 仅需扩展默认配置
视图解析器 需手动配置 自动配置 + 扩展
拦截器 需手动注册 自动配置 + 扩展

4. 验证步骤

  1. 检查静态资源路径

    bash 复制代码
    jar -tvf target/*.jar | grep "mdui.min.css"
    # 正确输出:
    # BOOT-INF/classes/static/plugins/mdui/css/mdui.min.css
  2. 访问资源URL

    bash 复制代码
    curl -v http://localhost:8080/plugins/mdui/css/mdui.min.css
    # 预期响应:
    # HTTP/1.1 200
    # Content-Type: text/css
  3. 查看资源加载日志

    application.yml 中开启调试日志:

    yaml 复制代码
    logging:
      level:
        org.springframework.web: DEBUG

    正常日志

    log 复制代码
    DEBUG o.s.w.s.r.ResourceHttpRequestHandler - Resource found: class path resource [static/plugins/mdui/css/mdui.min.css]
  • 优化后的代码

    @Configuration
    public class DateTimeConfig implements WebMvcConfigurer {

    复制代码
      private static final Logger logger = LoggerFactory.getLogger(DateTimeConfig.class);
    
      @Override
      public void addFormatters(FormatterRegistry registry) {
          logger.info("DateTimeConfig: 注册自定义日期时间格式化器");
    
          // 注册 Java 8 日期时间格式化器
          DateTimeFormatterRegistrar dateTimeRegistrar = new DateTimeFormatterRegistrar();
          dateTimeRegistrar.setDateFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
          dateTimeRegistrar.setDateTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
          dateTimeRegistrar.registerFormatters(registry);
    
          // 注册传统日期格式化器
          DateFormatterRegistrar dateRegistrar = new DateFormatterRegistrar();
          dateRegistrar.setFormatter(new DateFormatter("yyyy-MM-dd"));
          dateRegistrar.registerFormatters(registry);
      }

    }


5. 总结

  • WebMvcConfigurationSupport :适合需要 完全自定义 MVC 配置的场景,但会 覆盖默认行为
  • WebMvcConfigurer :适合 扩展默认配置,保留 Spring Boot 的自动配置能力。

通过替换为 WebMvcConfigurer,静态资源处理得以保留,问题自然解决。

相关推荐
陈天伟教授8 小时前
人工智能训练师认证教程(2)Python os入门教程
前端·数据库·python
信看9 小时前
NMEA-GNSS-RTK 定位html小工具
前端·javascript·html
代码or搬砖9 小时前
RBAC(权限认证)小例子
java·数据库·spring boot
Tony Bai9 小时前
【API 设计之道】04 字段掩码模式:让前端决定后端返回什么
前端
苏打水com9 小时前
第十四篇:Day40-42 前端架构设计入门——从“功能实现”到“架构思维”(对标职场“大型项目架构”需求)
前端·架构
king王一帅9 小时前
流式渲染 Incremark、ant-design-x markdown、streammarkdown-vue 全流程方案对比
前端·javascript·人工智能
苏打水com10 小时前
第十八篇:Day52-54 前端跨端开发进阶——从“多端适配”到“跨端统一”(对标职场“全栈化”需求)
前端
Bigger10 小时前
后端拒写接口?前端硬核自救:纯前端实现静态资源下载全链路解析
前端·浏览器·vite