文章目录

  • Maven 项目编译 和 运行
  • cmd 下编译 java 文件
  • `pom.xml`与 文件目录结构 的关系
  • 项目根目录名 vs. artifactId
  • 源代码文件层级目录`main/java/com/xxxx/demo` vs. `pom.xml`中的 groupId vs. 源代码中 package



Maven 项目编译 和 运行

cmd 下编译 java 文件

  1. 编译 java 文件
    在 cmd 下,进入项目的根目录pom.xml 所在目录)
mvn compile
  • 会从 远程仓库 下载依赖包到 本地仓库
  • 第一次下载会比较慢,因为会把所需要的环境(包括未来其他项目会用到的依赖,如:junit、log4j等)统统都下载到本地仓库。之后再次执行 mvn compile 就快了。
  • 会在 Maven 项目的根目录下生成 target 目录(Maven 项目打包输出目录)
  • 如果修改了代码,需要重新编译,需要清除当前编译好的文件,可以使用 mvn clean 。该操作会删除该Maven项目的 target 目录,但不会对mvn compile 下载到本地仓库的依赖包进行删除。

cmd 中显示 BUILD SUCCESS ,则 mvn compile 执行成功,maven 项目已经编译完成。

  1. 执行 main 方法
  • 如果 .java 文件是放在 包(package)里的,即文件目录如:
com 
 |
 |--- testmaven
          |
          |--- demo       // 这个 demo 是一个包
                 |
                 |--- Hello.java

则 首先 Hello.java 文件里第一行要说明 package com.testmaven.demo

mvn compile 成功编译之后,执行

mvn exec:java -Dexec.mainClass="com.testmaven.demo.Hello"

不能省略前面的 com.testmaven而只写 demo.Hello,否则执行不成功。

  • 如果 .java 文件是不放在包(package)里的,即文件目录如:
com 
 |
 |--- testmaven
          |
          |--- demo       // 这个 demo 是一个包
          |      |
          |      |--- Hello.java
          |
          |--- Hi.java    // Hi.java 并没有放在 包里

则 首先 Hi.java 文件里第一行不能写package com.testmaven.demo之类的包声明。

mvn compile 成功编译之后,执行

mvn exec:java -Dexec.mainClass="Hi"

不能写成 com.testmaven.Hi(会导致执行不成功)。

注意看看下面的区别:

mvn exec:java -Dexec.mainClass="com.testmaven.demo.Hello"mvn exec:java-Dexec.mainClass="com.testmaven.demo.Hello"

前者正常执行。

后者报错:Could not find goal 'java-Dexec.mainClass=com.testmaven.demo.Hello' in plugin org.codehaus.mojo:exec-maven-plugin:3.0.0 among available goals exec, help, java -> [Help 1]

就是因为漏了一个空格,排查了一上午都不知道问题在哪里,网上也找不到答案,一度以为是 pom.xml 与 目录结构的对应问题。吃一堑长一智。


pom.xml与 文件目录结构 的关系

项目根目录名 vs. artifactId

其实 pom.xml 中的 artifactId 与 项目文件夹根目录名字是可以不同的,实测不会报错,正常编译执行。

mvn 命令编译、执行时,实际上以pom.xml中的groupIdartifactId为准(如果与有冲突也是按为准),而非以项目文件目录结构中的根目录或目录层级名为准。

源代码文件层级目录main/java/com/xxxx/demo vs. pom.xml中的 groupId vs. 源代码中 package

其实文件层级的名,并不影响 mvn compile 的编译,也不影响mvn exec:java -Dexec.mainClass="com.testmaven.demo.Hello" 的执行。

pom.xml中的 groupId 也不影响 mvn 可以对什么包编译执行。比如<groupId> 中为 com.testmavenmain/java/com目录下可以压根就不含testmaven 这个目录,而源代码中也可以压根不含 com.testmaven 打头的包声明。

而源代码中 package 的包声明,比如声明为 package com.haha.hey ,并不一定就要将该源代码放到 com/haha/hey目录下,你甚至可以直接放到com的外面,放到main/java/下,mvn compile对项目进行编译后,还是可以通过其包名.公共类名来执行。如:

mvn exec:java -Dexec.mainClass="com.haha.hey.Waah"

影响执行的是源代码中 package 到底是怎么写的。写的是

package com.testmaven.demo

执行时就得是这个包名.公共类名。如果没写,执行时就直接是公共类名

综上:

  1. mvn 命令执行时,以pom.xml 中 的<groupId><artifactId> 为准。不受文件层级名、项目跟目录名约束。
  2. mvn 运行 java 编译后的程序,只与 java 源代码中声明的包有关系,与该java源文件放在什么目录下无关。(当然该java源文件还是需要放在/src/main/java/内才行,再往外面就不行了。)
  3. Maven 项目的目录层级结构的命名只是约定,并不强制。pom.xml才是关键。