Maven abused me a thousand times, I treat Maven like my first love

foreword

In today's Internet project development, especially in the field of Java, it can be said that Maven can be seen everywhere. Maven's warehouse management, dependency management, inheritance and aggregation features provide a complete set of solutions for project construction. It can be said that if you don't understand Maven, then a multi-module project is enough to give you a headache, and dependency conflicts will It makes you overwhelmed, and you can't even figure out how the project works...OK, bloggers have been "hurt" by Maven, so the purpose of this topic is: completely get Maven!

Thinking in Maven

Recall that when you are new to a company, after installing the JDK, you will install and configure Maven (MAVEN_HOME, path). It is very likely that you need to modify the settings.xml file. For example, you will modify the local warehouse address path. For example, you are likely to It will copy a section of configuration to your settings.xml (probably some configuration of private server).

Next, you will go to IDEA or Eclipse to configure the Maven plug-in, and then you can start adding <dependency> tags in the pom.xml in the project to manage the jar package, write code in the directory structure of the Maven specification, and finally You will use plugins to test, package (jar or war), deploy, and run.

The above describes some of the ways we use Maven, let's think about it below:

local warehouse? What repositories does Maven have? How are they related?

If you want a jar package, it is impossible to download it online every time. It takes a lot of effort, so the local warehouse is equivalent to adding a layer of jar package cache, so come here to check first. If you can't find it here, then go to the private server to find it. If you can't find it on the private server, then go to the central warehouse to find it. After finding the jar, the jar information will be synchronized to the private server and the local warehouse.

Private server is just a server on the company's internal LAN. Think about it, when your project Project-A depends on the interface of other people's Project-B, what should you do? When there is no Maven, of course, copy the Project-B jar into your local lib and introduce it, then the Maven method obviously requires others to deploy Project-B to the private server repository for your use. Therefore, the company's internal dedicated jar is stored in the private server! Not only that, but the private server also acts as a mirror of the central warehouse, which is a proxy to put it bluntly!

Central repository: This repository stores jars on the Internet and is maintained by the Maven team at http://repo1.maven.org/maven2/.

About the use of <dependency>

In fact, this tag reveals the lookup coordinates of the jar: groupId, artifactId, version.

Generally speaking, we can enter the artifactId on the private server to search, or go to http://search.maven.org/, http://mvnrepository.com/ to find and determine the coordinates.

The version is divided into a development version (Snapshot) and a release version (Release), so why should it be divided? In actual development, we often encounter such scenarios. For example, service A depends on service B, A and B are developed at the same time, and B finds a bug in development. After modification, the version is upgraded from 1.0 to 2.0, then A must also Follow the version upgrade in POM.XML. A few days later, B found the problem again, made changes and released the upgraded version, and then notified A to upgrade... It can be said that the unstable version during the development process caused such a problem.

Maven has already figured out a solution for us, which is to use the Snapshot version. During the development process, the version released by B is marked as the Snapshot version, and A selects the Snapshot version when relying on it. Then every time B is released, it will be in the private server warehouse. , forming a Snapshot version with a timestamp, and when A builds, it will automatically download the Snapshot version with the latest timestamp of B!

Now that Maven has dependency management, why do dependency conflicts still occur? What are the means of dealing with dependency conflicts?

First of all, for Maven, only one version can be used under the same groupId and the same artifactId!

According to the order of dependencies in the diagram above, the 1.2 version of the jar will be used.

Now, we can think about it, for example, A and B need to be introduced into the project, and A depends on the 1.0 version of C, and B depends on the 2.0 version of C, then the problem comes, the version used by C will depend on the order in which A and B are introduced. ? This is obviously unreliable! If A's dependencies are written after B's dependencies, it means that the 1.0 version of C is finally introduced. It is very likely that the class (ClassNotFoundException) and method (NoSuchMethodError) cannot be found errors during the runtime (because B uses high version C)!

There are actually two concepts involved here: transitive dependency and Maven's recent dependency strategy.

Dependency transitivity: If A depends on B, and B depends on C, then introducing A means that both B and C will be imported.

Maven's closest dependency policy: If a project depends on multiple versions of the same groupId, artifactId, the version closest to the project in the dependency tree (mvn dependency:tree) will be used. (It can be seen from here that Maven is a little problem? Can you choose a higher version for dependency? It is understood that Gradle is the version+ strategy)

Now, we can think about how to deal with dependency conflicts?

Idea 1: We know which version to use, so can we lock the version regardless of how dependencies are passed?

Use <dependencyManagement> [this is mainly used for version consistency of submodules]

Idea 2: Can we remove what we don't want to depend on in dependency transit?

Use <exclusions> [In practice we can use plugins directly in IDEA to help us generate]

Idea 3: Since it is the most recent dependency strategy, then we directly use the explicit dependency to specify the version, isn't that the closest to the project?

use <dependency>

Introduce best practices for dependencies and spot problems ahead of time!

In the project, we can't avoid the need to add some dependencies. Maybe after adding the dependencies, we find that there is a dependency conflict to be resolved at runtime. It seems a bit late! So can we find the problem in advance?

If we add a new dependency, first use the mvn dependency:tree command to form a dependency tree to see if there is a transitive dependency in our newly added dependency, and if there is a conflict between the transitive dependency and the version in the dependency tree, if there are multiple Version conflicts, use the above method to resolve!

Maven canonicalize directory structure

There are two points to note here: First: the content under src/main will eventually be packaged into Jar/War, while the content under src/test is the test content and will not be packaged.

Second: The resource files in src/main/resources will be copied to the target directory, which is a prescribed action in Maven's default life cycle. (Think about it, the mapping XML of hibernate/mybatis needs to be placed under resources, and cannot be placed elsewhere)

Maven life cycle

We only need to pay attention to one thing: when the following command is executed, the previous command is automatically executed.

In fact, the most commonly used are the following:

  • clean: If there is a problem, clean up more!
  • package: typed into a Jar or War package, it will automatically perform clean+compile
  • install: upload the local project Jar to the local warehouse
  • deploy: upload to private server
About scope dependencies

Since Maven's life cycle includes the processes of compiling, testing, and running, it is obvious that some dependencies are only used for testing, such as junit; some dependencies are not used for compilation and can only be used when running, such as the mysql driver package during the compilation period. It is not used (the JDBC interface is used at compile time), but is used at runtime; there are also some dependencies, which are used at compile time, but do not need to be provided at runtime, because some containers already provide them, such as servlet- The api is already provided in tomcat, we only need to provide it at compile time.

In conclusion:
  • compile: The default scope, valid at runtime, needs to be entered into the package.
  • provided: It is valid at compile time. It does not need to be provided at runtime and will not be entered into the package.
  • runtime: Compilation is not required, it is valid at runtime and needs to be imported into the package. (separation of interface and implementation)
  • test: required for testing, will not be entered into the package.
  • system: A jar imported from a non-local repository and stored in a certain path of the system. (generally not used)

If you are struggling on the road of JAVA and want to get a high salary in the IT industry, you can participate in our training camp courses, choose the most suitable course for you to learn, and the technical experts will teach you personally. After 7 months, you can enter a famous company and get a high salary . Our courses include: Java engineering, high performance and distributed, high architecture. Performance tuning, Spring, MyBatis, Netty source code analysis and big data and other knowledge points. If you want to get a high salary, want to study, want good employment prospects, want to gain an advantage in competition with others, want to enter Ali for an interview but are worried that the interview will fail, you can come. The q group number is: 956011797

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324126029&siteId=291194637