🤹 Maven#
🧫 Background#
We basically divide our entire software lifecycle into: requirements (business proposes requirements, product writes documentation, technology sets schedules), development (requirement analysis, database design, coding, including unit testing and other self-testing), testing, packaging for external release, version updates (repeating the previous development and testing processes based on time and business requirement changes).
Project automation build
Maven (pom.xml). Developed based on Java, but with more comprehensive and powerful features, it automates support for almost all processes of the software lifecycle (compilation, testing, packaging and publishing, installation) by modifying related configuration files (pom.xml), and has a particularly powerful feature: JAR package dependency functionality.
👨💻 Commands#
- mvn clean
Cleans up previous compilation results to prepare for recompilation. - mvn compile
Compiles the Java source code into bytecode files. - mvn test
Tests key points in the project to ensure the correctness of key points during iterative development. - Report (): Records and displays test results in a standard format after each test.
- mvn package
Packages a project containing many files into a compressed file for installation or deployment. Java projects correspond tojar
packages, while Web projects correspond towar
packages. - mvn install
Installs the packaged result —jar
orwar
package — into the local repository in the Maven environment. - mvn deploy
Deploys the packaged result to a remote repository or deploys thewar
package to a server for operation.
mvn -version/-v
Displays version information.
It is recommended to perform mvn clean deletion before each operation; executing only mvn clean will delete the target directory (doubtful?).
A characteristic of Maven command execution is that it will complete the previous processes first. For example:
When executing mvn clean package, it actually first executes mvn clean compile, then test, and then package.
🥑 Core Concepts#
Maven's ability to achieve automated builds is inseparable from its internal principles. Here we start with Maven's nine core concepts to see how Maven achieves automated builds.
- POM
- Conventional directory structure
- Coordinates
- Dependency management
- Repository management
- Lifecycle
- Plugins and goals
- Inheritance
- Aggregation
Maven's core program only defines an abstract lifecycle, while specific operations are completed by Maven's plugins. However, Maven's plugins are not included in Maven's core program and need to be downloaded from the internet upon first use. The downloaded plugins will be saved to the local repository. The default location of the local repository is: ~/.m2/repository
.
🤖 POM#
Project Object Model: Encapsulates relevant information of a Java project as an object for easier operation and management.
<?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.example</groupId>
<artifactId>demo</artifactId>
<version>1.0-SNAPSHOT</version>
<name>demo</name>
<packaging>war</packaging>
<properties>
</properties>
<dependencies>
</dependencies>
<build>
<plugins>
</plugins>
</build>
</project>
⚓ Coordinates#
The core configuration of a Maven project.
G-A-V: Uses three vectors to uniquely locate a Maven project in the repository.
- groupId: Company or organization domain name in reverse order.
- artifactId: Module name, also the actual project name.
- version: The current version of the project.
<groupId>ink.onei</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
How to find a package in the repository using coordinates?
- Combine the three vectors into one string:
ink.onei+Hello+0.0.1-SNAPSHOT
- Use the combined string as a directory structure to search in the repository:
ink/onei/0.0.1-SNAPSHOT/Hello-0.0.1-SNAPSHOT.jar
Note: Our own Maven project must execute the install operation to enter the repository. The install command is: mvn install
.
🏗️ Structure#
A widely accepted viewpoint in the Java development field: Convention > Configuration > Coding (problems that can be solved with configuration should not be coded, and those that can be based on convention should not be configured).
Maven project directory
Project root directory Project name as root directory
├─src Source code directory
│ ├─main Main program directory
│ │ ├─java Main program's Java source file directory
│ │ │
│ │ └─resources Main program's resource file directory
│ │
│ └─test Test program directory
│ ├─java Test program directory
│ │
│ └─resources Test program's resource file directory
└─target Compilation structure
├─classes
│
└─generated-sources
└─annotations
🎨 Dependencies#
The most critical part of Maven; the main reason we use Maven is its dependency management functionality. To understand and master Maven's dependency management, we only need to solve the following questions:
What is the purpose of dependencies?#
When package A uses certain classes from package B, A becomes dependent on B, which is a conceptual description. So how do we introduce a package we need in a project as a dependency? The answer is very simple: use the dependency
tag to specify the coordinates of the dependent package.
<dependency>
<groupId>ink.onei</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
Dependency Scope#
Sometimes, in addition to the coordinates of the target package, there is also a scope setting in the dependency information, which is the dependency scope. The dependency scope has several optional values, commonly used ones are: compile
, test
, provided
, and of course, there are less commonly used ones like runtime
, system
...
- compile: Default scope, effective for compilation, testing, and running.
- provided: Effective during compilation and testing.
- runtime: Effective during testing and running.
- test: Effective only during testing.
- system: Effective during compilation and testing, associated with the local system, poor portability.
Summary of common dependency scope effectiveness
compile | test | provided | |
---|---|---|---|
Main program | ✔️ | ❌ | ✔️ |
Test program | ✔️ | ✔️ | ✔️ |
Participating in deployment | ✔️ | ❌ | ❌ |
Dependency Transitivity#
If A depends on B, and B depends on C, can A use C? That depends on whether B's dependency on C is compile; if it is, then it can be used; otherwise, it cannot.
Excluding Dependencies#
If we introduce a dependency A in the current project, and A depends on B, Maven will automatically include B as a dependency in the current project. However, in some cases, B may be an unstable version or have adverse effects on the current project. In this case, we can exclude B when introducing A.
<dependency>
<groupId>ink.onei</groupId>
<artifactId>Hello</artifactId>
<version>0.0.1-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
Unified Management of Dependency Versions#
Unified management of the versions of dependent packages is important; it is best to use the same version for a set of packages from the same framework. To facilitate upgrading the framework, the version information of the packages can be extracted uniformly.
- Unified declaration of version numbers:
<properties> <starfish.spring.version>4.1.1.RELEASE</starfish.spring.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties>
- Referencing the previously declared version number:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${starfish.spring.version}</version> <scope>compile</scope> </dependency>
Principles of Dependencies#
Resolving package conflicts:
- Shortest path takes precedence.
- If paths are the same, the first declared takes precedence.
📦 Repository Management#
- Local repository
Serves all Maven projects on the current local computer. - Remote repository
- Central repository: This is the default repository, hosted on the Internet, serving all Maven projects worldwide.
- Mirror repository: Configured through
settings.xml
insettings.mirrors.mirror
, hosted on various continents to share the load of the central repository, reducing pressure on it while responding to user requests faster, such as Alibaba Cloud mirror repository. - Private server: Hosted in the current local area network environment, serving all Maven projects within the current LAN.
Files in the repository:
- Maven plugins
- Modules of projects we develop ourselves
- Packages of third-party frameworks or tools
Regardless of the type of package, files in the repository are organized into a directory structure based on coordinates, allowing for a unified way to query or depend on them.
Other Repositories#
Global profile repository, configured through settings.xml
in settings.repositories.repository
.
Project repository, configured through pom.xml
in project.repositories.repository
.
Project profile repository, configured through pom.xml
in project.profiles.profile.repositories.repository
.
🌱 Lifecycle#
What is Maven's Lifecycle?#
Maven's lifecycle defines the execution order of various build stages. With this list, Maven can automate the execution of build commands.
Maven has three independent lifecycles:
- Clean Lifecycle: Performs some cleanup work before the actual build.
- Default Lifecycle: The core part of the build, including compilation, testing, packaging, installation, deployment, etc.
- Site Lifecycle: Generates project reports, sites, and publishes sites.
They are independent of each other; you can call clean to clean the working directory or call site to generate the site. Of course, you can also run mvn clean install site
to run all three lifecycles. Each lifecycle consists of a set of phases, and the commands we enter in the command line always correspond to a specific phase. For example, when running mvn clean
, this clean is a phase of the Clean lifecycle. There is a Clean lifecycle and a clean phase.
Clean Lifecycle#
The Clean lifecycle consists of three phases:
- pre-clean: Executes some work that needs to be completed before clean.
- clean: Removes all files generated from the last build.
- post-clean: Executes some work that needs to be completed immediately after clean.
Site Lifecycle#
- pre-site: Executes some work that needs to be completed before generating site documentation.
- site: Generates the project's site documentation.
- post-site: Executes some work that needs to be completed after generating site documentation and prepares for deployment.
- site-deploy: Deploys the generated site documentation to a specific server. The site phase and site-deploy phase are often used to generate and publish Maven sites, which is a powerful feature of Maven that managers particularly like, as documentation and statistics are generated automatically and look great.
Default Lifecycle#
The Default lifecycle is the most important one in Maven's lifecycle, where most of the work occurs (listing some important phases):
- validate: Validates the project to ensure it is correct and all necessary resources are available.
- compile: Compiles the project's source code.
- test: Tests the compiled source code using an appropriate unit testing framework. These tests do not require packaging and deployment.
- package: Packages the compiled code into a deployable format, such as jar, war, etc.
- integration-test: If necessary, processes the package and deploys it to an environment where integration tests can be performed.
- verify: Runs all checks to verify that the package is valid and meets quality standards.
- install: Installs the package into the local Maven repository, making it available for other projects as a dependency.
- deploy: In an integration or release environment, copies the final version of the package to a remote repository, allowing other developers or projects to share it.
Lifecycle and Automated Builds#
When running any phase, all preceding phases will be executed. For example, when we run mvn install, the code will be compiled, tested, and packaged. This is why Maven can automatically execute various stages of the build process. Additionally, Maven's plugin mechanism completely relies on Maven's lifecycle, so understanding the lifecycle is crucial.
🔌 Plugins and Goals#
- Maven's core only defines an abstract lifecycle; specific tasks are completed by plugins.
- Each plugin can implement multiple functions, with each function being a plugin goal.
- Maven's lifecycle is bound to plugin goals to complete specific build tasks. For example: compile is a goal of the
maven-compiler-plugin
; pre-clean is a goal of themaven-clean-plugin
.
🧬 Inheritance#
Why is an inheritance mechanism needed?
Since dependencies with non-compile
scopes cannot be passed in the "dependency chain," projects that need them must configure them separately.
- Creating a parent project: Creating a parent project is similar to creating a regular Java project, with the only note being that the packaging type must be set to
pom
. - Reference the parent project in the child project, using the relative path from the current directory to the parent project's
pom.xml
file.
<parent>
<groupId>com.starfish.maven</groupId>
<artifactId>Parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- Relative path to the parent project's pom.xml file based on the current file -->
<relativePath>../Parent/pom.xml</relativePath>
</parent>
At this point, if the child project's groupId
and version
are the same as the parent project, they can be removed.
-
Manage dependencies in the parent project: Wrap the
dependencies
tag in the Parent project with thedependencyManagement
tag.<dependencyManagement> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.9</version> <scope>test</scope> </dependency> </dependencies> </dependencyManagement>
-
In the child project, re-specify the required dependencies, removing the scope and version number.
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency>
💞 Aggregation#
Why use aggregation?
After splitting multiple projects into modules, it is necessary to manually install each one into the repository for dependencies to take effect. After modifying the source code, it is also necessary to manually perform clean operations one by one. However, after using aggregation, Maven projects can be installed and cleaned in batches.
How to configure aggregation? Use the modules/module tags in the overall aggregation project to specify the relative paths of the module projects.
<!-- Configure aggregation -->
<modules>
<!-- Specify the relative paths of each sub-project -->
<module>starfish-learn-grpc</module>
<module>starfish-learn-kafka</module>
<module>starfish-web-demo</module>
</modules>