飘逸的野马 · 约基奇:想成为丹佛的邓肯 愿终生效力于掘金 ...· 13 小时前 · |
乐观的冰棍 · 2023年宁波义务段学校招生入学政策公布 ...· 2 月前 · |
聪明伶俐的小刀 · B端页面——详细表格设计流程 | 人人都是产品经理· 3 月前 · |
果断的汽水 · 2023年国际刑事法院模拟审判竞赛(英文)队 ...· 10 月前 · |
爱搭讪的哑铃 · 【快穿】绝美白莲在线教学漫画_【快穿】绝美白 ...· 1 年前 · |
Maven是Java中较为重要的项目构建工具,它跟npm工具一样都是依赖的管理工具。同时,它还包含了打包,编译,测试,发布等功能的像webpack的工具。
Maven是相比Java的Ant更为好用的工作,主要改进是:
Maven的打包流程是固定的,不能被改变的,我们要配置的是不同的打包阶段(phrase),应该调用什么样的插件。而不是去配置哪个命令完成之后执行哪个命令,这大大简化了配置的难度。在之前的Ant工具,Makefile工具,npm工具中我们都是定义命令的执行流程,而不是定义阶段的需要插件是什么。
最后是,Maven的其他功能包括:
官网 下载二进制包,解压后加入以上的环境变量
mvn -v
成功后运行以上命令能看到结果,我的是3.6.3版本
<settings>
<mirrors>
<mirror>
<id>aliyun</id>
<name>aliyun</name>
<mirrorOf>central</mirrorOf>
<!-- 国内推荐阿里云的Maven镜像 -->
<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
</mirror>
</mirrors>
</settings>
在主目录的.m2文件夹下创建一个settings.xml配置文件,配置如上来切换国内的maven镜像
这样会在全交互提示的情况下创建项目结构
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=helloworld -Dpackage=com.mycompany.app -Dversion=1.0-SNAPSHOT
预先配置项目名称,仅交互提示项目结构就可以了
➜ maven git:(master) ✗ tree .
└── helloworld
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── mycompany
│ └── app
│ └── App.java
└── test
└── java
└── com
└── mycompany
└── app
└── AppTest.java
12 directories, 3 files
一般选择7: internal -> org.apache.maven.archetypes:maven-archetype-quickstart就可以了。项目结构如上
打包生成jar包
指定jar文件启动
<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>com.mycompany.app</groupId> <artifactId>mvc</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>mvc</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath/> </parent> <properties> <start-class>com.mycompany.app.App</start-class> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
新建项目以后,新增parent和dependency,以及plugin,最后记得加上properties的starter-class。由于有额外的plugin,所以方便了使用Spring-Boot的特殊命令。
package com.mycompany.app; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App public static void main( String[] args ) SpringApplication.run(App.class,args);
App.java的文件
package com.mycompany.app; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; @RestController @RequestMapping(path="/design",produces="application/json") public class HomeController{ @GetMapping("/recent") public String home(){ return "123";
HomeController.java的文件
server.port=8081
src/resources/applications.properties的文件,描述了项目属性
打包后,用JRE启动,很方便
4.1 脚手架
创建一个maven项目,脚手架是maven-archetype-quickstart的1.4版本,而且,项目的groupId是com.myapp,artifactId是basic。groupId是用来区别不同项目的全名,artifactId是项目名称。
├── pom.xml └── src ├── main │ └── java │ └── com │ └── myapp │ └── App.java └── test └── java └── com └── myapp └── AppTest.java 9 directories, 3 files这是生成的目录结构,可以看到groupId
4.2 打包
进行打包,编译和单元测试都会进行,会自动生成target目录
4.3 清理
清空项目的生成文件,删除target目录
4.4 文档
在target/site目录中的生成文档网站
打开index.html就能打开网站了
4.5 安装
安装当前包到本地local仓库去
显示是安装到用户目录的~/.m2/repository目录上了
4.6 配置说明
<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>com.myapp</groupId> <artifactId>app</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>app</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
modelVersion就是Maven配置文件的版本,dependencies就是依赖的描述,其他都没啥好说的。
资源filter就是在编译时对资源文件替换属性(properties)的过程
5.1 内置文件属性
资源filter,就是在编译时,对资源进行属性值替换的操作
创建项目,注意这次有填入DarchetypeGroupId,-B参数是免交互方式提示的
├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── mycompany │ │ └── source │ │ └── App.java │ └── resources │ └── application.properties └── test └── java └── com └── mycompany └── source └── AppTest.java 12 directories, 4 files
建立application.properties文件
资源文件的内容
package com.mycompany.source; import java.io.*; * Hello world! public class App public static void main( String[] args ) try{ new App().run(); }catch(Exception e){ e.printStackTrace(); public void run()throws Exception{ InputStream is = getClass().getResourceAsStream( "/application.properties" ); byte b[]=new byte[1024]; is.read(b); is.close(); System.out.println("data is ["+ new String(b)+"]");
App.java文件的内容
<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>com.mycompany.source</groupId> <artifactId>my-source</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>my-source</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <my.filter.value>hello</my.filter.value> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
pom.xml的文件的内容,主要是加入了build的resources的配置,指定哪些资源文件执行属性filter的操作。
➜ my-source git:(master) ✗ java -cp target/my-source-1.0.jar com.mycompany.source.App data is [application.name=my-source application.version=1.0 message=hello] ➜ my-source git:(master) ✗
这是输出描述,即使我们没有定义任何的属性,Maven也会有自己预定义的属性,就是project开头的属性了。另外一方面,我们可以在pom.xml的properties标签中加入自己自定义的属性,这就是message输出为hello的原因了。
5.2 外置命令行属性
├── pom.xml └── src ├── main │ ├── java │ │ └── com │ │ └── mycompany │ │ └── source │ │ └── App.java │ └── resources │ └── application.properties └── test └── java └── com └── mycompany └── source └── AppTest.java 12 directories, 4 files
目录结构,和刚才的一样
application.properties的内容
<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>com.mycompany.source</groupId> <artifactId>my-source3</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>my-source3</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
pom.xml和刚才的也是一样的
打包的时候,使用-D参数传入属性值
➜ my-source3 git:(master) ✗ java -cp target/my-source3-1.0-SNAPSHOT.jar com.mycompany.source.App data is [myname=Hello Cat] ➜ my-source3 git:(master) ✗
这是输出结果,可以看到资源文件的内容,在编译时,根据命令行的输入参数改变了
目录结构,加入了filter.properties文件
application.properties的资源文件内容
filter.properties的内容,这是外置的属性文件描述
<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>com.mycompany.source</groupId> <artifactId>my-source2</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>my-source2</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <my.filter.value>hello</my.filter.value> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <filters> <filter>filter.properties</filter> </filters> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build> </project>
这是pom文件,在build标签下,加入了filters的配置,指定了外置配置文件的来源。
➜ my-source2 git:(master) ✗ java -cp target/my-source2-1.0-SNAPSHOT.jar com.mycompany.source.App data is [message=hello message2=Cat]
这是输出内容
Maven 有以下三个标准的生命周期:
这是一个典型的build工作的生命周期
<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>com.mycompany.app</groupId> <artifactId>lifecycle</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>lifecycle</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.1</version> <executions> <execution> <id>id.compile</id> <phase>compile</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>compile phase</echo> </tasks> </configuration> </execution> <execution> <id>id.test</id> <phase>test</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>test phase</echo> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
pom.xml文件的配置。
在Maven中,使用插件是由两部分组成,插件和goal。所以,我们先在plugins中声明一个maven-antrun-plugin插件,然后在executions声明每个任务。每个任务包括要执行插件的哪个goal,以及插件执行时的配置configuration,id是可选的,phase也是可选的。
<plugin> <groupId>org.codehaus.modello</groupId> <artifactId>modello-maven-plugin</artifactId> <version>1.8.1</version> <executions> <execution> <configuration> <models> <model>src/main/mdo/maven.mdo</model> </models> <version>4.0.0</version> </configuration> <goals> <goal>java</goal> </goals> </execution> </executions> </plugin>
有些插件的goal默认就绑定到哪些phase上面了,所以就不需要再配置phase了。当有多个execution任务的时候,才需要去配置id标签
输出以上,可以看到不同编译阶段,会触发插件的输出
不同的生命周期下,Maven已经有默认的插件的绑定,这里就不啰嗦了,具体看 这里
代码在 这里
├── parent │ └── pom.xml └── subModule ├── pom.xml └── src ├── main │ └── java │ └── com │ └── mycompany │ └── app │ └── App.java └── test └── java └── com └── mycompany └── app └── AppTest.java 13 directories, 4 files目录结构如上,我们在同一个目录中建立了两个模块,parent模块与subModule模块。
<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>com.mycompany.app</groupId>
<artifactId>multi1</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>multi1</name>
<url>http://maven.apache.org</url>
<properties>
<subModuleVersion>1.0.0</subModuleVersion>
</properties>
</project>
这是parent/pom.xml的配置,注意声明了subModuleVersion的属性,以及packaging的值为pom。
<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> <parent> <groupId>com.mycompany.app</groupId> <artifactId>multi1</artifactId> <version>1.0</version> <relativePath>../parent/pom.xml</relativePath> </parent> <artifactId>subModule</artifactId> <version>${subModuleVersion}</version> <packaging>jar</packaging> <name>subModule</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
这是subModule/pom.xml的配置,注意,声明了parent配置,并用relativePath指向到同级的parent目录。在这里,subModule无需再声明groupId,version也可以直接用父级的属性subModuleVersion。这是模块继承带来的意义,子模块会继承父模块的groupId,以及父模块的properties。另外,在parent标签中,依然需要指定版本号version,而relativePath默认值为../pom.xml,如果默认值不对的话,需要显式指定。
在subModule的目录中,执行mvn package,发现可以执行运行,生成的版本号的确也是父模块定义的版本号
在parent的目录中,执行mvn package。什么工作都没有做,这是一个正常的现象。
模块聚合的目的是,将多个互相依赖的模块进行统一的编译打包等操作
├── parent │ └── pom.xml ├── subModule │ ├── pom.xml │ └── src │ ├── main │ │ └── java │ │ └── com │ │ └── mycompany │ │ └── app │ │ ├── App.java │ │ └── Service.java │ └── test │ └── java │ └── com │ └── mycompany │ └── app │ └── AppTest.java └── subModule2 ├── pom.xml └── src ├── main │ └── java │ └── com │ └── mycompany │ └── app2 │ └── App.java └── test └── java └── com └── mycompany └── app └── AppTest.java 25 directories, 8 files这是多模块的目录结构,有一个主模块,以及两个子模块。
<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>com.mycompany.app</groupId> <artifactId>parent</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <name>parent</name> <url>http://maven.apache.org</url> <modules> <module>../subModule</module> <module>../subModule2</module> </modules> </project>
这是parent/pom.xml,模块聚合的话,需要设置modules标签,并且以相对路径的方式指向子模块的位置
<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>com.mycompany.app</groupId> <artifactId>subModule</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>subModule</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
这是subModule/pom.xml的配置,普通的配置,没啥特别的,注意没有parent标签配置
package com.mycompany.app; public class Service public String go(){ return "Hello SubModule Service Go!";
这是subModule下的Service.java文件,一个模块对外的实现
<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>com.mycompany.app2</groupId> <artifactId>subModule2</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>subModule2</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.mycompany.app</groupId> <artifactId>subModule</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies> </project>
这是subModule2/pom.xml的配置,注意没有parent的配置。但是加入了一个dependency,指向subModule的模块。
package com.mycompany.app2; import com.mycompany.app.Service; * Hello world! public class App public static void main( String[] args ) Service service = new Service(); System.out.println(service.go());
这是subModule2的入口方法,注意应用了subModule模块的Service类。
这个时候,如果我们在subModule2中进行打包操作,会提示失败。因为没有找到subModule模块,这点和模块继承是不同的。
我们需要在parent模块,执行mvn package操作,才是正常的
java -cp ../subModule2/target/subModule2-1.0-SNAPSHOT.jar:../subModule/target/subModule-1.0-SNAPSHOT.jar com.mycompany.app2.App
在parent目录下,执行以上命令就能启动subModule2模块了
从实验中我们可以看出,Maven在模块依赖的时候,可以绕过本地仓库,远程仓库,直接在当前模块modules中寻找对应的依赖实现,相当方便。相比之下,npm的依赖查找相当僵硬地一定要放在node_modules目录,为了解决开发时的多模块查找的问题时,引入了麻烦的npm link命令。
7.3 组合使用
模块继承就是子模块中进行parent标签的配置,目的是为了继承父模块的配置。而模块聚合就是父模块中进行modules标签的配置,目的是为了同时编译打包和识别多个模块。两者并不冲突,我们也经常混合在一起经常使用。
├── parent │ └── pom.xml ├── subModule │ ├── pom.xml │ └── src │ ├── main │ │ └── java │ │ └── com │ │ └── mycompany │ │ └── app │ │ ├── App.java │ │ └── Service.java │ └── test │ └── java │ └── com │ └── mycompany │ └── app │ └── AppTest.java └── subModule2 ├── pom.xml └── src ├── main │ └── java │ └── com │ └── mycompany │ └── app2 │ └── App.java └── test └── java └── com └── mycompany └── app └── AppTest.java 25 directories, 8 files跟刚才一样的目录和代码,仅仅是配置文件不同
<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>com.mycompany.app</groupId> <artifactId>parent</artifactId> <version>1.0</version> <packaging>pom</packaging> <name>parent</name> <url>http://maven.apache.org</url> <properties> <subModuleVersion>1.2.0</subModuleVersion> <subModuleVersion2>1.3.0</subModuleVersion2> </properties> <modules> <module>../subModule</module> <module>../subModule2</module> </modules> </project>
parent/pom.xml文件,加入了properties
<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> <parent> <groupId>com.mycompany.app</groupId> <artifactId>parent</artifactId> <version>1.0</version> <relativePath>../parent/pom.xml</relativePath> </parent> <groupId>com.mycompany.app</groupId> <artifactId>subModule</artifactId> <version>${subModuleVersion}</version> <packaging>jar</packaging> <name>subModule</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
subModule/pom.xml文件,加入了parent,并且version使用了属性引用
<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> <parent> <groupId>com.mycompany.app</groupId> <artifactId>parent</artifactId> <version>1.0</version> <relativePath>../parent/pom.xml</relativePath> </parent> <groupId>com.mycompany.app2</groupId> <artifactId>subModule2</artifactId> <version>${subModuleVersion2}</version> <packaging>jar</packaging> <name>subModule2</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.mycompany.app</groupId> <artifactId>subModule</artifactId> <version>${subModuleVersion}</version> </dependency> </dependencies> </project>
subModule2/pom.xml的配置文件,加入了parent的配置,以及version与dependence的version都是用属性引用。
在subModule2的目录下输入命令,依然出错,可见parent指令依然只是继承属性,不会影响依赖查找
在parent的目录下输入命令,和之前一样正常运行
7.4 FAQ
7.4.1 指定模块打包
默认的mvn package会打包所有模块,我们可以指定-pl来指定只打包特定的模块,但是要注意的是,需要加上-am参数,表示将依赖的模块也一起编译。
7.4.2 指定模块执行Maven指令
我们只想执行app模块的flyway:clean指令,但是运行就会报错。因为app模块,依赖于common模块,而common模块没有在-pl列表中,所以app模块在执行flyway:clean的时候就会失败(需要编译common模块)。
这一次,我们将app与common模块一起加入-pl后执行,发现还是报错。因为common模块是公用模块,是没有flyway-maven-plugin的。
最终,我们使用其他方法来迂回实现。在app模块(非顶级模块)直接执行maven指令的时候,依赖是只会在local repository或者remote repository中寻找,不会在当前项目的多模块中寻找的。因此,我们需要将当前项目所有模块都提前install到local repository,就能实现单独模块的maven指令执行了。
相关资料:
Multi Module Maven Project and Running Flyway before build start 8 条件配置
8.1 条件配置与激活
代码在这里
<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>com.mycompany.app</groupId> <artifactId>profile</artifactId> <packaging>jar</packaging> <name>profile</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <profiles> <profile> <id>profile_a</id> <activation> <!--默认触发--> <activeByDefault>true</activeByDefault> </activation> <properties> <my_version>1.0</my_version> </properties> </profile> <profile> <id>profile_b</id> <!--命令行触发,mvn package -P profile_b --> <properties> <my_version>1.1</my_version> </properties> </profile> <profile> <id>profile_c</id> <!--指定属性触发,mvn package -Ddebug=123 --> <activation> <property> <name>debug</name> <value>123</value> </property> </activation> <properties> <my_version>1.2</my_version> </properties> </profile> <profile> <id>profile_d</id> <!--jdk版本触发,mvn package //jdk版本为1.8--> <activation> <jdk>1.7</jdk> </activation> <properties> <my_version>1.3</my_version> </properties> </profile> <profile> <id>profile_e</id> <!--os与cpu架构触发,mvn package //x86的cpu--> <activation> <arch>x86</arch> </activation> <properties> <my_version>1.4</my_version> </properties> </profile> </profiles> <version>${my_version}</version> </project>
在profiles中声明条件配置,然后可以通过以下方式来激活对应的配置:
命令行指定哪个配置文件,-P profile-1,profile-2, Profile下的activation触发条件,包括有activeByDefault,property,jdk,os等等。 <project> <repositories> <repository> <id>global-repo</id> </repository> </repositories> <profiles> <profile> <id>profile-1</id> <activation> <activeByDefault>true</activeByDefault> </activation> <repositories> <repository> <id>profile-1-repo</id> </repository> </repositories> </profile> <profile> <id>profile-2</id> <activation> <activeByDefault>true</activeByDefault> </activation> <repositories> <repository> <id>profile-2-repo</id> </repository> </repositories> </profile> </profiles> </project>
注意,条件配置是允许同时触发多个配置的,当多个配置文件的配置同时激活的时候,配置就会合并在一起。例如,多个激活的配置文件都有repository配置的时候,最终就有多个repository的配置,那么它们各自的优先级为:
Profile放在更前面的,优先级更高。 没有Profile的外层配置,优先级最低。 8.2 多级配置文件的条件配置
Maven有多级的配置文件,包括有
每个项目,在pom.xml中定义 每个用户,在%USER_HOME%/.m2/settings.xml中定义 全局,在${maven.home}/conf/settings.xml中定义 在额外文件的定义的配置文件(settings.xml或者profiles.xml),为了保证Maven配置文件的可移植性,这类的配置文件中只允许在Profile标签下面进行配置以下内容:
repositories pluginRepositories properties 在pom.xml的配置文件中,我们允许在Profile标签下面进行配置以下的内容:
repositories pluginRepositories dependencies plugins properties, (not actually available in the main POM, but used behind the scenes) modules reports reporting dependencyManagement distributionManagement build元素下允许包含以下的内容 * defaultGoal * resources * testResources * directory * finalName * filters * pluginManagement * plugins
8.3 条件配置激活查看
查看哪些条件配置激活的
查看进行了Super BOM,多级配置文件合并以后,最终计算得到的pom配置结果
9 依赖机制
Java的依赖与npm的依赖不同的是,同一个包只能有一个版本号。所以,Maven在选定依赖版本的时候,需要深度遍历每个模块的依赖,然后最终选定一个依赖的包的版本作为整个项目的唯一版本。
9.1 依赖调解
├── B │ └── C │ └── D 2.0 └── E └── D 1.0
Maven使用最近路径优先的版本选择,例如,A项目通过依赖B,和依赖E,都最终依赖了D库,但是各自D库的版本都不同。那么,最终会选择D 1.0版本,因为A-E-D的路径最短。
当路径一致的时候,Maven选择依赖放在前面的版本。
├── B │ └── C │ └── D 2.0 ├── E │ └── D 1.0 └── D 2.0我们可以利用这个机制,在A项目顶部显式指定依赖D 2.0版本,来强行指定Maven最终必须使用D 2.0版本,而不是D 1.0版本。因为A-D的路径最短。
<project> <dependencies> <dependency> <groupId>group-c</groupId> <artifactId>artifact-b</artifactId> <version>1.0</version> <type>war</type> <scope>runtime</scope> </dependency> </dependencies> </project>
依赖有6种作用域,分别是:
<project>
<dependencies>
<!-- declare the dependency to be set as optional -->
<dependency>
<groupId>sample.ProjectA</groupId>
<artifactId>Project-A</artifactId>
<version>1.0</version>
<scope>compile</scope>
<optional>true</optional> <!-- value will be true or false only -->
</dependency>
</dependencies>
</project>
声明一个依赖为optional的方式,就是在optional标签设置为true
ProjectA声明ProjectB的依赖为optional的时候,对于ProjectA的编译和打包操作没有任何区别。但是当ProjectX声明ProjectA为依赖的时候,ProjectX仅仅会导入ProjectA依赖,而不会导入ProjectB依赖,因为ProjectA对Project的依赖声明为optional的。 可选依赖不会影响直接上级的依赖图计算,但是会影响祖父级及以上的依赖图计算
可选依赖的使用场景是这样的,当一个类似Hibernate的ORM框架,它能透明地支持MySql,PostgresSQL,Sql Server等等这些的驱动层。显然,在编译时,它需要逐一指定包含这些数据库的连接器依赖。但是,对于使用方来说,他可能仅仅是使用MySql的Hibernate,他并不希望因为Hibernate对各种各样的数据库支持,导致所有数据库的连接器依赖都包含进来项目,这样过分多余了。
因此Hibernate可以将这些驱动层依赖都标记为Optional,在它编译的时候,这些驱动层都包含过来。但是对于使用方来说,包含Hibernate依赖的时候,不会自动将Hibernate的那些标记为Optional的驱动层依赖也包含进来。使用方需要显式依赖Hibernate的同时,也要去显式依赖哪些驱动层依赖,以显式的方式避免默认的导入过多依赖。
<project> <dependencies> <dependency> <groupId>sample.ProjectA</groupId> <artifactId>Project-A</artifactId> <version>1.0</version> <scope>compile</scope> <exclusions> <exclusion> <!-- declare the exclusion here --> <groupId>sample.ProjectB</groupId> <artifactId>Project-B</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
声明exclusion的方法也简单,在一个依赖的exclusions指定groupId和artifactId就可以了,由使用方来显示剔除那些依赖。注意,不需要指定剔除依赖的版本号,因为Maven会从ProjectA对ProjectB的依赖分析中计算得到。
Optional是库开发者为库使用者隐式剔除哪些依赖,而Exclusion是库使用者指定哪些依赖需要显式剔除。Exclusion一般是使用方用来替换一部分依赖实现。例如,我不喜欢库开发者默认指定的Log4j,我更喜欢Slf4j,那么就需要用Exclusion来显式剔除,然后在依赖中加入显式Slf4j的依赖即可。
最后,注意点有:
与npm对比
我们在多模块一节中,探讨了可以用parent标签来继承父级的配置,例如是properties属性。在这里,我们探讨,parent标签可以指定子级的依赖版本号,从而让多个子级统一依赖版本。
<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>com.mycompany.app</groupId>
<artifactId>multi1</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<name>multi1</name>
<url>http://maven.apache.org</url>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
这是parent/pom.xml文件,通过dependencyManagement来指定需要子级的依赖需要用什么版本号
<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> <parent> <groupId>com.mycompany.app</groupId> <artifactId>multi1</artifactId> <version>1.0</version> <relativePath>../parent/pom.xml</relativePath> </parent> <artifactId>subModule</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>subModule</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <!--不需要指定版本号,因为parent的dependencyManagement标签中指定了版本号--> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> </dependencies> </project>
这是subModule/pom.xml文件,先用parent来继承父级配置,然后在dependency中指定什么依赖就可以了,版本号会自动从父级的dependencyManagement中查找获取。
但是,每个项目只有一个parent标签配置,当我们需要同时继承多个父级的依赖配置的时候怎么办?可以用import
<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>com.mycompany.app</groupId> <artifactId>multi1</artifactId> <version>1.0</version> <packaging>pom</packaging> <name>multi1</name> <url>http://maven.apache.org</url> <dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.2</version> </dependency> </dependencies> </dependencyManagement> <modules> <module>../subModule/pom.xml</module> </modules> </project>
这是parent/pom.xml文件,依然用了dependencyManagement来指定子级依赖的版本号,同时使用了modules。
<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>com.mycompany.app</groupId> <artifactId>subModule</artifactId> <version>1.0</version> <packaging>jar</packaging> <name>subModule</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>com.mycompany.app</groupId> <artifactId>multi1</artifactId> <version>1.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <scope>test</scope> </dependency> </dependencies> </project>
这是subModule/pom.xml文件,注意,这次没有再使用parent标签了。而是在dependencyManagement里面用import方式导入父级的项目。然后,我们又能愉快地直接在dependencies指定依赖就行,不需要版本号。
这种方法的优势在于可以同时import多个父项目,但是只继承依赖配置,不继承properties等配置。
可以查看依赖树结构
快照版本号的,每次刷新依赖都会重新从远程仓库拉取,以保证最新版本
普通版本号的,会优先从本地仓库拉取,本地仓库没有该依赖才向远程仓库拉取
Maven有三大远程仓库,包括有:
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
我们一般在pom.xml中添加远程仓库地址就可以了,不要在settings.xml添加,以免影响配置文件的可移植性。
打开用户所在目录的settings.xml文件
<mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> <!-- 中央仓库1 --> <mirror> <id>repo1</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>https://repo1.maven.org/maven2/</url> </mirror> <!-- 中央仓库2 --> <mirror> <id>repo2</id> <mirrorOf>central</mirrorOf> <name>Human Readable Name for this Mirror.</name> <url>https://repo2.maven.org/maven2/</url> </mirror>
加入阿里云公共仓库的镜像,注意阿里云只是对应central仓库的,所以mirrorOf的配置为central,不能填写为*。这样会镜像所有的仓库,导致jitpack这样的远程仓库无法正常拉取。
如果你遇到了这类错误,就只能打开代理服务器了
我们将演示如何将github仓库的发布到JitPack的远程仓库,主要步骤为:
先将代码,以Maven的格式上传到github,例如像这个 项目 ,从这个项目中可以看出,这是一个多模块的Maven项目,但是我们不想将整个项目到上传到JitPack,只想上传它的其中一个模块。
于是,我们这里用到node的一个gh-pages的小工具
"name" : "spring-boot-starter-id-generator" , "version" : "1.0.0" , "description" : "Java的ID生成器" , "main" : "index.js" , "scripts" : { "deploy" : "mvn clean && gh-pages -d spring-boot-starter-id-generator -b jitpack" , "test" : "echo \" Error: no test specified \" && exit 1" "repository" : { "type" : "git" , "url" : "git+https://github.com/fishedee/spring-boot-starter-id-generator.git" "author" : "" , "license" : "ISC" , "bugs" : { "url" : "https://github.com/fishedee/spring-boot-starter-id-generator/issues" "homepage" : "https://github.com/fishedee/spring-boot-starter-id-generator#readme" , "devDependencies" : { "gh-pages" : "^3.2.3"在package.json中设置deploy的scripts。这个脚本的意思是,每次先执行mvn clean,然后将spring-boot-starter-id-generator文件夹发布到jitpack分支上
这是我执行的结果
然后在Github首页的右侧,点击Release,再点击Draft a New Release
选择分支为jitpack,填写好版本号,以及发布描述就可以了
这里,我们发布了一个1.4版本的Release。发布Release的目的是让Jitpack知道从哪里拉数据去编译代码
然后选择,我们的仓库,选择Releases,以及我们的版本号1.4,最后选择Get It就可以了。它就会自动拉代码下来编译打包,成为可被远程仓库加载的模块。
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>com.github.fishedee</groupId>
<artifactId>spring-boot-starter-id-generator</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
最后,在项目的pom.xml文件中填写以上的配置,就在任意项目里面加载我们的这个模块了。为JitPack点个赞,真的简单又好用!
SPRING_PROFILES_ACTIVE=test mvn test
mvn test -Dspring.profiles.active=test
-D是java在命令行传递属性的方式,也是可以覆盖环境变量的配置一种方式。
mvn -B clean package -Dmaven.test.skip=true -Dautoconfig.skip
也可以用-D来设置系统配置,从而影响Maven的运行配置。系统配置可以看 这里
<profile>
<id>jdk-1.8</id>
<activation>
<activeByDefault>true</activeByDefault>
<jdk>1.8</jdk>
</activation>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
</profile>
加入默认的jdk
IDE读取的是自己打包的Maven包,但是它依然能读取我们的配置。
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd"> <localRepository/> <interactiveMode/> <usePluginRegistry/> <offline/> <pluginGroups/> <servers/> <mirrors> <mirror> <id>aliyunmaven</id> <mirrorOf>central</mirrorOf> <name>阿里云公共仓库</name> <url>https://maven.aliyun.com/repository/public</url> </mirror> </mirrors> <proxies/> <activeProfiles/> </settings>
在mac下,IDE的Maven工具会读取~/.m2/settings.xml的配置。以上配置写入了阿里云镜像的配置。
使用IntelliJ来导入Maven项目,选择Import Project
选择项目的pom.xml即可
启动的时候,要点击任意一个源文件以后,再点击菜单栏的Run运行。
当pom.xml更新了以后,要执行Maven的Reimport来刷新Maven仓库
参考资料有:
使用Idea创建插件项目,选择mojo脚手架即可
mvn archetype:create -DgroupId=* -DartifactId=* -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-mojo
或者使用mvn脚手架生成器,都是一样的
两种方式都可以,但是最重要的是要定义好artifactId,artifactId有一套固定的规范。例如artifactId为cc-maven-plugin,那么IDEA就会识别这个插件名为cc,注意这个规范不能改,否则maven和IDEA会识别不了这个插件。
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.fishedee</groupId>
<artifactId>cc-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<version>1.0-SNAPSHOT</version>
<name>myPlugin Maven Mojo</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.5</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<version>3.5.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.5.2</version>
</plugin>
</plugins>
</build>
</project>
更新pom文件,使用以上的依赖
package com.fishedee; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import java.io.File; import java.io.FileWriter; import java.io.IOException; @Mojo(name="go") public class MyMojo extends AbstractMojo @Parameter( property = "project", required = true, readonly = true private MavenProject mavenProject; @Parameter( property = "codegen.outputDir", defaultValue = "src/main/java" private String outputDir; @Parameter( property = "codegen.packageName", required = true private String packageName; public void execute() throws MojoExecutionException Log log = getLog(); log.info("baseDir "+mavenProject.getBasedir()); log.info("outputDir "+outputDir); log.info("packageName "+packageName);
一个简单的插件代码,使用@Mojo来定义插件的目标,使用@Parameter来获取配置参数
最重要的这一步是,将插件安装到本地的mvn库
13.2 使用插件
<?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>com.fishedee</groupId> <artifactId>plugin_sample</artifactId> <version>1.0-SNAPSHOT</version> <name>plugin_sample</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>com.fishedee</groupId> <artifactId>cc-maven-plugin</artifactId> <version>1.0-SNAPSHOT</version> <configuration> <outputDir>ac</outputDir> <packageName>com.kk</packageName> </configuration> <!--定义在执行compile的阶段执行插件的hello目标--> <executions> <execution> <goals> <goal>go</goal> </goals> <phase>compile</phase> </execution> </executions> </plugin> </plugins> </build> </project>
然后我们定义一个新的项目,在plugin中指定我们的插件。注意,我们定义了该插件是在compile阶段,顺带执行它的go目标。另外,注意configuration是如何传入配置的。
最后,我们在Maven视图中可以看到这个插件。或者直接对项目compile的时候也会触发这个插件。
这是执行结果,没啥好说的
20 FAQ
20.1 Process terminated
在IDEA中发现了这个错误,肯定是因为pom.xml有语法错误了
改掉语法错误,重新reload就可以了
20.2 IDEA多模块无法识别
在多模块项目导入到IDEA以后,有时候修改了其中一个模块的版本号以后,其他模块即使修改了版本号也无法正常编译。
解决办法是在,顶级的POM文件中,选择Reload Project就可以了
java.util.zip.ZipException:invalid distance distance too far back启动SpringBoot的时候报出以上错误,将~/.m2/repository里面的本地缓存包删掉,重新mvn clean 和mvn install就可以了。
20.4 IDEA无法识别多模块的类
导入一个多模块到IDEA以后,一个常见的问题是,编译可以成功,但是IDEA却总是提示这个类找不到,哪个类找不到。Module Settings里面对文件的配置都是正确的,问题在于缺少.iml文件,这听说是IDEA的bug。
mvn idea:module
在顶层pom.xml文件,输入以上命令即可补充缺失的.iml文件。
IDEA启动报错,无法找到org.springframework.bootidea开发 SpringBoot启动报错 程序包org.springframework.boot不存在,而使用maven 命令直接执行时无任何问题,不会报错。
![](/assets/img/2022-02-21-14-23-20.png
解决方法是将启动分发给Maven来做,但是这样做会有很多额外的问题,例如是停止Maven的时候,并不能关闭程序,导致网络端口被占用。
mvn idea:idea
也有人说通过以上命令来解决,看这里
20.6 Maven打包不进行单元测试
使用系统参数,使得package的过程跳过单元测试的步骤
Maven单元测试的时候指定SpringBoot和Maven参数使用-D的系统配置参数就可以做到了,不需要用环境变量
Maven指定测试时的资源文件夹<build> <testResources> <testResource> <directory>src/test/java/com/fishedee/erp</directory> </testResource> </testResources> </build>
在build里面指定testResources就可以了
20.9 Maven解决编译的乱码问题
<properties> <start-class>com.fishedee.erp.App</start-class> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.2.0</version> <configuration> <propertiesEncoding>UTF-8</propertiesEncoding> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> </pulugins> </build>
指定resources与compiler,以及默认的project.build.sourceEncoding
maven有固定的项目目录格式,比ant严谨多了。
参考资料: