一、介绍
java -cp 命令中 cp 指的就是 classpath。使用该命令可以运行jar中的某个指定的测试类
使用方法
Java -cp 依赖jar或者是依赖jar库 测试类的全限定名
1
其中需要注意的是“依赖jar或者是依赖库”一定要是绝对路径。如果依赖的是jar库,多个jar路径之间的分割符会因平台的不同存在差异,在window上用分号";“分割,在linux上用冒号”:"分割
二、使用
1、创建springboot功能
创建一个springboot项目,名叫javapc
新建MyTestBean类
package com.javapc.demo.test;
public class MyTestBean {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void outStr() {
System.out.println("我是猪!!!");
}
}
在resources下创建spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="myTestBean" class="com.javapc.demo.test.MyTestBean"/>
</beans>
创建测试类Test
package com.javapc.demo.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
MyTestBean bean = (MyTestBean) ac.getBean("myTestBean");
bean.outStr();
}
}
项目结构很简单,如下图所示
打包项目
打包完成后我们通过java -pc 运行一下
zhishengjie@zhishengjiedeMacBook-Pro target % java -cp demo-0.0.1-SNAPSHOT.jar com.javapc.demo.test.Test
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/context/ApplicationContext
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
at java.lang.Class.getMethod0(Class.java:3018)
at java.lang.Class.getMethod(Class.java:1784)
at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:650)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:632)
Caused by: java.lang.ClassNotFoundException: org.springframework.context.ApplicationContext
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:355)
at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
... 7 more
我们会发现,起不来,会报java.lang.NoClassDefFoundError错误。其实我们一看就知道原因,是因为缺少spring的相关依赖。其实springboot项目打包需要借助一个plugin的,否则打出来的jar中是不会包含项目启动所需要的依赖的。但是我们要的就是不包含依赖jar的项目jar包
<!-- springboot打包插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.javapc.demo.JavapcApplication</mainClass>
<!-- <skip>true</skip> -->
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
其实此刻我们发现的这个问题,也是 java -cp 的一个优点。
举个例子:
假如我们这个程序的运行时需要依赖另一个叫 other.jar 的包。
如果我们使用 java -jar 的话,就只能把 other.jar 放到 demo-0.0.1-SNAPSHOT.jar 中,因为 -jar 后面只能指定一个 jar 包启动。
如果使用 -cp ,我们可以选择将 other.jar 放到 demo-0.0.1-SNAPSHOT.jar 中,也可以选择不放入 demo-0.0.1-SNAPSHOT.jar 中,使用以下命令来运行:
# 当前环境是linux,所以使用":"分割
java -cp other.jar:demo-0.0.1-SNAPSHOT.jar com.javapc.demo.test.Test
这样做的好处就是,假如修改了 demo-0.0.1-SNAPSHOT.jar 中的某个类,可以只上传修改后的 demo-0.0.1-SNAPSHOT.jar 到服务器,jar体积更小,上传也会节约很多时间。
其实讲到这里大家就都已经清楚上面的报错应该怎么修改了,不就是jar中没有包含项目启动所需要的spring的相关jar嘛,我们把spring的jar拎出来放到单独的一个文件夹中,我们使用 java -cp 运行
# java -cp 依赖jar:依赖jar:依赖jar:demo-0.0.1-SNAPSHOT.jar com.javapc.demo.test.Test
java -cp spring1.jar:spring2.jar:spring3.jar:demo-0.0.1-SNAPSHOT.jar com.javapc.demo.test.Test
是不是就是上面脚本这个意思,但是我们依赖的jar有很多,这样一个一个写进来岂不是要累死了,所以我们可以通过shell脚本来实现
启动程序的shell脚本
export LANG=en_US.UTE-8
rootpath="/Users/zhishengjie/workspace/IdeaProjects/test_javapc"
appname="project"
apppath=${rootpath}/${appname}
cd ${apppath}
export CP_PATH=.
# 加载启动项目所需的依赖jar,这里就是指项目所依赖的spring相关jar
for i in `ls ${rootpath}/libs/`
do
CP_PATH=$CP_PATH:${rootpath}/libs/$i
done
echo "打印加载的依赖……"
echo ${CP_PATH}
echo "打印依赖结束!"
# 加载项目jar,这里就是指demo-0.0.1-SNAPSHOT.jar
for i in `ls ${apppath}/`
do
CP_PATH=$CP_PATH:${apppath}/$i
done
echo "打印部署jar的……"
echo ${CP_PATH}
echo "打印部署jar结束!"
# com.javapc.demo.test.Test 指的就是项目中启动的测试类的全限定类名
exec=`ps -ef | grep com.javapc.demo.test.Test | grep java | grep -v grep | awk '{print $2}'`
if [ -n "$exec"];then
echo "Processing testbat is running. Don't call it again. "
fi
if [ -z "$exec"];then
echo "Start the process testbat."
java -cp ${CP_PATH} -Dfile.encoding=utf-8 -Xmx512m -Xmx12288m com.javapc.demo.test.Test $*
fi
下图为存放的目录结构
运行脚本,这不就成功了嘛
zhishengjie@zhishengjiedeMacBook-Pro test_javapc % ./start.sh
打印加载的依赖……
.:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/jakarta.annotation-api-1.3.5.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/jul-to-slf4j-1.7.31.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/log4j-api-2.14.1.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/log4j-to-slf4j-2.14.1.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/logback-classic-1.2.3.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/logback-core-1.2.3.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/slf4j-api-1.7.31.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/snakeyaml-1.28.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-aop-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-beans-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-boot-2.5.2.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-boot-autoconfigure-2.5.2.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-boot-jarmode-layertools-2.5.2.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-context-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-core-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-expression-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-jcl-5.3.8.jar
打印依赖结束!
打印部署jar的……
.:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/jakarta.annotation-api-1.3.5.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/jul-to-slf4j-1.7.31.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/log4j-api-2.14.1.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/log4j-to-slf4j-2.14.1.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/logback-classic-1.2.3.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/logback-core-1.2.3.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/slf4j-api-1.7.31.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/snakeyaml-1.28.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-aop-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-beans-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-boot-2.5.2.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-boot-autoconfigure-2.5.2.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-boot-jarmode-layertools-2.5.2.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-context-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-core-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-expression-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/libs/spring-jcl-5.3.8.jar:/Users/zhishengjie/workspace/IdeaProjects/test_javapc/project/demo.jar
打印部署jar结束!
Processing ecifbat is running. Don't call it again.
Start the process ecifat.
14:59:37.405 [main] DEBUG org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@5fcfe4b2
14:59:37.548 [main] DEBUG org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loaded 1 bean definitions from class path resource [spring.xml]
14:59:37.577 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myTestBean'
我是猪!!!
zhishengjie@zhishengjiedeMacBook-Pro test_javapc %
其实本文到此就应该结束了,但是有的小伙伴可能会有些疑问,你怎么知道项目依赖的spring的jar都有哪些的?这……
其实我是使用springboot的插件打了个jar,把这个jar包中的BOOT-INF下的lib目录给拿过来了……
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!