笔记:Maven

281 阅读5分钟

Tomcat部署项目的方式

image.png

增加Artifacts的时候,如果选择:
【Web Application: Exploded(暴露)】:编译后的产物是解压的
【Web Application: Archive(压缩)】:编译后的产物是压缩的war包

  • 将Web项目整个文件夹,放在%TOMCAT_HOME%/webapps目录中,文件夹名作为ContextPath

例如crm项目,build后 项目路径 out文件夹 --> artifacts文件夹 下的 crm_war_exploded 文件夹 拷贝至 %TOMCAT_HOME%/webapps。 启动Tomcat后,http://localhost:8080/crm_war_exploded/就可以访问。context就是文件夹名crm_war_exploded

  • 将web项目打包成war, 放在%TOMCAT_HOME%/webapps目录中,war文件名作为ContextPath

例如crm项目,build后 项目路径 out文件夹 --> artifacts文件夹 --> crm_war_exploded的子文件夹压缩成 crm1.zip 后缀改成 crm1.war, 移动至 %TOMCAT_HOME%/webapps,会自动解压成crm1文件夹。 启动Tomcat后,http://localhost:8080/crm1/就可以访问。context就是文件夹名crm1

war包本质上就是jar,jar就是基于zip,zip基础上加上签名等操作

image.png

  • %TOMCAT_HOME%/conf/server.xml的HOST标签中添加以下内容(ContextPath是Path属性值):

    <Context docBase="项目路径" path="xxxx" />
    
  • %TOMCAT_HOME%/conf/Catalina/localhost中新建一个xml文件,xml文件名作为ContextPath: (不需要path属性,path即为xml文件名)

  • IDEA 为了不侵入,%TOMCAT_HOME%.在Dcatalina.base(每次启动都变化,可从控制台获取)下增加 crm.xml

<Context path="/crm"  docBase="/Users/~/Desktop/learn_java/code/MyPro/out/artifacts/crm_war_exploded" />

image.png

image.png

maven初始化配置

  1. windows: 先配置JAVA_HOME,然后配置MAVEN_HOME,添加%MAVEN_HOME%/binPATH中.mac:在~/.zshrc中配置环境变量:
export M2_HOME=/Users/robbie/apache-maven-3.3.3
export PATH=$PATH:$M2_HOME/bin
  1. 修改仓库位置:在%MAVEN_HOME%/conf/settings.xml<settings>标签中添加1个<localRepository>
<localRepository>F:\Dev\Java\.m2\repository</localRepository>

3.提高仓库的下载速度:在%MAVEN_HOME%/conf/settings.xml<mirrors>标签中添加1个<mirror>

<mirror>

<id>aliyun</id>

<name>aliyun</name>

<url>https://maven.aliyun.com/repository/public</url>

<mirrorOf>central</mirrorOf>

</mirror>

命令行新建Maven项目

1、 命令行输入:mvn archetype:generate, 会让我们选择项目类型。默认值是7,maven-archetype-quickstart,是个普通的java项目,创建web项目,输入10.输入groupId、artifactId、version、package.

2、命令行输入:mvn archetype:generate -DgroupId=com.xx.maven -DartifactId=helloworld -Dversion=1.0-RELEASE -DarchetypeGoupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-quickstart

image.png

  • mav compile、mav clean、mvn test 、 mvc package

mvn compile会报错 需要修改JDK版本。mvn test默认使用Junit3.8。

image.png image.png image.png

<profile>
    <id>jdk14</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>14</jdk>
    </activation>
    <properties>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>

        <maven.compiler.compilerVersion>14</maven.compiler.compilerVersion>

    </properties>
</profile>

IDEA创建maven项目

  • IDEA自带一个maven

image.png

  • 创建Maven项目

image.png

  • 导入Maven项目

选择pom.xml进行导入

  • pom.xml

image.png

  • 下载依赖

以下操作,会把工程下所有module的依赖全部下载。 image.png

以下只会下载当前module的依赖,或者点击module文件夹右键,【Maven】-【Reload project】

image.png

构建生命周期

image.png

image.png

在终端输入:mvn compile 这个是 阶段phase. mvn compiler:compile 是执行某个插件的某个goal。

default 生命周期

image.png

image.png

生成Runnable Jar

jar包分为普通jar包:提供功能供别人使用,Runnable Jar:可以直接运行。

运行jar包命令:$ java -jar 路径

普通项目打包(非maven项目)

建一个普通java项目,主类Main方法里打印一句话。

image.png

image.png

然后 【build】-【build Artifacts】

java -jar 运行,发现成功打印。

maven项目打包

  • 方法一 maven-jar-plugin
<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>主类</mainClass>
                    </manifest>
                </archive>
                <finalName>jar的文件名</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>
    </plugins>
</build>

executions: 在executions中说明这个插件该如何执行。

image.png

image.png

这种方式,依赖的lib并没有放入最终的jar里。不推荐这种方式。

  • 方法二 maven-assembly-plugin
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.3.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>主类</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <finalName>jar文件名</finalName>
                <appendAssemblyId>false</appendAssemblyId>
            </configuration>
            <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
            </executions>
        </plugin>
    </plugins>
</build>

image.png

多出的一个firstmvn-1.0.0.jar是按照默认方式打的,不用管。

  • 方法三 maven-shade-plugin
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.3</version>
            <executions>
                <execution>
                     <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <shadedArtifactAttached>true</shadedArtifactAttached>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>主类</mainClass>
                            </transformer>
                        </transformers>
                        <finalName>jar文件名</finalName>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  • 方法四 spring-boot-maven-plugin
<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> -->
                    <goals>
                        <goal>repackage</goal>
                    </goals>
                    <configuration>
                        <mainClass>com.scc.Main</mainClass>
                        <finalName>firstmvn4</finalName>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

安装本地jar到Maven的LocalRepository

mvn install:install-file -Dfile=jar的路径 -DgroupId=组织 -DartifactId=库名 -Dversion=版本 -Dpackaging=jar

然后再pom.xml里引用依赖

dependency中的scope取值

image.png

类路径包括编译路径、测试路径、运行路径等。
compile是默认的,在编译路径、测试路径、运行路径都可用。
test仅在测试编译和执行阶段可用。
system使用场景:上面说本地的jar包可以安装到maven本地的中央仓库里使用,也可以放在项目里,指定system.不推荐这种做法,推荐安装到本地仓库 具体步骤:

1.项目里lib文件,导入jar包。然后 右键【Add As Library】
2.添加依赖,依赖里指定system和systemPath.

<dependency>
    <groupId></groupId>
    <artifactId></artifactId>
    <version></version>
    <scope>system</scope>
    <systemPath>${basedir}/lib/xxxx.jar</systemPath>
</dependency>
  1. 打包的插件添加<includeSystemScope>true</includeSystemScope>

image.png

创建maven web项目

首先参考上面创建普通的maven项目,不勾选Create from archetype

然后配置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">

    <!--    模型版本-->
    <modelVersion>4.0.0</modelVersion>

    <!--    项目信息-->
    <groupId>com.scc</groupId>
    <artifactId>webpro</artifactId>
    <version>1.0.0</version>

    <!--    打包方式-->
    <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>

    </dependencies>

    <!--    构建信息-->
    <build>
        <filename>webpro</filename>
    </build>


</project>

加上<packaging>war</packaging>,只有加上这个IDEA才会认为这是个web项目。然后对项目进行Reimport。【Project Structure】--【Facets】--【web】下面才会出现这个项目。

为了避免jar包冲突,修改servletscopeprovided

这时候main文件夹下没有webapp文件夹

添加web.xml

image.png

将web.xml放在/src/main/webapp/WEB-INF下面

image.png

把Maven项目部署到Tomcat上去

使用Maven内置的Tomcat

Maven自带tomcat7插件,利用这个插件部署项目。会把项目部署到tomcat7上,而不是我们自己下载的tomcat9.(tomcat7是从maven中央仓库下载的。)

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
        <path>/context_path</path>
        <port>8080</port>
        <uriEncoding>UTF-8</uriEncoding>
    </configuration>
</plugin>

<uriEncoding>UTF-8</uriEncoding>:浏览器会自动给url进行uriencoding操作,在tomcat7时,必须配置uriencoding的解码方式,tomcat8之后不需要。不配置会乱码,即使request.setCharacterEncoding("UTF-8");也不行,后面【编码问题】再讨论这个问题。

运行命令$ tomcat7:run报错。是因为编译阶段需要javax.servlet,所以pom.xml里配置了javax.servlet的依赖,但是tomcat7运行时又自带了javax.servlet,导致了jar包冲突。解决办法:修改 修改servlet的scope为provided。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency

运行命令$ tomcat7:run,可以成功部署项目,但无法热部署。我们自己的Tomcat是Tomcat9。 解决方案是:利用 $ tomcat7:deploy把我们的项目部署到IEDA关联的Tomcat9上。这样就能方便的使用IDEA的热更新了。

使用独立安装的Tomcat9

首先把tomcat9运行起来,但是tomcat9是不允许任何项目随便部署上去,Tomcat9提供一个用户名和密码,开发权限,然后通过url、用户名和密码部署上去。

%TOMCAT_HOME%/conf/tomcat-users.xml中添加用户权限.如下。用户名和密码可以自己定,其他不要改。

<tomcat-users xmlns="http://tomcat.apache.org/xml"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://tomcat.apache.org/xml tomcat-users.xsd"
              version="1.0">
  <role rolename="manager-gui"/>
  <role rolename="manager-script"/>
  <user username="root" password="root" roles="manager-gui,manager-script" />
</tomcat-users>

%MAVEN_HOME%/conf/settings.xml的中添加

<server>
      <id>tomcat9</id>
      <username>root</username>
      <password>root</password>
</server>

集成tomcat7-maven-plugin

<plugin>
    <groupId>org.apache.tomcat.maven</groupId>
    <artifactId>tomcat7-maven-plugin</artifactId>
    <version>2.2</version>
    <configuration>
            <path>/context_path</path>
            <update>true</update>
            <port>8080</port>
            <!--
            <url>http://localhost:8080/manager/text</url>
            -->
            <uriEncoding>UTF-8</uriEncoding>
            <server>tomcat9</server>
            <!--
            <username>root</username>
            <password>root</password>
            -->
    </configuration>
</plugin>

<path>/context_path</path>:配置context_path. <update>true</update>:是否可以热部署。 <url>http://localhost:8080/manager/text</url>:访问Tomcat9的url.端口和ip根据实际情况配置。本地的话可以省略。 <uriEncoding>UTF-8</uriEncoding>:后面再加以说明。
<server>tomcat9</server>:通过%MAVEN_HOME%/conf/settings.xml配置的server的id,查找server.(也可以通过 username和password的方式。)然后会自动通过url上传到自己本地的tomcat9上去。

步骤:启动tomcat9.(sh startup.sh) --> mvn tomcat7:deploy/redeploy. 这样就部署到tomcat9上去了。

image.png

可以看到,mvn tomcat7:deploy.命令会首先执行编译打包操作,然后会上传到tomcat9上去。

但是这样还是不方便,我们要结合Maven和IDEA。 使用IDEA内置的build.

删除tomcat7插件。

<build>
    <finalName>webpro</finalName>
</build>

配置IDEA的tomcat

image.png

这样就依然可以使用IDEA部署,热更新了。

image.png

Tomcat7编码问题

通过Tomcat7部署项目,会出现编码问题

pom.xml

<build>
    <finalName>webpro</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.2</version>
            <configuration>
                    <path>/myweb</path>
                    <port>8080</port>
            </configuration>
        </plugin>
    </plugins>
</build>

LoginServlet:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 解决post请求参数乱码
    request.setCharacterEncoding("UTF-8");
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println(username +" ======= "+ password);
    response.setContentType("text/plain,charset=UTF-8");
    if ("123".equals(username) && "123".equals(password)) {
        response.getWriter().write("登录成功");
    } else {
        response.getWriter().write("登录失败");
    }
}

@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    doGet(request, response);
}

post请求正常,get请求,用户名和密码输入中文的时候,打印的是乱码。是因为浏览器会自动进行uriEncoding。 设置request.setCharacterEncoding("UTF-8");是设置请求体的编码,并不会影响url。所以post请求正常,get会乱码。

解决: 方法一:在tomcat7,server.xml的connector标签配置uriEncoding。 方法二:在tomcat7插件里配置。

<configuration>
      <path>/myweb</path>
      <port>8080</port>
      <uriEncoding>UTF-8</uriEncoding>
</configuration>

当输入账号和密码后,发现响应又是乱码。这里就不是Tomcat7的问题了,Tomacat9也有可能有问题。

这是因为首先LoginServlet.java里的内容写入文件时,IDEA配置的是UTF-8编码

image.png

LoginServlet.java编译的过程中,会首先加载到内存中,然后再写入.class文件,那么加载在内存和写入.class文件的时候,如果用IDEA build,他会保持和写入文件时一样的编码方式,但是如果用mvn package,如果不配置,他会使用系统默认的编码方式,windows是GBK.(mac这里没问题) 就会导致乱码的产生。

配置maven编译的时候编码方式,pom.xml里增加:

<!--    属性-->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>    
</properties>

image.png

其他常见问题

image.png

image.png