编译依赖范围,如果没有指定,默认使用该依赖范围,对于编译源码、编译测试代码、测试、运行4种classpath都有效,比如上面的spring-web。
如:
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>compilescope>
dependency>
dependencies>
测试依赖范围,使用此依赖范围的maven依赖,只对编译测试、运行测试的classpath有效,在编译主代码、运行项目时无法使用此类依赖。比如junit,它只有在编译测试代码及运行测试的时候才需要。
如:
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>testscope>
dependency>
dependencies>
已提供依赖范围。表示项目的运行环境中已经提供了所需要的构件,对于此依赖范围的maven依赖,对于编译源码、编译测试、运行测试中classpath有效,但在运行时无效。比如上面说到的servlet-api,这个在编译和测试的时候需要用到,但是在运行的时候,web容器已经提供了,就不需要maven帮忙引入了。
如:
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>providescope>
dependency>
dependencies>
运行时依赖范围,使用此依赖范围的maven依赖,对于编译测试、运行测试和运行项目的classpath有效,但在编译主代码时无效,比如jdbc驱动实现,运行的时候才需要具体的jdbc驱动实现。
如:
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>runtimescope>
dependency>
dependencies>
系统依赖范围,该依赖与3中classpath的关系,和provided依赖范围完全一致。但是,使用system范围的依赖时必须通过systemPath元素显示第指定依赖文件的路径。这种依赖直接依赖于本地路径中的构件,可能每个开发者机器中构件的路径不一致,所以如果使用这种写法,你的机器中可能没有问题,别人的机器中就会有问题,所以建议谨慎使用。
如:
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>systemscope>
<systemPath>${basedir}/lib/threadpool4j-1.0.0.jarsystemPath>
dependency>
dependencies>
要搞懂上面的意思,我们先来认识一下java的classpath
Java中,我们经常听到classpath这个东西,classpath是JVM用到的一个环境变量,它用来指示JVM如何搜索class。
因为Java是编译型语言,源码文件是.java,而编译后的.class文件才是真正可以被JVM执行的字节码。因此,JVM需要知道,如果要加载一个com.chen.Hello的类,应该去哪搜索对应的Hello.class文件。简单地说就是去classpath指定路径下去找对应的.class文件
所以,classpath就是一组目录的集合,比如
C:\Users\Administrator\Desktop\tt;C:\java;"D:\My project\project1\bin"
现在假设classpath是 .;C:\Users\Administrator\Desktop\tt;C:\java .表示当前目录,当JVM在加载com.chen.Hello这个类时,会依次查找:
如果JVM在某个路径下找到了对应的class文件,就不再往后继续搜索。如果所有路径下都没有找到,就报错。
classpath的设定方法有两种:
没有设置系统环境变量,也没有传入-cp参数,那么JVM默认的classpath为.,即当前目录。
知道classpath后,举个例子,我们创建一个目录,创建一个java文件,并在类中输出 Hello World!:
public class Test {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
在该目录下执行编译javac 得到 Test.class 文件
如果我们不指定classpath,并且在 Test.class 所在的目录执行 cmd,是可以正确输出的:
但是我们不指定classpath,并且不是在 Test.class 所在的目录执行 cmd,是不可以正确输出的:
在别的目录执行:
但是我们指定classpath,并且不是在 Test.class 所在的目录执行 cmd,是可以正确输出的:
指定classpath且在别的目录执行:
可以看到输出了Hello,World! -cp是-classpath 的简写,两个可以互换, -cp指定jvm到只在这个路径下去找Test,即路径 C:\Users\Administrator\Desktop\tt\Test.class
我们熟悉的jar包,其实就是一个目录,就是一个zip格式的压缩文件。向上面的如果有很多很多.class文件,散落在各层目录中,肯定不便于管理和使用。这时候jar包就可以发挥作用了,把目录打一个包,变成一个文件,它可以把package组织的目录层级,以及各个目录下的所有文件(包括.class文件和其他文件)都打成一个jar文件,这样一来,就简单多了。
package com.chen;
public class Test {
public static void main(String[] args) {
System.out.println("Hello,World!");
}
}
创建好后,打包成jar包,把它赋值到别的地方,我们在这个地方进行测试
执行
java -cp ./demo2-1.0-SNAPSHOT.jar com.chen.Test
因为jar包就是zip包,所以,找到正确的目录,点击右键,在弹出的快捷菜单中选择“添加到压缩文件”,“压缩(zipped)文件夹”,就制作了一个zip文件。然后,把后缀从.zip改为.jar,一个jar包就创建成功,还有就是可以借助maven来获取jar包。
通过上面我们知道,java中编译代码、运行代码都需要用到classpath变量,classpath用来列出当前项目需要依赖的jar包
maven也一样,maven用到classpath的地方有:编译源码、编译测试代码、运行测试代码、运行项目,这几个步骤都需要用到classpath。
编译、测试、运行需要的classpath对应的值可能是不一样的,这个maven中的scope为我们提供了支持,可以帮我们解决这方面的问题,scope是用来控制被依赖的构件与classpath的关系(编译、打包、运行所用到的classpath),scope几种值如开头:
我们打包一个jar包,并在我们项目中引用,通过改变scope来看看
引用我们本地打包的HelloWorld
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
dependencies>
1,compile
把scope 改成 compile ,这是默认的
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>compilescope>
dependency>
dependencies>
编译测试代码
可以看到在编译源码、编译测试代码都可以找到HelloWorld类
2,test
把scope 改成 test
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>testscope>
dependency>
dependencies>
编译测试代码
可以看到在只在编译测试代码可以找到HelloWorld类
3,provide
把scope 改成 provide
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>providescope>
dependency>
dependencies>
可以看到在编译源码、编译测试代码都可以找到HelloWorld类
4,runtime
把scope 改成 runtime
<dependencies>
<dependency>
<groupId>com.chengroupId>
<artifactId>HelloWorldartifactId>
<version>1.0-SNAPSHOTversion>
<scope>runtimescope>
dependency>
dependencies>
可以看到在只在编译测试代码可以找到HelloWorld类