Java 的 Jar 包在各个地方的作用
使用记事本和命令行工具组合
-
先下载一个 Jar 文件用作测试
这里选择 Gson 库,它能在 Java 对象 和 Json 字符串之间进行转换
下载地址:Maven Repository: com.google.code.gson » gson » 2.10 (mvnrepository.com) 点击 Files 的 Jar 即可下载
-
打开一个文件夹,编辑一个最简单的 Java 程序
Main.java
import com.google.gson.Gson; public class Main { public static void main(String[] args) { // 创建 Gson 实例对象 Gson gson = new Gson(); // 实例化 Student 对象 Student student = new Student("Wen", 22); // 将 Student 对象转换为 Json 字符串 String studentStr = gson.toJson(student); // 将 Json 字符串转为 Student 对象 Student studentFromJson = gson.fromJson(studentStr, Student.class); System.out.println("student:" + student); System.out.println("studentFromJson:" + studentFromJson); System.out.println("student.name.equales(studentFromJson.name):" + student.name.equals(studentFromJson.name)); System.out.println("student.age == studentFromJson.age:" + (student.age == studentFromJson.age)); } static class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return this.name; } public int getAge() { return this.age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } } }
PS:不会也有人企图记事本里面 sout 吧
-
目录结构
Main.java --lib ----gson-2.10.jar
-
直接使用
javac Main.java
进行编译PS ...> javac .\Main.java .\Main.java:1: 错误: 程序包com.google.gson不存在 import com.google.gson.Gson; ^ .\Main.java:7: 错误: 找不到符号 Gson gson = new Gson(); ^ 符号: 类 Gson 位置: 类 Main .\Main.java:7: 错误: 找不到符号 Gson gson = new Gson(); ^ 符号: 类 Gson 位置: 类 Main 3 个错误
-
使用选项(
--class-path
,-classpath
,-cp
)来指定依赖库文件的路径PS ...> javac -cp .\lib\* .\Main.java PS ...> ls Directory: C:\Users\twat1\Documents\Work\other Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 2022/11/30 18:42 lib -a--- 2022/11/30 18:52 1685 Main.class -a--- 2022/11/30 18:49 1451 Main.java -a--- 2022/11/30 18:52 661 Main$Student.class
上面的 -cp .\lib* 表示当前目录 lib 文件夹下的使用 jar 或者 class 文件
-
然后信誓旦旦的直接
java Main
PS ...> java Main Exception in thread "main" java.lang.NoClassDefFoundError: com/google/gson/Gson at Main.main(Main.java:7) Caused by: java.lang.ClassNotFoundException: com.google.gson.Gson at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ... 1 more
不出意外的出意外了,为什么有
NoClassDefFoundError
了呢,明明编译的时候指定了呀,很明显 javac 和 java 分家,所以在使用 java 命令时也需要指定依赖的文件路径 -
使用选项(
--class-path
, -classpath
)来指定依赖库文件就好啦PS ...> java --class-path=".;.\lib\*" Main student:Main$Student@6aceb1a5 studentFromJson:Main$Student@12bc6874 student.name.equales(studentFormJson.name):true PS ...> java -classpath ".;.\lib\*" Main student:Main$Student@6aceb1a5 studentFromJson:Main$Student@12bc6874 student.name.equales(studentFormJson.name):true student.age == studentFromJson.age:true PS ...> java -cp ".;.\lib\*" Main student:Main$Student@6aceb1a5 studentFromJson:Main$Student@12bc6874 student.name.equales(studentFormJson.name):true student.age == studentFromJson.age:true
主要这里需要使用
.
java 命令在 JDK 5 开始默认是在当前目录了。但是这里指定了 classpath,所以需要另外设置一下,不然找到了 gson 库,找不到 Main 了,可以自己执行一下java -cp ".\lib\*" Main
命令 -
一个最简单的记事本加上命令行的示例就结束啦,但是有什么用呢?
在一些情况使用 SpringBoot 编译出生产运行的 Jar 包可能会上百MB,但是一般项目在进行到后期后,不会在有过多的依赖变动,那么通过将项目的依赖包提前部署在服务器上,不将依赖打包到运行的 Jar 内,在运行 Jar 程序时手动指定依赖的位置能使生产 jar 包的体积缩小的几 MB 甚至更小
使用 IDEA 进行依赖管理
注意指的是不用 Maven 和 Gradle 的情况,本文也不会涉及这两个项目构建工具
直接使用 IDEA 打开之前编辑的 Main.java 所在的文件夹,然后如果使用的 IDEA 的版本过高(🐶),那么它可能已经自动帮你识别到了 lib 文件下面的 Gson Jar 文件,并添加到了库路径
查看方法:
- 右上角有一个 Project Structure
- 使用快捷键 Ctrl + Shift + Alt + S
然后如果这个依赖里面有 gson 了,那就是可以直接打开 Main.java 如果直接点击绿色的箭头,或者按 Ctrl + Shift + F10 直接运行
运行效果
C:\Users\twat1\Documents\Work\Tools\JDK\jdk-19.0.1\bin\java.exe -javaagent:C:\Users\twat1\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\223.7571.123\lib\idea_rt.jar=50262:C:\Users\twat1\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\223.7571.123\bin -Dfile.encoding=UTF-8 -Dsun.stdout.encoding=UTF-8 -Dsun.stderr.encoding=UTF-8 -classpath C:\Users\twat1\Documents\Work\other\out\production\other;C:\Users\twat1\Documents\Work\other\lib\gson-2.10.jar Main
student:Main$Student@77f03bb1
studentFromJson:Main$Student@7a92922
student.name.equales(studentFormJson.name):true
student.age == studentFromJson.age:true
怎么做到的呢?
看 IDEA 运行命令,精简一下就是
java -javaagent:... [VM Args] -classpath "...\other;...\other\lib\gson-2.10.jar" Main
java 都知道
-javaagent 是什么呢,我也不知道,好像是字节插桩(🐶等我去瞅瞅),这里不重要
-classpath 就是刚刚我们上面写过的了,不过这里没有使用 *,而是直接使用的 Jar 名,因为 IDEA 只会使用你指定了依赖,通过上面图的 + 号添加依赖
Main 程序的入口类名
注意看上图的左边的 Libraries 选项卡,这里是指定的项目的库,有时候可能模块不一定引入了,如果模块运行缺少了Jar文件,记得去上图的 Dependencies 下查看是否有对于的依赖 Jar 包
IDEA + Tomcat 组合使用
这里就不从 0 到 1 创建 Web 项目了,我们只需要知道 Tomcat 会读取 WEB-INF\lib 下面的 lib 库,所以在一般情况下,可以直接将 Jar 放入 lib 文件夹下,IDEA一般情况下会自动识别,然后提供语法高亮,但是每一个项目都要存储一个 Jar 文件,不是很方便,这个 IDEA想到了,所以只需要和上面一样,将库文件添加到模块依赖,然后在 项目结构的 Artifacts 选项卡里把对应的依赖,添加到 lib 目录下,那么IDEA 在运行 Tomcat 时,会自动将库文件夹添加到 lib 文件夹下
所以就是如果项目运行时出现 NoClassDefFoundError,检查对应的工件 lib 有没有 Jar 或者库文件