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

Spring Boot可执行Jar启动失败(tomcat-embed-jasper相关问题)

解决方案:Spring Boot可执行Jar中JSP渲染+zip file closed异常修复

问题本质

Spring Boot可执行Jar采用嵌套Jar结构,而tomcat-embed-jasper默认的资源加载逻辑不支持从嵌套Jar中读取JSP文件,导致Zip资源被提前关闭,触发java.lang.IllegalStateException: zip file closed异常。IDEA中运行正常是因为它直接使用项目本地文件目录,而非嵌套Jar结构。

可选解决方案

方案1:打包为WAR文件(推荐,兼容性更好)

WAR文件结构无需嵌套Jar,Tomcat可直接读取JSP资源,步骤如下:

  1. 修改pom.xml的打包类型为war
<packaging>war</packaging>
  1. 调整依赖配置,将tomcat starter设为provided,保留jasper依赖
<dependencies>
    <!-- 其他依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-tomcat</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
    </dependency>
</dependencies>
  1. 让主类继承SpringBootServletInitializer
@SpringBootApplication
public class YourApp extends SpringBootServletInitializer {
    public static void main(String[] args) {
        SpringApplication.run(YourApp.class, args);
    }
}
  1. 执行打包命令:
mvn clean package

生成的WAR文件可直接用java -jar your-app.war启动,JSP能正常渲染,无zip文件异常。

方案2:自定义Tomcat资源加载器(保持Jar打包)

通过将JSP文件提取到临时目录,避免嵌套Jar的读取限制:

  1. 添加配置类,自定义Tomcat上下文和资源加载逻辑
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;

@Configuration
public class TomcatJspConfig {

    @Bean
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatJspCustomizer() {
        return factory -> factory.addContextCustomizers(context -> {
            try {
                // 把classpath下的JSP复制到临时目录
                ClassPathResource jspDir = new ClassPathResource("WEB-INF/jsp/");
                File tempJspDir = Files.createTempDirectory("spring-boot-jsp").toFile();
                copyDir(jspDir.getFile(), tempJspDir);
                // 设置Tomcat上下文的文档根为临时目录
                context.setDocBase(tempJspDir.getAbsolutePath());
            } catch (IOException e) {
                throw new RuntimeException("Failed to copy JSP files to temp dir", e);
            }
        });
    }

    @Bean
    public InternalResourceViewResolver viewResolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setPrefix("/WEB-INF/jsp/");
        resolver.setSuffix(".jsp");
        return resolver;
    }

    // 递归复制目录
    private void copyDir(File source, File target) throws IOException {
        if (source.isDirectory()) {
            if (!target.exists()) target.mkdirs();
            for (String child : source.list()) {
                copyDir(new File(source, child), new File(target, child));
            }
        } else {
            Files.copy(source.toPath(), target.toPath());
        }
    }
}
  1. 修改pom.xml,确保打包时包含JSP资源
<build>
    <resources>
        <resource>
            <directory>src/main/webapp</directory>
            <includes>
                <include>WEB-INF/jsp/**</include>
            </includes>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <includeResources>
                    <include>WEB-INF/jsp/**</include>
                </includeResources>
            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  1. 执行mvn clean install后,运行Jar文件即可正常渲染JSP。

验证步骤

  1. 执行打包命令后,检查生成的Jar/WAR文件是否包含WEB-INF/jsp目录下的文件
  2. 启动应用,访问JSP页面,确认页面正常渲染且无启动异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:00:40