【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,静态资源处理得以保留,问题自然解决。

相关推荐
用户380225859824几秒前
vue3源码解析:生命周期
前端·vue.js·源码阅读
遂心_几秒前
前端路由进化论:从传统页面到React Router的SPA革命
前端·javascript
前端菜鸟杂货铺6 分钟前
前端首屏优化及可实现方法
前端
遂心_6 分钟前
React Fragment与DocumentFragment:提升性能的双剑合璧
前端·javascript·react.js
ze_juejin7 分钟前
ionic、flutter、uniapp对比
前端
咚咚咚ddd7 分钟前
WebView Bridge 跨平台方案:统一 API 实现多端小程序通信
前端·前端工程化
程序视点8 分钟前
Microsoft .Net 运行库离线合集包专业解析
前端·后端·.net
混水的鱼9 分钟前
PasswordValidation 密码校验组件实现与详解
前端·react.js
ze_juejin10 分钟前
async、defer 和 module 属性的比较
前端
归于尽12 分钟前
关于数组的这些底层你真的知道吗?
前端·javascript