introduce
Maven is a project management and build tool.
Do you still not know what Maven does? Project management and construction may sound like a sham,
For example, our Alpha e-commerce project is divided into order module, commodity module, business module, user module and marketing module. The order module needs the code of the user module, such as the interface to query user information. Is it necessary for the students of the user module to copy the code to the order module? So there will be a lot of question, is the first user modules students to write the code may have bugs, in need of repair, also the function of the module has been in the iteration, such as the original only in accordance with the userId query interface, increased the name query, mobile phone number query, finished the need to copy the code, the efficiency is very low, clever engineers think of a way, Centralized storage management, the code package + version of the way, this is where the centralized storage warehouse, everyone will be subject to warehouse, change to maintenance, by version number in order to prevent every small changes need to be modified version, also is to use offline and online test version of production environment, divided into the Snapshot package and Release package.
Overall, Maven makes it easy to manage project structure and dependencies.
warehouse
An important concept in Maven is Repository.
image-20220123161718538
Maven repositories are divided into local and remote repositories.
Remote warehouses also include private servers and central warehouses. Private server is well understood, many companies will build their own company in the LOCAL area network private warehouse address.
Here is a concept to distinguish, a lot of people will put private server and mirror (mirror) confused, mirror (mirror) is a copy of the central warehouse, the reason is very simple, central warehouse in foreign countries, you access the central warehouse speed is slow, mirror server in the domestic, equivalent to get a cache.
If you have downloaded Maven, you can see the maven repository configuration in the Maven configuration file. The following image shows the Maven configuration on Angela’s computer, usually in the user’s.m2 folder, setting.xml.
image-20220123161949266
You can see that repository is the local repository folder and setting.xml is the Maven configuration.
Let’s go to settings.xml and take a look.
<? The XML version = "1.0" encoding = "utf-8"? > < 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>/${user.home}/.m2/repository</localRepository> <interactiveMode>true</interactiveMode> <! -- Some Settings on the server side. Settings such as usernames and passwords should not be placed with the project's POM.xml. Authentication information such as passwords should exist in settings.xml. --> <servers> <server> <! This is the server ID (not the user login ID) that matches the ID of the Repository element in distributionManagement. --> <id>server001</id> <! My_login </username> <! --> <password>my_password</password> <! ${usr. Home}/.ssh/id_dsa</privateKey> <! - Private key password used for authentication. --> <passphrase>some_passphrase</passphrase> </server> </servers> <mirrors> <mirror> <! -- <id>aliyunmaven</id> <! -- Id of the server being mirrored. -- > < mirrorOf > central < / mirrorOf > < name > ali cloud public warehouse < / name > < url > https://maven.aliyun.com/repository/public < / url > < / mirror > </mirrors> <profiles> <profile> <! -- Unique identifier of profile --> <id>aliyun</id> <! -- Conditions for activating the current profile --> <activation> <! -- Default active status is false --> <activeByDefault>false</activeByDefault> <! -- Activation with JDK 1.8 --> < JDK >1.8</ JDK > </activation> <! Aliyun </id> <name> Aliyun </name> <url>http://maven.aliyun.com/nexus/content/groups/public/</url> <layout>default</layout> </repository> </repositories> </profile> </profiles> <activeProfiles> <activeProfile>aliyun</activeProfile> </activeProfiles> </settings>Copy the code
Let’s explain one by one:
-
LocalRepository: the localRepository address of the maven package we pulled from the remote repository;
-
InteractiveMode: Indicates whether Maven needs to interact with the user to get input. This option will prompt you to type groupId, artificialId, say yes or no to building this project. Set to true if Maven needs to interact with the user to get input, and false if maven needs to interact with the user to get input. The default is true.
-
Servers: Some warehouses, such as the company’s own, require username and password authentication for access. General repositories and distributionManagement will be defined in the project’s POM. XML, but the user name password is not suitable for the project’s POM, and some passwords are private to everyone. Therefore, maven settings.xml is more suitable for configuration;
-
“Mirrors” may be used to buffer some of the stress of a remote warehouse. As Angela mentioned earlier, there may be a lot of traffic in the central warehouse. Mirrors may be used to buffer some of the stress of a remote warehouse.
The mirror I configured above is the mirror of ali Cloud in China to the central warehouse. The value of mirrorOf is central, which represents the mirror of the central warehouse.
-
Profiles: The list of environment parameters to adjust build configurations.
The profile element in settings. XML is a clipped version of the profile element in POM.xml. It contains only five parts
-
Id: unique id of a profile
-
Activation: Conditions for activating the current profile
-
Repositories: If the current profile is active, the list of remote repositories defined in this profile will act as the remote repositories for the current POM, which Maven will use to build the project. Here you can see the remote warehouse of Ali Cloud.
-
PluginRepositories: List of remote repositories for plug-ins There are two types of repositories in Maven: repositories for artifacts and repositories for plugins. This is where you can specify the repository for the plugin.
-
Properties: After the profile takes effect, the valid attribute values are stored in the Maven context as key-value pairs. These values can be used anywhere in pom.xml using the tag ${X}.
For example, there are five ways to obtain the maven context properties property value.
<! -- 1.env.x: Prefixing a variable with "env." returns a shell environment variable. For example," env.path "refers to the $PATH environment variable (%PATH% on Windows). 2. Project. x: refers to the corresponding element value in the POM. For example: <project><version>1.0</version></project> get the version value from ${project.version}. 3. Settings. x: refers to the value of the corresponding element in settings. XML. For example: < Settings ><offline>false</offline></ Settings > Get the value of offline with ${settings.offline}. 4. Java System Properties: all can through the Java lang. System. The getProperties () to access attributes can access using the form in the POM, such as ${Java. Home}. 5.x: Set in the <properties/> element, or in an external file, as ${someVar}. --> <properties> <user.install>${user.home}/our-project</user.install> </properties>Copy the code
As shown in the figure above, you can get property values in the POM via ${user.install}.
This feature is often used in maven configuration for projects. Manage all package versions in the poM file of the parent Maven package and reference the version value through ${xx.version}, which will be covered later.
-
-
ActiveProfiles: List of manually activated profiles. For example, the profile configured above is to enable Aliyun.
How about maven looking for packages when we package according to our settings. XML file?
Maven will first look for packages in the local repository on your computer. If not, maven will look for packages in the active repository. If not, Maven will look for packages in the central repository. This is how Maven automatically pulls packages.
Summary: Warehouse is divided into local and remote warehouse, local repository is equivalent to the package cache on-demand pull, remote warehouse is divided into the central warehouse (central) and private servers, private servers in company, school or other groups in order to accelerate packet access structures, local area network (LAN) access to the warehouse, in addition some larger IT vendors, such as ali cloud will build the central warehouse mirror, If we configure the mirror of the central repository, the requests to the central repository will be redirected to the mirror repository. Maven repositories can be customized in settings. XML (system directory and user directory, generally recommended). Profiles can set different activation conditions and configure corresponding repositories.
The following describes Maven within the project.
Engineering structure
Maven defines a standard directory structure based on convention over configuration. As follows:
directory | purpose |
---|---|
${basedir} | Store POM.xml and all subdirectories |
${basedir}/src/main/java | Java source code for the project |
${basedir}/src/main/resources | Project resources, such as property files, springMVC.xml |
${basedir}/src/test/java | Test classes for the project, such as Junit code |
${basedir}/src/test/resources | Resources for testing |
${basedir}/src/main/webapp/WEB-INF | Directory of Web application files, information about Web projects, such as web.xml, local images, JSP view pages |
${basedir}/target | Package output directory |
${basedir}/target/classes | Compile output directory |
${basedir}/target/test-classes | Test the compile output directory |
Test.java | Maven automatically runs only test classes that conform to this naming convention |
~/.m2/repository | The default location of Maven’s local repository directory |
Our standard engineering structure is shown below:
Alpha - mall ├ ─ ─ pom. XML ├ ─ ─ the SRC │ ├ ─ ─ the main │ │ ├ ─ ─ Java │ │ └ ─ ─ resources │ └ ─ ─ the test │ ├ ─ ─ Java │ └ ─ ─ resources └ ─ ─ targetCopy the code
Alpha-mall is the ${basedir} directory. The rest of the chart is very clear.
Basedir is the default Properties in the Maven project.
Maven POM
The Project Object Model (POM) is the basic unit of work of The Maven Project. It is an XML file that contains the basic information of the Project, describing how the Project is built, declaring Project dependencies, and so on.
Before creating a POM, we first need to describe the project group (groupId), the unique ID of the project.
<? The 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> <! Maven will place the jar packages of the project in the local path, such as com.angela. Alpha. Alpha-shoppingmall: /com/angela/alpha/alpha-shoppingmall --> <groupId>com.angela.alpha</groupId> <! ArtifactId --> <artifactId>alpha-shoppingmall</artifactId> <! -- version number --> <version>1.0 -- SNAPSHOT</version> </project>Copy the code
All POM files require a project element and three required fields: groupId, artifactId, and Version.
node | describe |
---|---|
project | Project root tag. |
modelVersion | Model version needs to be set to 4.0. |
groupId | This is the logo of the engineering group. It is usually unique within an organization or project. For example: Ant SOFA project groupId: com.Alipay. Sofa |
artifactId | This is the logo of the project. It is usually the name of the project. For example, consumer banking. GroupId, together with artifactId, defines the location of the artifact in the repository. ArtifactId: sofaboot- Dependencies of Ant SOFA project |
version | This is the project version number. In repositories of artifacts, it is used to distinguish between different versions. Such as:Com. Alipay. Sofa: sofaboot - dependencies: 1.0 com. Alipay. Sofa: sofaboot - dependencies: 1.1 |
Dependency management:
image-20220123175622774
A depends on B, B depends on C, and A also depends on C.
Here’s an example:
image-20220123175853833
Build life cycle
image-20220123194248631
I took a screenshot of IDEA Maven Lifecycle
- Clean: remove the old class bytecode file from the compiled file.
- Compile: Compile Java source programs into class bytecode files, compile resource files;
- Test test: Automatically runs test cases
- Report report: Results of test program execution
- Package package: War package for dynamic Web projects, JAR package for Java projects
- Install: Copy the packaged files to the specified location in the “repository”. For example, we used Install to install the packages to the local repository when we built multiple modules.
- Deploy: Deploy the package to a specified repository or configure the running directory for application deployment.
Lifecycle is going to be done by plug-ins, maven is going to be done by plug-ins.
The engineering practice
We are now working on a project that, as I mentioned in the previous article, is a bit larger and is managed by multiple modules. If we introduce the concept of domain, general layer and domain layer, how should we set up the maven package structure for such a project? Such as:
image-20220123200043364
First we will define these in the parent project which contains modules for this project
    <modules>
        <module>alpha-mall-api</module>
        <module>alpha-mall-dao</module>
        <module>alpha-mall-manager</module>
        <module>alpha-mall-service</module>
        <module>alpha-mall-web</module>
        <module>start</module>
    </modules>
Copy the code
Then there is dependencyManagement, which is very important in multi-module projects.
DependencyManagement configuration is not actually introduced, only for version management.
The version of the dependency package used by the entire project should be managed in the parent project POM dependencyManagement, so that the version is not messy and the management is centralized.
< properties > < Java version > 1.8 < / Java version > < project. Build. SourceEncoding > utf-8 < / project. Build. SourceEncoding > <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> < spring - the boot version > against 2.4.1 < / spring - the boot. Version > < arthas - spring - the boot. Version > 3.4.8 < / arthas - spring - the boot. Version > </properties> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-spring-boot-starter</artifactId> <version>${arthas-spring-boot.version}</version> <type>jar</type> </dependency> </dependencies> </dependencyManagement>Copy the code
You can define versions of third-party packages, such as Spring Boot and Spring Cloud versions, directly in properties.
< span style = “box-sizing: border-box; color: RGB (51, 51, 51); line-height: 22px; font-size: 14px! Important; word-break: inherit! Important;” The poM means we only need maven package version information. What is the advantage of this? For example, if you are importing a third-party package and you are worried that the version you are using is not compatible with Spring’s version, don’t worry, Spring has already decided for you. When you introduce spring-boot-dependencies, they include a list of commonly used components and their versions. Take a look at the screenshot:
image-20220123202210031
The other property is scope, which is also important. Let’s look at the optional values for scope:
The scope values | Valid range (compile, Runtime, test) | Depend on the transfer | example |
---|---|---|---|
compile | all | is | spring-core |
provided | compile, test | no | servlet-api |
runtime | runtime, test | is | JDBC driver |
test | test | no | JUnit |
system | compile, test | is |
Important: The compile attribute is not configured by default.
Compile: The default value, compile indicates that the dependent project needs to participate in the compilation of the current project, of course, subsequent tests, run cycle is also involved, is a strong dependency. It’s usually included when you pack it.
Provided: is available at compile and test time, but not at run time. For example: servlet-API, Tomcat is already provided when running projects, so Maven does not need to introduce it repeatedly.
Runtime: Valid when running, testing, but not when compiling code. For example, to implement the JDBC driver, only the JDBC interface provided by the JDK is required for project code compilation, and only the specific JDBC driver that implements the interface is required for testing or running the project.
Test: This parameter is valid only for testing, for example, JUnit.
System: valid at compile and test time, but invalid at run time. The difference with Provided is that using system-scoped dependencies must explicitly specify the path to the dependent file through the systemPath element. Because such dependencies are not resolved through Maven repositories and are often tied to native systems, they should be used with caution, potentially making builds non-portable.
Scope dependencies pass A — >B — >C. The current project is A, A depends on B, and B depends on C. If we know the scope of B in project A, how do we know the scope of C in project A? A) provided B) provided C) provided D) provided Otherwise, A depends on C, whose scope inherits from B’s scope.
The maven package is configured as follows:
In the start module, let’s take a look:
// Define the parent module, RelativePath <parent> <groupId>com.angela. Alpha </groupId> <artifactId>alpha </artifactId> < version > 0.0.1 - the SNAPSHOT < / version > < relativePath >). /pom.xml</relativePath> </parent> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.taobao.arthas</groupId> <artifactId>arthas-spring-boot-starter</artifactId> <scope>runtime</scope> </dependency>Copy the code
As you can see, package dependencies do not have version numbers, because all version numbers are defined by the parent module. This also reduces the number of inconsistent package versions and multiple versions of a project.
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
      <exclusion>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
Copy the code
In addition, we often see exclusion, which is very effective in resolving package conflicts.
Let’s start with the cause of packet conflict, for example
- A -> B -> C. A depends on B and B depends on C
- A -> D ->C, A depends on D, D depends on C
But do not match the version B and D is introduced into C, compile time complains, this time to determine the error code to use which version, general principle is to use the new version, because most of the time would consider compatible third-party packages to upgrade, not directly to cover the original version, but there are special circumstances, this for analyzing the specific case.
Dependency Analyzer in the Maven Helper plug-in can be used to analyze conflicting JAR packages.
For the sake of space, the introduction of Maven will end here. I hope you can enjoy it.