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

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

@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. 行为差异

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

2. 问题根源

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

3. 解决方案

推荐使用 WebMvcConfigurer

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

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

4. 验证步骤

  1. 检查静态资源路径

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

    curl -v http://localhost:8080/plugins/mdui/css/mdui.min.css
    # 预期响应:
    # HTTP/1.1 200
    # Content-Type: text/css
    
  3. 查看资源加载日志
    在 application.yml 中开启调试日志:

    logging:
      level:
        org.springframework.web: DEBUG
    

    正常日志:

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

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐