持续学习&持续更新中…
学习态度:守破离
【Java从零到架构师第二季】【11】Maven_Tomcat部署项目_可运行Jar
WEB项目是怎么部署到Tomcat上的
Tomcat部署项目的方式
编译打包web项目生成war
注意:
-
普通Java项目应该打包为jar,Java Web项目应该打包为war
-
web项目整个文件夹指的是IDEA编译该项目后生成的文件夹
-
【不推荐】war包本质上是一种zip包,可以将IDEA编译生成的项目文件夹压缩为zip,然后更改后缀名为war。(Tomcat运行时会自动将war解压为IDEA编译生成的项目文件夹)
-
【推荐】使用IDEA打包项目为war文件:
首先,找到生成编译项目文件的路径,方便找到编译打包之后的文件和文件夹。
然后使用IDEA打包war文件。
IDEA是如何部署web项目到Tomcat的
在Tomcat服务器启动的时候,控制台会输出一个CATALINA_BASE
,复制其后路径,在文件夹中打开此路径。
进入该目录下的conf\Catalina\localhost
,会发现一个以context path
命名的xml文件
该xml文件中就有部署项目的配置信息。
传统开发中的常见痛点
传统项目 VS Maven项目
什么是Maven
https://maven.apache.org/
https://maven.apache.org/download.cgi
http://maven.apache.org/docs/history.html
Maven项目的常见目录
Maven常用命令(指令)
首先需要进入创建好的Maven项目中。
指令mvn compile
该指令作用:编译项目
Maven默认创建的项目使用的是JDK5,但它却不支持JDK5,此时,需要配置pom.xml,参考我的另外一篇文章Maven 安装_常用操作步骤.下的修改Maven项目的JDK版本
该指令会生成target/classes
指令mvn clean
该指令作用:删除编译好的项目文件(target)
clean命令以后会经常用到。
指令mvn test
该指令作用:进行单元测试
单元测试时,不只会编译src/main,同时也会编译src/test。
也就是说会生成target/classes和target/test-classes
指令mvn package
该指令作用:打包
使用该指令之前,应先clean一下该项目。
该指令会生成target/classes、target/test-classes和jar文件
问什么会生成jar文件呢,原因在于pom.xml中有个<packaging>jar</packaging>
packaging标签是配置打包方式的(默认就是jar,如果想配置打包方式为jar的话,不用写packaging标签也可以)
打包后的jar文件中只会包含target/classes,也就是说只会打包主要的生成文件,不会打包测试生成文件
pom.xml
什么是pom.xml
Maven坐标
-
groupId、artifactId、version它们是一个整体,用来描述该项目
-
groupId、artifactId、version组成一个Maven坐标(Coordinate),能够确定唯一的一个项目
-
依赖于一个第三方库也是一样的:
<dependencies>
<!-- groupId、artifactId、version三者共同确定一个唯一的项目 -->
<!-- 因此,依赖某一个第三方库的时候,必须写这三个东西 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
</dependencies>
Maven仓库查询
我们怎么某个第三方库的groupId、artifactId、version呢?
使用如下网站查询:
https://search.maven.org
https://mvnrepository.com【推荐】
完整流程:
报错说明本地仓库没有该库文件,需要reload一下:
reload方式一
reload方式二
一个普通Java项目的pom.xml
<?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">
<!-- pom的版本 必要元素 决定了pom.xml中能写什么 -->
<modelVersion>4.0.0</modelVersion>
<!--
一个整体,用来描述该项目;
这三者组成一个Maven坐标(Coordinate);
这三者能够确定唯一的一个项目;
-->
<groupId>com.mj</groupId>
<artifactId>09_hellojava</artifactId>
<version>1.0.0</version>
<!-- 打包方式 默认值为jar; 如果是web项目,应该打包为war -->
<packaging>jar</packaging>
<!-- 属性 比如文本编码等 -->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<!-- 依赖 -->
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- 安装本地jar后,就可以使用dependency了 -->
<dependency>
<groupId>com.mj</groupId>
<artifactId>dom4j</artifactId>
<version>2.1.3</version>
</dependency>
</dependencies>
<!-- 构建信息 插件配置等 -->
<build>
<!-- 插件配置 -->
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
<executions>
<execution>
<!-- <phase>package</phase> -->
<!-- 在该插件下,下面配置的这些goal默认被package阶段绑定 -->
<!-- 但是有的插件,下面配置的这些goal就不会被某个阶段默认绑定 -->
<!-- 因此最好写上phase -->
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.mj.Main</mainClass>
<finalName>hellojava</finalName>
<!-- <includeSystemScope>true</includeSystemScope> -->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
一个JavaWeb项目的pom.xml
- 在pom.xml中加上
<packaging>war</packaging>
就代表该项目是一个web项目
<?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>programmer.lp</groupId>
<artifactId>nine_hellojava</artifactId>
<version>1.0.0</version>
<!-- 加上这一句,就代表该项目是一个web项目-->
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!--junit依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.6.RELEASE</version>
</dependency>
<!-- JSTL -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.49</version>
</dependency>
<!-- <dependency>-->
<!-- <groupId>programmer.lp</groupId>-->
<!-- <artifactId>dom4j</artifactId>-->
<!-- <version>1.1</version>-->
<!-- </dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib</classpathPrefix>
<mainClass>programmer.lp.MainTest</mainClass>
</manifest>
</archive>
<finalName>hellojava</finalName>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<!-- <phase>package</phase> -->
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<path>/test</path>
<port>8080</port>
<uriEncoding>UTF-8</uriEncoding>
</configuration>
</plugin>
</plugins>
</build>
</project>
打可运行Jar包
什么是Jar
jar包分为普通jar和可运行jar。
-
普通jar就像使用的第三方库junit、springjdbc等jar,是一种供别人使用的工具jar
-
可运行jar是可启动、可运行(执行)的,是具有main方法的jar。
-
运行jar包的命令:
java -jar xxx.jar
生成可运行Jar(普通Java项目)
一个Java项目中,是可以存在多个main方法的(多个程序入口)。
因此我们直接打包为Jar文件,当运行该Jar文件时,不知道去运行哪个main方法。
因此我们需要配置一下入口main方法。
此时,可以看出src/META-INF目录下的MANIFEST.MF文件中存在如下配置信息,这就是来配置程序入口main方法所在类的。
生成可运行Jar(Maven Java 项目)
方式一
- 1 配置pom.xml
<build>
<!-- 通过给build标签下声明一个<finalName>标签,来指定最终生成的Jar包的名字 -->
<finalName>finalName</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib</classpathPrefix>
<mainClass>programmer.lp.Main</mainClass>
</manifest>
</archive>
<finalName>hellojava</finalName>
</configuration>
</plugin>
<!-- 我们的项目有时会依赖很多第三方jar,因此需要做如下配置 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<!-- <phase>package</phase> -->
<!-- 该插件会默认将goals绑定至package阶段 -->
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<!-- ${project.build.directory}就相当于target目录 -->
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
- 2 执行package命令
打包成功后会生成一个Jar文件和一个lib目录,lib目录中放着项目依赖的第三方Jar
以后想要让别人运行我们的Jar就可以将lib目录和生成的Jar一起发送给别人(lib和Jar必须处于同一目录)。
其他方式
方式一有点麻烦,因为如果想要让别人运行我们的程序,要发送lib整个目录和Jar
还有其他方式可用,其配置详见该文章中的生成Runnable Jar。
打包本地Jar
有时候,我们项目依赖的Jar,Maven中央仓库中并没有,Jar的开发者并没有将其上传至Maven官网(中央仓库),那么这时候应该怎样打包呢?
- 1 安装本地Jar到Maven的LocalRepository
将本地Jar(xxx-2.1.3.jar)拷贝到桌面,然后命令行到桌面,执行如下命令:
mvn install:install-file -Dfile=xxx-2.1.3.jar -DgroupId=programmer.lp -DartifactId=xxx -Dversion=2.1.3 -Dpackaging=jar
此时xxx-2.1.3.jar会被安装到本地仓库中,而Maven在解析依赖时会优先从本地仓库加载,所以这时就可以使用dependency了。
- 2 在pom.xml中添加如下依赖
<dependency>
<groupId>programmer.lp</groupId>
<artifactId>xxx</artifactId>
<version>2.1.3</version>
</dependency>
实例:
mvn install:install-file -Dfile=dom4j-1.1.jar -DgroupId=programmer.lp -DartifactId=dom4j -Dversion=1.1 -Dpackaging=jar
<dependency>
<groupId>programmer.lp</groupId>
<artifactId>dom4j</artifactId>
<version>1.1</version>
</dependency>
Build Lifecycle
什么是Build Lifecycle
default生命周期
-
default的phase的执行顺序就是上图表格从上往下的顺序。
-
install会将前面几个phase最终生成的Jar安装到本地Maven仓库
Lifecycle&Plugin
-
build lifecycle(构建生命周期)由phase(阶段)组成,phase是按照顺序从上往下执行的
-
plugin由goal组成
-
一个plugin goal就代表一个任务(比如编译、打包…)
-
一个phase可以跟一个或多个plugin goal绑定
-
一个phase被执行,就会执行其绑定的所有goal
-
每一个插件基本上都会有help goal
mvn 插件名:任务名
执行某个插件中的某个goal
mvn 阶段名
执行某个phase(阶段)
dependency中scope的取值
scope分类
使用scope system打包本地Jar:
不推荐使用(本地Jar推荐install的方式打包)
<!-- 此标签就表明该dependency是一个本地Jar 需要<systemPath></systemPath>标签配合使用 -->
<scope>system</scope>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.0.RELEASE</version>
<executions>
<execution>
<!-- <phase>package</phase> -->
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<mainClass>com.mj.Main</mainClass>
<finalName>hellojava</finalName>
<!-- 将scope system类型的本地Jar也打包 -->
<includeSystemScope>true</includeSystemScope>
</configuration>
</execution>
</executions>
</plugin>
Maven依赖Servlet
使用Maven依赖Servlet时,为了防止冲突,需要加上scope provided
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
一些细节
-
普通Java项目应该打包为jar,Java Web项目应该打包为war
-
jar包分为普通jar和可运行jar。
-
在pom.xml中加上
<packaging>war</packaging>
就代表该项目是一个web项目
参考
李明杰: Java从0到架构师②JavaEE技术基石.
本文完,感谢您的关注支持!