Contents

Spring Boot 静态资源首次访问无样式问题排查

问题现象

在开发SSO登录页面时遇到一个奇怪的问题:

  • 直接在浏览器地址栏输入 http://localhost:8080/sso/login 访问,页面没有CSS样式
  • 但是点击刷新按钮后,样式就正常显示了
  • 这种"首次无样式,刷新后有样式"的现象很诡异

排查过程

最初怀疑是以下问题:

  1. ❌ Sa-Token拦截器配置问题 - 已排除静态资源路径
  2. ❌ Spring MVC静态资源配置问题 - 配置正确
  3. ❌ 浏览器缓存问题 - 尝试添加版本参数无效
  4. ❌ CSS文件路径问题 - 文件存在且内容正确

真正原因

通过浏览器开发者工具的Network面板发现,CSS文件的请求URL变成了:

http://localhost:8080/css/sso/login.css;jsessionid=8E5753F407FFFE8DF6116069A2207295

根本原因:Spring Session的URL重写机制!

  • 当浏览器首次访问时,Spring不确定是否支持Cookie
  • 为了保证会话跟踪,Spring会在所有URL后面添加 ;jsessionid=xxx
  • 这导致静态资源路径变成非法URL,服务器无法找到对应文件
  • 刷新时浏览器已经建立Cookie,不再使用URL重写,所以正常

解决方案

在Spring配置类中添加ServletContextInitializer,禁用URL重写:

@Bean
public ServletContextInitializer servletContextInitializer() {
    return new ServletContextInitializer() {
        @Override
        public void onStartup(ServletContext servletContext) throws ServletException {
            // 只使用Cookie跟踪会话,禁用URL重写
            servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
            log.info("已禁用URL重写,只使用Cookie跟踪会话");
        }
    };
}

总结

  • 问题本质:Spring Session的URL重写机制影响静态资源访问
  • 解决思路:禁用URL重写,只使用Cookie进行会话跟踪
  • 经验教训:遇到静态资源加载问题时,要检查实际的网络请求URL
  • 适用场景:现代Web应用基本都支持Cookie,可以安全禁用URL重写

这个问题比较隐蔽,因为只在特定条件下出现(首次访问且无Cookie),容易被忽略。