This article is participating in “Java Theme Month – Java Debug Notes Event”, see < Event link > for more details.

preface

Maven is ubiquitous in today’s Web projects, especially Java development. Maven’s repository management, dependency management, inheritance, and aggregation features provide a complete solution for building projects. If you don’t understand Maven, a multi-module project can be a headache, dependency conflicts can be confusing, and you can’t even figure out how the project works. People who have used Maven must have been hurt by Maven, but had to let it hurt, who let it facilitate the construction of the project.

Recently, there have been a number of people in the wechat group who have encountered various problems when building projects using Maven. Some of the most common questions you’ll ever hear about Maven are: Love, hate, and love.

Why use Maven

Usually in a project, we will use some third-party class libraries to improve the speed of development, rather than closed-door. After all, under the trend of rapid development of today’s software, some excellent class libraries are constantly emerging and open source for us to use flexibly. When Maven is not used, it is often necessary to set up a lib directory in a project to hold the various libraries that the project depends on, so that after submitting to SVN or GIT, each developer checks out the project locally so that all developers have the same dependent libraries. But you must face the following problems:

1. Rely on redundancy and waste space

As companies get bigger and more projects and more modules, there are problems with this approach. Different projects and modules may refer to the same dependencies. When each module commits its dependencies to SVN or GIT, the same dependencies will occupy a large space in the SVN or GIT Repository, resulting in a waste of space.

2. Version problems

If the dependent version in one project is inconsistent with the dependent version in another project. For example, one project relies on spring-boot-starter-parent-1.5.9.RELEASE, while another might rely on spring-boot-starter-parent-2.0.0.RELEASE. When combining the two projects, The lack of detailed version information of the dependent class library may cause problems such as version confusion and conflict.

3. Management problems

With the continuation of the project, the class libraries that the project depends on May need to be updated. At this time, the jar files of the class libraries that the project depends on in the lib directory need to be replaced constantly from the Internet or through other means, which brings inconvenience to the management of the dependent class libraries.

In order to solve the above problems in the process of managing the dependency library, we need to seek another dependency management approach, that is, a centralized dependency management approach. Depends on various projects as long as through the unified description file (pom) XML) to specify their own need to rely on, and don’t have to manage yourself real dependent libraries, because all the projects using the same central dependent libraries (central warehouse), so even if the project has the same dependence, also won’t appear depend on the problem of redundant. When the dependent libraries need to be upgraded, just modify pom.xml to facilitate the update. The new dependency management approach, Maven, is a POM-based tool for project dependency management, build management and project information management.

Recall that when you are new to a company or a new project and install Maven configuration after installing the JDK, you may need to modify the settings.xml file. For example, you may have to copy some configuration from someone else into your settings.xml file. Next, you will go to IDEA or Eclipse to configure the Maven plugin. Then you can start adding and modifying the

tag in the project’s POP.xml to manage jar packages, and write code in the directory structure specified by Maven. Finally, you test, package, deploy, and run plug-ins.

Q&A

Here’s why we use Maven and when we use it, and here’s a look at some of the most frequently asked questions:

1. Local warehouse? What warehouses does Maven have? How are they related?

Local repository path configuration:

<localRepository>E:/.m2/repository</localRepository>
Copy the code

You want to rely on JAR package, it is impossible to download from the Internet every time, especially some companies or projects simply do not have the case of the Internet, more laborious, so the local warehouse is equivalent to adding a layer of JAR package cache, to check here first. If you can’t find the jar, go to the private server. If you can’t find the JAR, go to the central repository. When you find the JAR, the jar will be synchronized to the private server and the local repository.

Private server: it is A server on the Intranet of your company. When your Project A depends on the interface of someone else’s Project B, what should you do? If you don’t have Maven, copy the project-b jar to your local lib. If you don’t have Maven, copy the project-b jar to your local lib. If you don’t have Maven, copy the project-b jar to your local lib. Therefore, private server stores the company’s internal dedicated JAR, not only that, private server also acts as a mirror of the central warehouse, in plain English, a warehouse agent!

The central warehouse, the warehouse is located in the Internet, by Maven team to maintain, the address is http://repo1.maven.org/maven2/. In addition, like ali and foreign provides a central repository, the address is http://maven.aliyun.com/nexus/content/groups/public, download speed faster than Maven, it is recommended to use.

2, about the<dependency>The use of

Pom. XML dependency

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> . < version > 2.0.0 RELEASE < / version > < / dependency >Copy the code

As you can see from the figure above, groupId, artifactId, version can find the location of the dependent JAR in the repository.

In general, we can go to the private servers enter artifactId on search, or to http://search.maven.org/, http://mvnrepository.com/ to find certain dependent jar.

versionDivided into development versions (Snapshot) and release versions (Release), so why?

In actual development, we often encounter such A scenario, such as service A depends on service B, A and B are developed at the same time, B found A BUG during development, after modification, the version is upgraded from 1.0 to 2.0, then A must also be upgraded in pom.xml. A few days later, B finds the problem again, modifies it, releases the upgrade version, and notifies A to upgrade… It can be said that version instability during development is the cause of this problem.

Maven has already worked out A solution for us, which is to use the Snapshot version. During the development process, the version released by B will be marked as Snapshot version, and A will select Snapshot version for dependency. Then, each release of B will be stored in the private server repository. The Snapshot version with the latest timestamp will be automatically downloaded when A builds.

3, The pom. XML dependency configuration, the local repository has been downloaded, why there is still a dependency conflict?

When you check the local repository to find that the dependency package already exists, you are prompted with a dependency conflict or a class cannot be found. In this case, you can clear the corresponding dependencies in the local repository and download them again.

4. Introduce dependency best practices to detect problems in advance!

In project engineering, we cannot avoid increasing some dependencies, maybe after adding dependencies, the runtime finds the existence of dependency conflicts and then resolves them, it seems a little late! So can you detect problems in advance?

MVN Dependency :tree if you add a new dependency, use MVN dependency:tree command to create a dependency tree and see if there are any transitive dependencies, and if there are multiple versions conflict, then solve the problem step by step!

5,MavenNormalized directory structure

The figure above shows the canonical directory structure for a Maven project.

The following two points need to be noted:

  • Contents under SRC /main will eventually be packaged into Jar/War, while contents under SRC /test will be tested and not packaged.

  • Resource files in SRC /main/resources are copied to the destination directory, which is a specified action in Maven’s default lifecycle. Hibernate/Mybatis mapping XML needs to be placed in Resources, not anywhere else.

6,MavenLife cycle of

Maven’s lifecycle includes clean, validate, compile, test, package, verify, install, site, and deploy. Note the following: When you run the following command, the previous command is automatically executed (you can skip the previous step, such as: test).

  • clean: clean up. Have a problem, clean up!
  • validate: validation. Verify that the project is correct.
  • compile: compile. Compilation is performed, and source code compilation is completed at this stage.
  • test: test. Use appropriate unit testing frameworks (e.gJUnit) Run tests.
  • package: packaging. minglejar 或 warPackage, which will proceed automaticallyclean+compile.
  • verify: check. The results of integration tests are checked to ensure that quality is met.
  • install: the installation. Local worksjarPackages are uploaded and installed to a local repository for use by other projects.
  • site: site. Deploy the site.
  • deploy: deployment. Copy the final project package to a remote repository or private server to share with other developers and projects.

The scope depends on the scope

Maven’s life cycle includes compilation, testing, and packaging. Some of these dependencies are only used for testing, such as junit, and some dependencies are not used at compile time, but only at run time. For example, mysql driver packages are not used at compile time (compile time uses JDBC interface), but at run time. There are also dependencies that need to be provided at compile time that don’t need to be provided at run time because some containers are already provided, such as the servlet-API, which is provided in Tomcat, so we just need to be provided at compile time.

Scope can solve the above problem, that is, the scope parameter is used to control the timing of packaging, and scope has the following values, representing as follows:

  • compile: the defaultscope, valid during runtime, need to be entered into the packet.
  • provided: valid at compile time, do not need to provide at run time, will not be put into the package.
  • runtime: not required for compilation, valid at run time, need to import package. (Interface separated from implementation)
  • test: is required for testing and will not be entered into packets.
  • system: indicates that a non-local repository is imported and exists in a path of the systemjar. (Generally not used)

8. Error like “Source value 1.5 is outdated and will be removed in all future releases” at compile time

An error similar to the following occurs while compiling the project:

Warning: Java: Source value 1.5 is out of date and will be removed from all future releases Warning: Java: Target value 1.5 is out of date and will be removed from all future releases To hide warnings about obsolete options, use -xlint :-options.Copy the code

This is because the project source and target are using JDK1.5 when compiling in IDEA. However, we do not have JDK1.5 installed at present (in fact, we installed JDK1.7 or higher). Finally, we use our own version to compile, so the compilation still fails. This is the kind of mistake that just happened!

There are three complete solutions:

Modules->Language Level = “8”

  • inIDEATo open project Settings (or pressCtrl + Alt + Shift + S)
  • findModulesFind the corresponding item
  • The 【Language LevelChange the value of the drop-down menu to “8”

The second option is to configure the Maven configuration file and change the JDK used to compile the plugin to 1.8

  • Open thesettings.xml
  • find<profiles>... </profiles>Tag pair and add the following code in the middle of the tag pair:
<profile> < ID > JDK-1.8 </ ID > <activation> <activeByDefault>true</activeByDefault> < JDK >1.8</ JDK > </activation> Piler < properties > < maven.com. Source > 1.8 < / maven.com piler source > < maven.com piler. Target > 1.8 < / maven.com piler. Target > The < maven.compiler.com pilerVersion > 1.8 < / maven.compiler.com pilerVersion > < / properties > < / profile >Copy the code
  • To enable theprofileSet, find<activeProfiles>... </activeProfiles>Tag pairs, add:
< activeProfile > JDK 1.8 < / activeProfile >Copy the code

Indicates that profile configuration is enabled.

Third: add it to the project’s POM.xml

Piler < properties > < maven.com. Source > 1.8 < / maven.com piler source > < maven.com piler. Target > 1.8 < / maven.com piler. Target > </properties>Copy the code

9, an error"Usage of API Documented as @since 1.8+"

If the following error occurs in the code:

Usage of API Documented as @since 1.8+ This Inspection finds All Preparing of Methods that have @since tag in their documentation. This may be useful when development is performed under newer SDK version as the target platform for production.Copy the code

The problem occurred because our code used new JAVA8 features, but the Language Level (the lowest supported version) was too low to support these features. For example, if the Language Level is set to 6.0, but new features of 8.0/9.0 are used, 6.0 cannot parse these features, so the IDE will alert us with an error.

Add the following configuration to pom.xml to solve the problem.

<build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.0</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugins>  </build>Copy the code

10,Spring Boot,Spring CloudHow to resolve the conflict between dependency packages in the project?

In the microservice project, we will introduce many dependency packages, and there are many versions of different dependency packages. It is often found that the introduced version is not appropriate, and it is easy to cause the classes in some packages to conflict with each other. For example, the database aspect loop calls a certain class, etc., which is usually difficult to solve. With a lot of effort, a search of the official website will reveal that this is due to the incorrect version of one of the packages you rely on, and you’ll have to change the version number as required.

Here’s a way to avoid this problem. You can create your project online via Spring Initializr (https://start.spring.io/), from which you can select the functional modules you need, and it will automatically match you to each version. Very convenient. You don’t have to use the auto-generated demo project, but you can refer to the auto-generated pom.xml file to get the version of the dependency package. This can completely avoid some conflicts caused by the selection of the wrong version.

Maven’s love, hate, and hatred are shared here today. If you have any other problems, please share them in the comments.

Reference:

1. maven.apache.org/guides/intr…

2. www.runoob.com/maven/maven…

3. www.cnblogs.com/wangyonghao…