Maven(二):Maven的使用入门

news2024/11/26 0:31:01

文章目录

  • 使用入门
    • 项目骨架
    • pom.xml
    • 构建过程
    • 编写测试
    • 打包和运行
      • 常用打包方式
      • maven-shade-plugin
        • 使用
        • filter与artifactSet - 过滤jar包
        • Transformer
  • 参考文献

使用入门

项目骨架

对于一个使用Maven来管理的项目,Maven提倡使用一个目录结构标准:

${basedir}	存放pom.xml和所有的子目录
${basedir}/src/main/java	项目的java源代码
${basedir}/src/main/resources	项目的资源,比如说property文件,springmvc.xml
${basedir}/src/test/java	项目的测试类,比如说Junit代码
${basedir}/src/test/resources	测试用的资源
${basedir}/src/main/webapp/WEB-INF	web应用文件目录,web项目的信息,比如存放web.xml、本地图片、jsp视图页面
${basedir}/target	打包输出目录
${basedir}/target/classes	编译输出目录
${basedir}/target/test-classes	测试编译输出目录
Test.java	Maven只会自动运行符合该命名规则的测试类
~/.m2/repository	Maven默认的本地仓库目录位置

在这里插入图片描述

说到这里,可以提一下Archetype,Maven中利用Archetype来生成项目骨架,其实就是上面这些东西,会自动生成一个空白项目的目录,连pom.xml都给你生成了,异常贴心。

当然,如果你是用的IDE的话,项目骨架它自动就给你建好了,但如果你一定要体验一下通过命令行来生成项目骨架的话,也可以。

如果是Maven3的话,在指定的项目父目录执行:

mvn archetype:generate

这个过程实际上是运行插件maven-archetype-plugin的过程。

接着会输出很多很多很多东西,这是在向你展示可供选择的项目骨架,即Archetype,每个Archetype都有一个编号,我看了一下,编号都到2423了。。。

我们可以选择maven-archetype-quickstart,输入后回车,通过数字选择就可以。

然后maven会提示你输入要创建项目的groupID、artifactId、version以及包名package等。全部输入,然后确定Y:

在这里插入图片描述

目录已经建好了。

像是src/main/javasrc/test/javapom.xml这种,它都给你就建好了。

我设定的包名是org.wlh,于是它很贴心的给我生成了一个src/main/java/org/wlh/App.java来作为主文件。

Archetype可以帮我们迅速构建起项目的骨架,而且提供了多种模板,非常棒。

这个了解下就行,毕竟IDE都帮我们做好了。

pom.xml

类似Make的Makefile、Ant的build.xml一样,Maven项目的核心是pom.xml。

POM(Project Object Model,项目对象模型)定义了项目的基本信息,比如说项目如何构建、声明项目依赖等。

下面是一个极度原始的pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
    xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0
    http://maven.apache.org/xsd/maven-4.0.0.xsd">
 
    <!-- 模型版本 -->
    <modelVersion>4.0.0</modelVersion>
    <!-- 公司或者组织的唯一标志,并且配置时生成的路径也是由此生成, 如com.companyname.project-group,maven会将该项目打成的jar包放本地路径:/com/companyname/project-group -->
    <groupId>com.companyname.project-group</groupId>
 
    <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 -->
    <artifactId>project</artifactId>
 
    <!-- 版本号 -->
    <version>1.0</version>
    <name>Hello World Project</name>
</project>

第一行是XML头,指定了该xml文档的版本和编码方式。

其余是project元素,project是pom.xml的根元素。

modelVersion指定了当前pom模型的版本,对于Maven2及Maven3来说,它只能是4.0.0。

这段代码中最重要的是groupId、artifactId和version三行。这三个元素基本定义了一个项目的基本坐标。

  • groupId:定义了项目属于哪个组;
  • artifactId:定义了当前项目在组内的唯一ID;
  • version:当前项目的版本;
  • name:非必要,定义了一个对于用户更友好的项目名称。

正常来讲,应该把项目主代码放到src/main/java目录下,Maven会自动搜索这个目录来找到项目入口类。

其次,项目入口类的包名,应该跟POM中定义的groupId和artifactId保持一致,即包名为groupId.artifactId,这样子更加清晰,也方便Maven的自动搜索。当然,不一样也是可以的,对运行没啥大影响。

构建过程

入口类编写完毕后,就可以使用Maven进行编译了。

在根目录下运行命令:mvn clean compile

clean会告知Maven清理输出目录target/;

compile则告诉Maven编译项目主代码;

完成后,Maven会将项目主代码编译至target/classes目录。

比如说我现在声明一个主类Hello World:

package org.wlh.helloworld;
public class Hello {
	public static void main(String[] args) {
		System.out.println(new Hello().HelloMaven());
	}

	public String HelloMaven(){
		return "Hello Maven";
	}
}

编写测试

Maven中测试代码应该放在src/test/java目录下。

Java项目中常用的单元测试框架JUnit。使用时需要在POM中引用该依赖。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.wlh</groupId>
	<artifactId>helloworld</artifactId>
	<version>1.0-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.12</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

代码中添加了dependencies元素,该元素下可以包含多个dependency元素以声明项目的依赖,一个dependency就是一个依赖。

dependency元素下的scope元素,表示该依赖的依赖范围

  • test:只对测试代码有效,在主代码中使用会报编译异常;
  • compile:默认的依赖范围,表示主代码和测试代码都能使用。

在src/test/java下编写测试类HelloTest:

package org.wlh.helloworld;

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class HelloTest {
	@Test
	public void testHello(){
		Hello hello = new Hello();
		String result = hello.HelloMaven();
		assertEquals("Hello Maven", result);
	}
}

以上就是一个典型单元测试的三个步骤:

  • 准备测试类及数据
  • 执行要测试的行为
  • 检查结果

Junit3中,约定需要执行的测试方法以test开头,Junit4仍然推荐遵循这一规定。另外,Junit4中,需要执行的测试方法都应该以@Test进行标注。

测试用例编写完成后,可以执行测试了。如果是通过mvn命令行的话,那需要运行mvn clean test

打包和运行

打包mvn clean package

输出的日志里可以看到jar:jar的形式,实际上就是把jar插件的jar目标将项目主代码进行打包。

如果想让其他的Maven项目直接引用这个jar包作为依赖的话,则需要把这个jar包安装到本地仓库:

安装mvn clean install

这里需要注意,默认打包生成的jar是不能够直接运行的。如果直接java -jar运行的话,会提示jar包中没有主清单属性

这是因为带有main方法的入口类不会添加到manifest中,即打开jar文件中的META-INF/MANIFEST.MF文件,无法看到Main-Class一行。

另外,如果你的项目里有依赖其他jar包的话,Maven默认的package也不会把它们打进去,而只会打包自身的class文件。

那如果想生成可执行的jar文件,该怎么办呢?

两种解决方案:

  1. 给上一步生成的jar包添加主清单属性,即在MANIFEST.MF添加一行:Main-Class: org.wlh.helloworld.Hello,即入口类的完整路径,再java -jar运行就可以了。
  2. 借助其他插件,比如说maven-shade-plugin插件,一步到位生成可执行jar包。

常用打包方式

在Maven中,其实提供了3种方式来打包:

  • maven-jar-plugin:默认的打包插件,用来打普通的jar包,不可执行;
  • maven-shade-plugin:用来打可执行jar包,就是所谓的fat jar包,也支持依赖项目过滤等;
  • maven-assembly-plugin:支持自定义的打包结构,也可以定制依赖项目等。

maven-jar-plugin打的包,只包含了项目本身的class文件,并没有把项目依赖的所有jar包一起打进去,再加上默认不会指定main-class,所以这样打出来的包不能执行。

maven-shade-plugin和maven-assembly-plugin打出来的包都是含项目依赖的所有jar包的,所以都是可以执行的。二者的具体区别在于,maven-assembly-plugin的一项bug

一个项目一般会依赖很多jar包,而这些被依赖的jar包可能又会依赖其他的jar包,这样的话,项目本身可能会依赖不同版本的相同包(假设是spring包)。

在这种前提下,使用assembly打包的时候,只能将某一个版本的spring.schemas文件放入最终打出的jar包里,这样会有问题。

而使用shade进行打包的时候,它能够将所有spring jar包中的spring.schemas文件进行合并,所以最终生成的jar包里,相当于是会包含项目中所有出现过的spring版本。

基于这种问题,如果只是想打可执行包的话,推荐使用maven-shade-plugin就可以了

2022-5-17 16:22:46 但是好像要配置一下?这个看看参考文献3吧。

下面讲一下如何通过maven-shade-plugin插件来生成可执行文件:

maven-shade-plugin

使用

在pom.xml文件中加入下列代码:

记得把mainClass节点里的路径换成你项目的入口类就可以。

<project>
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-shade-plugin</artifactId>
				<version>3.0.0</version>
				<configuration>
					<createDependencyReducedPom>false</createDependencyReducedPom>
				</configuration>
				<executions>
					<execution>
						<phase>package</phase>
						<goals>
							<goal>shade</goal>
						</goals>
						<configuration>
							<transformers>
								<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
									<mainClass>org.wlh.helloworld.Hello</mainClass>
								</transformer>
							</transformers>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>

基于shade插件打包完毕后,target目录下会生成两个jar包,一个是origin-xxx.jar,一个是xxx.jar。其中origin-xxx.jar中只包含了工程自己的class文件,而xxx.jar包含了项目本身的class + 所依赖的jar包。用第二个就可以。

而且也可以看到,xxx.jar中包含了Main-Class一行。

filter与artifactSet - 过滤jar包

利用filter可以在打包的时候排除掉jar包中的部分内容。

以 groupId:artifactId 为标识,在 filter 内部可以使用<include>/<exclude>更细致地控制,既可以移除代码文件,也可以移除配置文件。

<!-- 按package过滤junit包 -->
<configuration>
    <filters>
        <filter>
        	<artifact>junit:junit</artifact>
        	<includes>
        		<include>junit/framework/**</include>
        		<include>org/junit/**</include>
        	</includes>
        	<excludes>
        		<exclude>org/junit/experimental/**</exclude>
        		<exclude>org/junit/runners/**</exclude>
        	</excludes>
        </filter>
    </filters>
</configuration>

如果想将整个 jar 包都过滤掉,可以使用<artifactSet>,也是指定 groupId:artifactId 的标识。

<configuration>
	<artifactSet>
		<excludes>
			<exclude>classworlds:classworlds</exclude>
			<exclude>junit:junit</exclude>
			<exclude>jmock:*</exclude>
			<exclude>*:xml-apis</exclude>
			<exclude>org.apache.maven:lib:tests</exclude>
			<exclude>log4j:log4j:jar:</exclude>
		</excludes>
	</artifactSet>
</configuration>

另外配置<minimizeJar>将项目中没有使用的依赖自动移除

<configuration>
    <minimizeJar>true</minimizeJar>
</configuration>

Transformer

shade插件提供了丰富的Transformer工具类,这里介绍一些常用的Transformer。更多的 Transformer 见http://maven.apache.org/plugins/maven-shade-plugin/examples/resource-transformers.html

ManifestResourceTransformer

作用是往 MANIFEST 文件中写入 Main-Class ,这是可执行包的必要条件。

<configuration>
	<transformers>
		<transformer 
			implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
			<mainClass>com.lcifn.Application</mainClass>
		</transformer>
	</transformers>
</configuration>

AppendingTransformer

用来处理多个jar包中存在相同的配置文件的合并,尤其是spring。

<configuration>
	<transformers>
		<transformer
			implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
			<resource>META-INF/spring.handlers</resource>
		</transformer>
		<transformer
			implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
			<resource>META-INF/spring.schemas</resource>
		</transformer>
	</transformers>
</configuration>

ServicesResourceTransformer

JDK 的服务发现机制是基于 META-INF/services/目录的,如果同一接口存在多个实现需要合并 ,则可以使用此 Transformer。

<configuration>
  <transformers>
    <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
  </transformers>
</configuration>

参考文献

  1. 通过IDEA 快速 生成 可执行 jar包(超级简单) 没成功,但是过程有点意思。
  2. Maven3种打包方式之一maven-shade-plugin的使用
  3. [1119使用maven插件maven-shade-plugin对可执行java工程及其全部依赖jar进行打包

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/662860.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Selenium+Python+Pycharm自动化环境搭建具体步骤

一、python下载&#xff1a;建议选择3.4以上的版本 官网下载地址&#xff1a; Download Python | Python.org 下载后自行进行安装&#xff0c;安装python需要配置环境变量&#xff0c;安装时可勾选“add python to path”的选项。勾选之后会自动将python添加到系统环境变量Pa…

学习AD的一些记录

1.首先创建一个工程&#xff0c;然后在工程里面创建原理图&#xff0c;PCB&#xff0c;原理图库和PCB库。 并保存。 2.将外部的原理图库&#xff0c;pcb库复制到自己创建的原理图库和pcb库。放到这两个里面。 复制&#xff0c;并粘贴到自己创建的原理图库中。PCB库同理 3.然后…

vue2和vue3的渲染过程简述版

文章目录 vue2渲染过程vue3渲染过程优化和扩充 vue2和vue3对比 vue2渲染过程 在Vue 2的渲染过程中&#xff0c;包括以下几个关键步骤&#xff1a; 解析模板&#xff1a;Vue 2使用基于HTML语法的模板&#xff0c;首先会将模板解析成抽象语法树&#xff08;AST&#xff09;&…

高频前端面试题汇总之代码输出结果篇

前言&#xff1a; 代码输出结果是面试中常考的题目&#xff0c;一段代码中可能涉及到很多的知识点&#xff0c;这就考察到了应聘者的基础能力。在前端面试中&#xff0c;常考的代码输出问题主要涉及到以下知识点&#xff1a;异步编程、事件循环、this指向、作用域、变量提升、…

SolidWorks软件三维建模教程——莫比乌斯环建模案例

SolidWorks是达索系统&#xff08;Dassault Systemes &#xff09;下的子公司&#xff0c;专门负责研发与销售机械设计软件的视窗产品。SOLIDWORKS软件三维建模功能强大&#xff0c;为制造型企业提供SOLIDWORKS一体化解决方案和服务。 今天微辰三维就以莫比乌斯环的三维建模案例…

智慧灯杆云盒是什么?如何挑选智慧云盒?

慧路灯杆云盒&#xff0c;是一种专门用于智慧路灯杆远距通信、远程控制、数据分析、边缘计算的智能终端设备&#xff0c;智慧路灯杆云盒作为联通智慧路灯杆与物联网云平台的桥梁&#xff0c;可以有效提高智慧路灯杆的管理效率、降低维护成本、实现多样化设备联动协同功能&#…

【C++】的多态

目录 1. 多态的概念2. 多态的定义及实现虚函数虚函数的重写虚函数重写的两个例外&#xff1a;C11 override 和 final重载、覆盖(重写)、隐藏(重定义)的对比 3. 抽象类接口继承和实现继承 4. 多态的原理虚函数表 5. 单继承和多继承关系中的虚函数表单继承中的虚函数表多继承中的…

qemu虚拟机配置网络

一、实现qemu虚机&宿主机网络互通 qemu虚机的网络介绍及原理可参考前人文章&#xff1a;Linux 内核调试 七&#xff1a;qemu网络配置_lqonlylove的博客-CSDN博客 这里只简单梳理下操作流程&#xff0c;以便快速实现网络互通。 1.宿主机创建 tap0 [rootlocalhost ~]# if…

一文入门Mongodb

目录 概述核心概念下载与安装版本问题环境配置cmd运行 数据库与集合命令数据库命令集合命令文档命令 mongoosemongoose的使用插入字段类型mongoose字段验证与强制性设置删除文档更新文档读取数据条件控制 后记 概述 Mongodb是一个分布式文件存储的数据库。 官网&#xff1a;M…

使用 AI 修复去除不需要的对象

Inpainting 是一种运用了稳定扩散&#xff08;Stable Diffusion&#xff09;技术来部分重绘图像的方法。简单来讲需准备一张图像&#xff0c;绘制一块遮罩以标明想要重绘的图像区域&#xff0c;同时提供一些重绘提示。随后稳定扩散就能根据这些提示&#xff0c;重新绘制遮罩区域…

layui(5)——内置模块分页模块

模块加载名称&#xff1a;laypage laypage 的使用非常简单&#xff0c;指向一个用于存放分页的容器&#xff0c;通过服务端得到一些初始值&#xff0c;即可完成分页渲染&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset&quo…

聊一聊mysql的MVCC

技术主题 在mysql世纪使用中&#xff0c;经常涉及到MVCC的概念&#xff08;Multi-Vsersion Concurrency Control&#xff09;&#xff0c;即多版本并发控制&#xff0c;一种并发控制方法&#xff0c;根本目的是主为了提升数据库的并发性能。 mvcc为什么产生 数据库最原生的锁…

设计模式大全

使用设计模式的目的&#xff1a; 程序猿在编码的过程中面临着来自耦合性、内聚性、可维护性、可扩展性、重用性、灵活性等多方面的挑战。设计模式是为了让程序具有更好的&#xff1a; 1&#xff09;重用性&#xff0c;即相同功能的代码编写一次即可&#xff0c;不用重复编写 …

3-JVM 运行时数据区

目录 1.堆&#xff08;线程共享&#xff09;&#xff08;最大的一块区域&#xff09; 2.Java虚拟机栈&#xff08;线程私有&#xff09; 3.本地方法栈&#xff08;线程私有&#xff09; 4.程序计数器&#xff08;线程私有&#xff09; 5.方法区&#xff08;线程共享&#…

Oracle JSON_ARRAYAGG()函数的默认排序问题

引入&#xff1a; 在实际操作中&#xff0c;俺写了这样一个Funtcion&#xff1a; FUNCTION fun_get_xxx(v_param_one VARCHAR2) RETURN CLOB ASv_OUTPUT CLOB;BEGINWITH temp_table AS (SELECT * FROM (( SELECT one.action_id,two.log_timeFROM table_one oneLEFT JOIN table…

Python程序设计基础:字符串

文章目录 一、字符串二、字符串的索引与切片三、字符串处理与操作四、format()格式化方法五、字符串与数值的转换 一、字符串 在Python中&#xff0c;使用单引号或双引号括起来的内容&#xff0c;称为字符串类型数据&#xff08;str&#xff09;&#xff0c;可以使用以下4种方…

Linux主分区,扩展分区,逻辑分区的联系和区别

基本概念 硬盘分区有三种&#xff0c; 主磁盘分区、扩展 磁盘分区、 逻辑分区。 一个 硬盘 主分区至少有1个&#xff0c;最多4个&#xff0c;扩展分区可以没有&#xff0c;最多1个。且 主分区扩展分区总共不能超过4个。 逻辑分区可以有若干个。 在windows下激活的 主分区是 …

树形结构-二叉树结构

树形结构 树形结构简介 树结构是一种非线性储存结构&#xff0c;存储的是具有“一对多”关系的数据元素的集合 树的相关术语 结点&#xff08;Node&#xff09; 使用树结构存储的每一个数据元素被成为“结点” 结点的度&#xff08;Degree of Node&#xff09; 某个结点所拥…

一次完整的Loadrunner基本流程操作

目录 一.生成脚本&#xff1a; 二.回放脚本&#xff1a; 三.创建场景&#xff1a; 四.生成报告&#xff1a; Loadrunner基本流程操作 准备条件&#xff1a; 一.安装loadrunner 二.破解loadrunner &#xff08;注&#xff1a;本次使用lr11版本可以兼容的IE浏览器版本为I…