Several Ways of Packaging Projects in maven

  • 2021-10-11 18:34:14
  • OfStack

Directory Method 1: Packaging with maven-jar-plugin and maven-dependency-plugin Plugins Method 2: Packaging with maven-assembly-plugin Plugins Method 3: Packaging with maven-shade-plugin Plugins

Maven can use the mvn package directive to package the project. If you run the jar file using Java-jar xxx. jar, errors such as "no main manifest attribute, in xxx. jar" (Main-Class is not set) and ClassNotFoundException (dependent package cannot be found) will occur.

For the jar package to run directly through java-jar xxx. jar, you need to meet the following requirements:

1. Specify Main-Class in META-INF/MANIFEST. MF in the jar package to determine where the entry to the program is;

2. Be able to load dependency packages.

Using Maven, there are several ways to generate jar packages that can run directly, and you can choose one appropriate method according to your needs.

Method 1: Packaging with maven-jar-plugin and maven-dependency-plugin plug-ins

There is a disadvantage in generating jar packages in this way, that is, too many jar packages are generated, which is inconvenient to manage. The other two ways only generate one jar file, which contains the code, resources and all dependent packages of the project itself.


<build>
        <plugins>
            <!--       Configure packaging and configure MainClass ,   However, if the dependency package is not packaged, an exception will occur that the dependency cannot be found     -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <!--   MANIFEST.MF  Medium  Class-Path -->
                            <classpathPrefix>lib/</classpathPrefix>
                            <mainClass>cn.zoom.wqz.filter.Application</mainClass>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
            <!--       Configure dependency packages       -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy-dependencies</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <!--               Packaging dependency packages to target Under lib Directory               -->
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

Method 2: Packaging with maven-assembly-plugin plug-ins

Packaging method:


mvn package assembly:single  

Configuration mode:


          <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>cn.zoom.wqz.filter.Application</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
            </plugin>

After packaging, an xxx-jar-with-dependencies. jar file will be generated in the target directory. This file contains not only the code and resources in your own project, but also the contents of all dependent packages. So it can be run directly through java-jar.

It can also be packaged directly through mvn package without assembly: single, but one configuration is required:

However, if spring Framework is used in the project, the package typed in this way will run in error, which can be handled by using the following method 3.


           <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>cn.zoom.wqz.filter.Application</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <!--  Among them <phase>package</phase> , <goal>single</goal> That is, it means that it is executing package When packaging, execute the assembly:single -->
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

Method 3: Packaging with maven-shade-plugin plug-ins


            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>cn.zoom.wqz.filter.Application</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Once the configuration is complete, execute mvn package to package. Two jar packages are generated under the target directory, note that not the original-xxx. jar file, but the other one. Like maven-assembly-plugin1, the generated jar file contains all the dependencies, so it can be run directly.

If Spring Framework is used in the project and the dependency is called into one jar package, an error will occur at runtime reading the XML schema file. The reason is that multiple jar packages of Spring Framework contain the same files spring. handlers and spring. schemas, and if one jar package is generated, it will overwrite each other. To avoid mutual influence, you can use AppendingTransformer to append merge to file contents:


<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>cn.zoom.wqz.filter.Application</mainClass>
                                </transformer>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/spring.handlers</resource>
                                </transformer>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                    <resource>META-INF/spring.schemas</resource>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

Related articles: