2024-01-15

Maven - Zero to One [3.8.7]

notion image
Scenario 1: Let's say our project requires third-party dependencies such as Druid connection pooling, MYSQL database driver and Jackson JSON processing. Then we can write the information of the desired dependencies to the Maven project configuration file, Maven will automatically download and copy these dependencies to the project, no need to import jar packages and manage the jars yourself.
Scenario 2: The project is finished developing, we want to deploy to the server as a war, using the maven build command can be quickly packaged! Save a lot of time!
 

1. Maven installation and configuration

1.1 Maven environment configuration

  1. win + R → type sysdm.cpl
    1. notion image
  1. Configure the path
    1. notion image
  1. mvn -v to see if there is a maven version output in the console

1.2 Maven Feature Configuration

We need to modify the maven/conf/settings.xml configuration file, to modify some of the default configuration of maven, we mainly modify the configuration of three:: the location of the local cache (the location of the local cache)
  • rely on the local cache location (local repository location) → maven3.8.7\conf\settings.xml
  • maven download mirrors → domestic configuration Aliyun, overseas do not have to match
  • maven choose to compile the project's jdk version
 

2. Maven project GAVP

  1. GroupID format: com.{company/BU}. Business Line. [sub-line of business], up to 4 levels
    1. E.g.
      com.taobao.tddl
      com.alibaba.sourcing.multilang
  1. ArtifactID format: product line name - module name. Semantics are not duplicated or missing, check with the warehouse center first.
    1. E.g.
      tc-client/uic-api/tair-tool/bookstore
  1. Version version number format: major version number. Major version number. Revision number
      • Major version number: when a non-compliant API change is made, or when a new feature is added that changes direction.
      • minor version number: when backward compatible functionality is added (new classes, interfaces)
      • Revision number: bug fixes, enhancements that don't change method signatures, maintain API compatibility.
        • E.g. Initialization → 1.0.0 Bug fixes → 1.0.1 Feature adjustments → 1.1.1
      Packing definition rules.
      Instructs what type of file to package the project, idea recognizes the maven project type based on the packaging value!
      packaging attribute is jar (default), it means a normal java project, after packing, it is a file ending with .jar.
      packaging attribute is war, represents a Java web project, packaged as a .war file.
      packaging attribute is pom, which means that it will not be packaged and will be used as an inherited parent project.
      Maven Java project 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 是 POM的版本不是 maven的版本--> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.example</groupId> <artifactId>maven_test</artifactId> <version>1.0-SNAPSHOT</version> </parent> <!-- maven工程的坐标--> <groupId>com.artists.maven</groupId> <artifactId>maven_java</artifactId> <version>1.0-SNAPSHOT</version> <!-- maven工程的打包方式 --> <packaging>jar</packaging> <!-- dependencies--> <dependencies> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.9.2</version> <scope>test</scope> </dependency> </dependencies> <properties> <maven.compiler.source>17</maven.compiler.source> <maven.compiler.target>17</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project>
       

3. Maven project structure

|-- pom.xml # Maven 项目管理文件 |-- src |-- main # 项目主要代码 | |-- java # Java 源代码目录 | | -- com/example/myapp # 开发者代码主要目录 | | |-- controller # 存放 Controller 层代码的目录 | | |-- service # 存放 Service 层代码的目录 | | |-- dao # 存放 Dao 层的代码 | | |-- model # 存放数据模型的目录 | |-- resources # 资源目录, 存放配置文件,静态资源等 | | |-- log4j.properties # 日志配置文件 | | |-- spring-mybatis.xml # Spring Mybatis 配置文件 | | |-- static # 存放静态资源的目录 | | | |-- css # 存放 CSS 文件的兖 | | | |-- js # 存放 JavaScript 文件的目录 | | | |-- images # 存放图片资源的目录 | |-- webapp # 存放 WEB 相关配置和资源 | |-- WEB-INF # 存放 WEB 应用配置文件 | | |-- web.xml # Web 应用的部署描述文件 | | |-- classes # 存放编译后的 class 文件 | | |-- index.html # web 应用入口页面 |-- test # 项目测试代码 |-- java # 单元测试目录 |-- resources # 测试资源目录

4. Maven project build

4.1 Build Concepts and Processes

Project build refers to the process of converting source code, dependency libraries and resource files into an executable or deployable application, which includes compiling source code, linking dependency libraries, packaging and deployment.
Project building is an intuitively important part of the software development process, it can greatly improve the efficiency of software development, so that developers can focus more on the development and maintenance of the application, rather than caring about the details of the application construction.
At the same time, the project build can also bring together the code of multiple developers, and can automate the project build and deployment, greatly reducing the risk of project errors and improve development efficiency. Common build tools include Maven, Gradel, Ant and so on.
Clear → Compile → Test → Report → Package → Deploy
 

4.2 Command-based Project Build

The mvn command must be used in the pom.xml directory.
Command
Description
Tips
mvn compile
Compile the project, generate target file (only the core program can be compiled).
mvn test-compile
Compile the core program and test code
mvn package
Package the project, generating a jar or war file
1. Tests are run before the package, and there is no test program in the final package. 2. 2. If it is a war package error, most likely due to the war package packaging plug-ins and JDK version is not compatible. Here is an example of a JDK17 packaging plugin <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war- plugin</artifactId> <version>3.2.2</version> </plugin> </plugins> </plugins
mvn clean
To clean up the structure of a compiled or packaged project
mvn install
Packages the project and uploads it to the local maven repository
1. Different modules in a project have dependencies on each other, so you need to install the dependencies into your local repository. Maven's dependency lookup logic is to lookup the remote public repository only if the dependency does not exist in the local repository. 2. If mvn install fails, you can use mvn to install the dependency. 2. If mvn install fails, look carefully at the parent project of the dependent module to see if it is packaged.
mvn site
Generate site
mvn test
Execute the test source (execute the test for the current project)
1. Test methods must be named according to test[method name], if they are named randomly, e.g. aaa(), they will not be recognized as test methods when executing mvn test. mvn does not locate test methods based on the @Test annotation 2. test classes must start with or end in test, otherwise they will not be found, it does not matter if you recompile them or not. Class names are recommended to be named in the pattern [class name] Test.
mvn clean test
If you want to run mvn clean and then run mvn test, you can just use mvn clean test

4.3 Relationship between Build Plugins, Commands, and Lifecycle Commands

Example: mvn clean package
There are two main build lifecycles.
  • The clean cycle: It mainly deals with the compiled files of the project and includes the command: clean.
  • Default cycle: defines all the steps that need to be performed for a real build, it is the core part of the lifecycle Contains commands: compile → test → package → install → deploy
cycle → contains several commands → contains several plugins

4.4 Dependency scopes

You can set the scope of a jar package by setting the scope of the coordinates: compile environment, test environment, runtime environment.
Dependency scope
Description
compile
Default value of the scope element, since compilation. Maven dependencies with this scope are valid for all three classpaths, i.e., they will be introduced in all three classpaths. For example, log4j is required for compilation, testing, and runtime.
test
Test the dependency scope. Maven dependencies with this scope are only valid for the test classpath, e.g., Junit dependencies are only needed during the test phase.
provided
Dependency scopes have been provided. Using a Maven dependency from this scope is only valid for the compile classpath and the test classpath. For example, the servlet-api dependency is required for the compile and test phases, but in the runtime phase, Maven does not need to reintroduce the dependency because it is already provided by the external container.
runtime
Runtime dependency scope. Maven dependencies using this scope are only valid for the test classpath and runtime classpath. For example, the JDBC driver implementation dependency requires only the JDBC interface provided by the JDK at compile time, and only the driver that implements the JDBC interface is required for the test and runtime phases.
system
system dependency scope, the effect is consistent with the scope of the provided dependencies. It is used to add local dependencies from non-Maven repositories by specifying the path to the local dependency via the systemPath element in the dependency element. This is not recommended as it can lead to reduced portability of the project.
import
Import dependency scope, which can only be used in conjunction with the dependencyManagement element. Its function is to import and merge the configuration of the dependencyManagement in the target pom.xml file into the current pom.xml's dependencyManagement.
 

4.5 Solving Maven Project Dependency Download Failure Errors (Highlights)

When using Maven to build a project, dependency download errors may occur, mainly due to the following reasons.
  1. When downloading dependencies, there is a network failure or the repository server is down, resulting in a failure to connect to the Maven repository, and thus the dependencies cannot be downloaded.
  1. The version number of the dependency or the version number in the configuration file is wrong, or the dependency is not defined correctly, resulting in the dependency downloaded by Maven is not consistent with what is actually needed, and thus causing an error.
  1. The local Maven repository cache is polluted or corrupted, preventing Maven from properly utilizing existing dependencies.
 
Solution.
  1. Check network connectivity and Maven repository server status.
  1. Ensure that the version number of the dependency matches the version number of the project, and check that the dependency is correctly listed in the POM file.
  1. Make sure that the local Maven repository cache (the file ending with lastupdated) is clear, because as long as it exists, refreshing it will not re-download it. In the local repository, look down the folders one at a time according to the gav attribute, eventually delete the internal files, and refresh to re-download them!

4.6 Maven Project <Build> Build Configuration

Project build is the process of converting source code, dependencies and resource files into an executable or deployable application. This process involves compiling the source code, linking the dependencies, packaging and deploying the application.
By default, builds do not require additional configuration and are configured by default. Of course, it is possible to modify the behavior of the default build by customizing it in pom.xml.
Example.
  1. Specify the name of the build package, not the default name.
<!--自定义打包名称--> <build> <finalName>maven_web-1.0</finalName> </build>
  1. Specify the file format and excluded files to be included when building the package. If you add a java class to the java folder, it will be automatically packaged and compiled into the classes folder! If you add a java class to the java folder, it will be automatically compiled into the classes folder! By default, files placed according to the maven project structure will be compiled and packaged by default! In addition, we can use the resources tag to specify which static resources should be packaged in the root of the classes folder! Scenario: In mubatis, sometimes the mapping files for writing SQL statements and the mapper interface are written in a package under src./main/java, and the mapping files are not packaged.
    1. <build> <resources> <resource> <!--设置资源所在目录--> <directory>src/main/java</directory> <includes> <!--设置包含资源类型, **表示任意包, *表示任意以xml结尾的文件--> <include>**/*.xml</include> </includes> </resource> </resources> </build>
 
  1. Packaging plug-in version is too low, configure a higher version of the plug-in dependencies tag to introduce the development of the required jar package! We can build/plugins/plugin tag to introduce plug-ins commonly used plug-ins: modify the jdk version, tomcat plug-in, mybatis paging plug-in, mybatis reverse engineering plug-ins and so on!
    1. <plugins> <!--War包打包插件--> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <!--java编译插件, 配jdk的编译版本--> <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> <!--tomcat 插件--> <plugin> <groupId>org.apache.tomcat.maven</groupId> <artifactId>tomcat7-maven-plugin</artifactId> <version>2.2</version> <configuration> <port>8090</port> <path>/</path> <uriEncoding>UTF-8</uriEncoding> <server>tomcat7</server> </configuration> </plugin> </plugins>
Build configuration is specified in the pom.xml/build tags

5. Maven dependency passing and dependency conflicts

5.1 Maven Dependency Passing Features

Concepts
Join a Maven project A, project B depends on A, project C depends on B. Then we can say that C depends on A, that is, the dependency relationship is: C → B → A, then we execute the project C, will automatically download B, A are imported into the C project jar package file, which is since the pass-through.
This is pass-through.
  • Simplifies the dependency import process
  • Ensures that the dependency versions are correct
Principle of pass-through
On the premise that A depends on B and B depends on C, whether or not C can be passed on to A depends on the scope of the dependency and the configuration of the dependency that B uses to depend on C.
  • B depends on C with compile scope → passable
  • B depends on C using test or provided scope → can not be passed, so when you need such a jar package, you have to explicitly configure the dependencies in the place where they need to be matched.
  • When B depends on C, if you configure the following tags, then you can't pass it.
 
Termination of dependency passing
  • Dependency passing in non-compile scope
  • Use <optional> configuration to terminate the pass
  • Dependency conflicts (the dependency being passed already exists).

5.2 Maven Dependency Conflict Characterization

When direct or indirect references to the same jar package, then it, a project will appear the same repeated jar package, this is called a conflict! Dependencies out of the map will face duplicate dependencies, and terminate the dependency transfer!
notion image
maven automatically resolve dependency conflicts, according to their own principles, repeat dependency selection, but also provides a way to manually resolve conflicts, but not recommended!
 
How to resolve dependency conflicts (how to select duplicate dependencies).
  1. Automatic selection principle
      • Short-circuit prioritization (first principle)
        • A → B → C → D → E → X (version 0.0.1) A → F → X (version 0.0.2)
          then A depends on X (version 0.0.2).
      • If dependency paths are of the same length, then "first declaration takes precedence" (second principle).
        • A → E → X(version 0.0.1)
          A → F → X(version 0.0.2)
          Depending on which of E and F is configured first, A will depend on it.
          In <depencies></depencies>, the one declared first, with the same path, is preferred.
           
  1. Manual exclusion
    1. <dependencies> <dependency> <groupId>com.artists.maven</groupId> <artifactId>maven_B</artifactId> <version>1.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
 

6. Maven Project Inheritance and Aggregation Relationships

6.1 Maven Project Inheritance

Dependencies in the parent project are unconditionally inherited by the child project, so the following approach is generally used. Dependencies under <dependencyManagement> are not inherited directly by the child project, but rather the following approach is used to allow the child project to choose which dependencies to inherit.
<!--父工程--> <dependencyManagement> <dependencies> ... </dependencies> </dependencyManagement> <!--子工程, 不用写version--> <dependencies> <dependency> <groupId><groupId> <artifactId></artifactId> </dependency> </dependencies>
  1. Inheritance Concept Maven inheritance is the mechanism by which a project inherits configuration information from another project in a Maven project. Inheritance allows us to share the same configuration information across multiple projects, simplifying project management and maintenance.
  1. Inheritance serves the purpose of managing project dependencies in the same parent project.
    1. The context is.
      • Splitting a large project into modules.
      • Under a project, many modules are created.
      • Each module needs to be configured with its own dependencies.
      The requirement behind this is.
      • Maintaining dependency information in each module is prone to inconsistencies and is not easy to manage in a unified way.
      • If you use different packages from the same framework, they should be the same version, so the version of the framework used in the whole project needs to be standardized.
      • The combination of packages (or the combination of dependencies) needed to use the framework requires a long period of exploration and debugging to finally determine a usable combination. This laborious process should not be repeated in a new project. Maintaining a dependency set for the entire project in the parent project ensures that the entire project uses a standardized and accurate set of jar packages; it also saves time and effort by saving time from past experience.
      <parent> <groupId>com.artists.maven</groupId> <artifactId>maven_test</artifactId> <version>1.0-SNAPSHOT</version> </parent> <!--因为groupId 与 version 要与父工程保持一致, 所以这里可写可不写--> <artifactId>maven_A</artifactId>
       

6.2 Maven Project Aggregation

  1. Concept of aggregation
    1. Maven project aggregation refers to the organization of multiple projects into a parent project, in order to build and manage the mechanism together. Aggregation helps us to better manage a set of related subprojects while simplifying their build and deployment.
  1. The role of aggregation
      • Managing multiple subprojects: Aggregation allows you to organize multiple subprojects together for easy management and maintenance.
      • Build and release a set of related projects: Aggregation allows you to build and release multiple related projects in a single command, simplifying deployment and maintenance.
      • Optimize build order: Aggregation allows you to control the order of multiple projects to prevent build failures due to build dependency confusion.
      • Manage dependencies in one place: Aggregation allows you to manage public dependencies and plug-ins in the parent project, avoiding duplicate definitions.
      <!--父工程的操作, 子工程会同步进行. e.g. 打包父工程, 子工程也会打包--> <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"> <groupId>com.artists.maven</groupId> <artifactId>maven_test</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>maven_java</module> <!--注意这里不是模块名,而是模块的路径, 所以有可能出现../maven_java--> <module>maven_web</module> <module>maven_A</module> <module>maven_B</module> </modules> </project>

7. Nexus

7.1 Deploying jar packages to Nexus

Configure your maven project with the following configuration, then run mvn deploy
<distributionManagement> <snapshotRepository> <id>nexus-mine</id> -> 与settings.xml <mirror>下的配置一样 <name>Nexus Snapshot</name> -> 与settings.xml <mirror>下的配置一样 <url>http://localhost:8081/repositort/maven-snapshots</url> -> 与settings.xml <mirror>下的配置一样 </snapshotRepository> </distributionManagement>

7.2 Reference to someone else's deployed jar package

<repositories> <repository> <id>mine</id> -> 与settings.xml <mirror>下的配置一样 <name>Nexus Snapshot</name> -> 与settings.xml <mirror>下的配置一样 <url>http://localhost:8081/repositort/maven-snapshots</url> -> 与settings.xml <mirror>下的配置一样 <snapshots> <enabled>true</enabled> -> 能否使用快照版本的依赖 </snapshots> <releases> <enabled>true</enabled> -> 能否使用正式版本的依赖 </releases> </repository> </repositories>