Spring框架jar包全解析:从手动依赖到打包运行 简介这份Spring框架所需JAR包的完整合集专为Java后端开发者和Spring框架学习者准备用于解决搭建Spring及SpringMVC项目时依赖缺失、版本冲突、逐个查找下载成本高的问题。压缩包共包含21个文件即20个JAR包和1个XML配置文件整体大小仅7.71兆字节内容涉及Spring核心容器、SpringMVC、JDBC与事务管理、C3P0连接池、Oracle数据库驱动、JUnit单元测试等常用开发模块同时附带一份applicationContext.xml配置示例可对照理解Bean装配、数据源注入和事务配置方式快速搭建可运行的基础工程。包内文件按功能模块归类层次清晰引用进项目时能显著减少匹配版本的时间。目前已有309人学习浏览对于希望快速搭建Spring开发环境、或者需要在离线条件下完成工程配置的初级与中级Java工程师而言是一份高效、省心的实用资源也可作为了解Spring依赖组织的参考样例。 做Java开发这些年我经常在论坛和社群里看到有人求一份Spring框架需要的jar包完整版。尤其是一些还在用传统Web项目、没引入Maven或Gradle的团队新同事入职第一件事就是去网上搜各种jar包往lib目录里塞折腾半天还经常缺这缺那。这篇文章我就把Spring项目的jar包体系彻底讲清楚同时把打包、运行、排查这些配套问题一并带出来希望对还在手动管理依赖的朋友有帮助。1. Spring框架jar包全景认知1.1 为什么会有完整版jar包这种需求Spring从诞生到现在已经拆成了几十个模块真正开发Web应用时核心依赖其实用不到那么多。但网上很多资料年代久远动不动让人拷贝一整个spring-framework-x.x.x.RELEASE压缩包里面的jar包近百个很多根本用不上。手动收集jar包最容易踩的坑有三个版本不一致spring-core用的5.2版本spring-webmvc却用了4.3版本运行起来各种NoSuchMethodError。传递依赖缺失Spring在官网文档中明确标注了每个模块依赖的第三方库比如spring-context需要commons-logging没有这个jar包容器启动直接报ClassNotFoundException。重复引入lib目录里同时存在log4j-1.2.17.jar和logback-classic.jar虽然不至于崩但日志输出经常莫名其妙。所以如果要手动维护第一步不是下载而是先搞明白Spring的模块划分。1.2 Spring各模块jar包功能对照以Spring 5.2.x为例常用的模块和职责如下表所示jar包名称职责说明spring-core.jarIOC容器的基础工具类Resource、ConversionService等核心抽象都在这spring-beans.jarBean的创建、管理和属性填充JavaBean相关的核心逻辑spring-context.jar在上面两者之上提供ApplicationContext、事件机制、国际化等spring-expression.jarSpEL表达式语言支持spring-aop.jarAOP代理支持需要配合AspectJ相关jar包使用spring-web.jarWeb开发的基础支持包括DispatcherServlet所需的接口定义spring-webmvc.jarSpring MVC框架的完整实现spring-jdbc.jarJDBC抽象层封装了JdbcTemplate等spring-tx.jar声明式事务管理支持spring-orm.jar集成Hibernate、JPA、MyBatis等ORM框架注意spring-core并不是孤立的它底层还依赖spring-jcl组件Spring 5.x内部统一的日志门面这是很多人容易漏掉的一个jar包。如果使用Spring AOP还需要引入aspectjweaver。如果用到Autowired注解需要spring-beans和spring-context一起配合光放一个spring-core根本跑不起来。2. 两种主流的依赖组织方式2.1 手动搭建jar包目录的注意事项老式项目通常把jar包放在WEB-INF/lib目录下IDE会自动识别。如果你的项目结构比较特殊比如IDEA下用的是libs目录那么需要在Project Structure - Libraries里手动添加或者通过File - Project Structure - Modules - Dependencies把该目录加入依赖。手动收集时我建议把所有jar包按用途拆开放不要一股脑混在一起。推荐目录结构lib/ spring/ spring-core-5.2.20.RELEASE.jar spring-beans-5.2.20.RELEASE.jar spring-context-5.2.20.RELEASE.jar spring-web-5.2.20.RELEASE.jar spring-webmvc-5.2.20.RELEASE.jar spring-jdbc-5.2.20.RELEASE.jar thirdparty/ commons-logging-1.2.jar aspectjweaver-1.9.6.jar jackson-databind-2.11.4.jar每个模块的版本必须严格保持一致这是手动维护jar包时最基本的纪律。因为Spring内部类之间的方法签名在升级时会变化混用版本极容易出现ClassNotFoundError。2.2 用Maven/Gradle替代手动管理的迁移思路手动收集jar包适合学习Spring原理或维护老项目但一旦项目模块多了手动管理就是一场噩梦。我已经不止一次见到一个lib目录里堆着上千个jar包既不知道哪个是必需哪个是垃圾也不敢随便删。用Maven管理依赖之后只需要在pom.xml里声明几个核心坐标。我贴一份常用的Spring 5.x依赖清单直接复制就能用properties spring.version5.2.20.RELEASE/spring.version /properties dependencies dependency groupIdorg.springframework/groupId artifactIdspring-core/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-beans/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-context/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-web/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-jdbc/artifactId version${spring.version}/version /dependency dependency groupIdorg.springframework/groupId artifactIdspring-tx/artifactId version${spring.version}/version /dependency /dependenciesMaven的传递依赖机制会自动拉取spring-jcl等间接依赖不需要我们手动声明。这也是我强烈建议新项目一律使用构建工具的原因至少不会有低级版本冲突。3. 从零搭一个Spring项目jar包放好后怎么跑起来3.1 目录结构与jar包放置方案假设你手头没有Maven只能手动放置jar包我以最简单的控制台程序为例。推荐目录结构如下demo-spring/ src/ com/example/ Main.java UserService.java lib/ spring-core-5.2.20.RELEASE.jar spring-beans-5.2.20.RELEASE.jar spring-context-5.2.20.RELEASE.jar spring-jcl-5.2.20.RELEASE.jar commons-logging-1.2.jar这里的关键点是不要漏掉spring-jcl。Spring 5.x的日志桥接已经合并到了spring-jcl里如果缺它启动时通常会报java.lang.NoClassDefFoundError: org/apache/commons/logging/LogFactory。3.2 最小化配置文件和启动代码新建一个业务类package com.example; public class UserService { private String name; public void setName(String name) { this.name name; } public void sayHello() { System.out.println(Hello, name); } }在src/main/resources目录或项目根目录下新建applicationContext.xml?xml version1.0 encodingUTF-8? beans xmlnshttp://www.springframework.org/schema/beans xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd bean iduserService classcom.example.UserService property namename valueSpring/ /bean /beans启动类package com.example; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Main { public static void main(String[] args) { ApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml); UserService userService (UserService) context.getBean(userService); userService.sayHello(); } }如果是在IDEA里跑右键Main直接运行IDEA会自动把src/main/resources加入classpath所以能正确读取配置文件。如果在命令行手动编译运行需要把src/main/resources也加入classpath或者把配置文件放到classes目录下。3.3 验证容器是否正常工作的两个小技巧第一次跑通Spring时很多人不知道如何判断依赖是否齐了。除了程序正常输出还可以在main方法里做两个简单验证打印context.getBeanDefinitionCount()如果返回的数量和xml里配置的bean数量一致说明IOC容器初始化成功。调用context.getBean(userService)前先用context.containsBean(userService)判断是否存在避免直接抛NoSuchBeanDefinitionException。这两个方法成本极低排查依赖问题时非常实用。如果连getBean都没走到就报错那问题大概率出在jar包缺失或版本不匹配上先把classpath上的jar完整列出来逐一比对。4. 把Spring应用打包成可执行jar包4.1 静态html页面打进jar包的原理热搜词里有一条是生成显示helloworld的静态html页面打包成jar包这里我详细展开。先把概念说清楚jar包本质上就是一个Zip压缩文件里面可以存放class、配置文件、静态资源等。Java的ClassLoader能从jar包内部读取文件所以把静态页面放到classpath目录下程序运行时可以用getResource方法取出来。在Spring Boot项目中静态页面默认放在src/main/resources/static目录打包时会自动被复制进jar包的BOOT-INF/classes/static下。但使用纯Spring项目时不会自动处理静态资源需要手动配置。如果你用Spring Boot做演示目录结构如下src/main/resources/ static/ index.html application.propertiesindex.html内容!DOCTYPE html html head meta charsetUTF-8 titleHello World/title /head body h1Hello World from Spring Boot/h1 /body /html然后执行mvn clean package得到spring-boot-demo.jar运行java -jar spring-boot-demo.jar浏览器访问http://localhost:8080/就能看到页面。4.2 Spring Boot打可执行jar包的步骤与参数说明Spring Boot项目打可执行jar包重点在于spring-boot-maven-plugin。这个插件的作用是生成一个MANIFEST.MF指定Start-Class为启动类并把所有依赖jar包解压后再合并转载入BOOT-INF/lib这样java -jar才能直接运行。build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId version2.6.13/version executions execution goals goalrepackage/goal /goals /execution /executions /plugin /plugins /build打包后会自动生成两个文件xxx.jar和xxx.jar.original。前者是可执行jar包后者是Maven默认打出的原始jar包里面只有项目自身的class和配置文件没有依赖jar包。生产环境直接部署可执行版本即可。4.3 IntelliJ IDEA手动打jar包的完整流程不依赖Maven直接用IDEA打jar包也完全可行只是步骤稍微多点。我以纯Spring项目为例在IDEA菜单栏选择File - Project Structure - Artifacts - - JAR - From modules with dependencies。在弹出的窗口中Main Class选择启动类JAR files from libraries选择copy to the output directory and link via manifest如果选择extract to the output directory则会把依赖jar包的内容解压后合并进同一个jar包。点击OK后在IDEA菜单栏选择Build - Build Artifacts - Build生成的jar包会在out/artifacts/目录下。其他机器运行时需要保持lib目录与jar包相对路径一致或者把依赖jar包解压合并这一点非常关键手动打包报ClassNotFoundException基本都是classpath没配好。5. jar包实战过程与问题排查5.1 jar包反编译的正确姿势和工具推荐日常开发中经常遇到ClassNotFoundException却不知道该jar包里到底有没有这个类这时就要用到反编译工具。市面上的工具很多我按使用场景推荐几款工具名称适用场景javapJDK自带查看类结构、方法签名命令行直接用最轻量JD-GUI图形化查看jar包内class源码适合快速查看完整代码逻辑CFR反编译质量较高支持Java 8以上语法适合批量反编译IntelliJ IDEA自带反编译器配合Find in JARs功能适合在IDE内快速查找某个类命令行查看class或jar包内类的通用命令# 查看jar包内容列表 jar tf spring-core-5.2.20.RELEASE.jar | grep 类名 # 查看单个class文件的方法签名 javap -classpath spring-core-5.2.20.RELEASE.jar org.springframework.core.io.Resource如果jar tf能列出类但javap报错说明class文件格式与当前JDK版本不兼容比如用JDK 17去解析旧的class无法识别这时需要更换JDK版本或换其他工具。5.2 解压jar包编辑后IDEA报文件只读怎么破热搜词里有将jar包解压了进行编辑的时候IDEA依旧报该文件只读这个坑我很熟悉。IDEA把jar包当作一个整体来对待直接解压出来修改在弹出的编辑器里是只读的因为IDEA没把解压目录当作源码目录。第一步不要直接改jar包内部。正确的做法是把jar包复制一份到普通文件夹用jar xf解压改完代码或配置后再用jar cf重新打包。但这样容易破坏原有目录结构一旦缺少META-INF/MANIFEST.MF打包后的jar包就无法运行。第二步在IDEA中把解压后的文件夹标记为Sources Root这样IDEA才允许编辑源码。右键文件夹 -Mark Directory as - Sources Root然后新建一个类修改编译后替换classes目录下对应的class文件。第三步如果只想修改jar包内的某个配置文件比如application.yml可以用jar uf命令只更新单个条目这个方式最稳妥不会重打整个包导致其他文件受损jar uf myapp.jar BOOT-INF/classes/application.yml5.3 老项目导入jar包时我踩过的典型坑很多老ERP系统比如早期基于Java开发的进销存、财务系统没有Maven只能通过lib目录导入jar包。这类系统通常代码量大、依赖陈旧导入新jar包时极易出现问题。第一注意tiptop这类老系统的依赖冲突。它们往往自带一套老版本的common-lang、log4j和servlet-api一旦导入Spring框架就很容易和原有的类冲突。我的建议是新老jar包分目录存放并在classpath中把Spring相关jar包放在前面让类加载器优先加载新版类。第二老项目里常见javax.servlet包与新版jakarta.servlet包混用的情况。Spring 5用的是javax.servletSpring Boot 3才切到jakarta.servlet导入时务必看清版本。第三导入之后一定要重建索引并重启IDEA。很多诡异问题其实不是代码问题而是IDEA没刷新依赖。在Maven Projects面板点Reload All Maven Projects或对普通项目执行File - Invalidate Caches / Restart。最后再分享一点个人体会手动收集jar包只能算是一个过渡阶段它能帮助你透彻理解Spring的运行机制但真正到了项目工程化Maven或Gradle才是标准答案。如果你还在为jar包完整版发愁我建议直接把项目升级到Maven结构用一两天的成本换取之后几年不踩依赖坑这笔账很划算。在一个老项目里接手过千包大战的人应该都懂这句话的分量。本文还有配套的精品资源点击获取