server

BIOS 配置

断电恢复后自启动

  • 开机长按 Delete 进入 BIOS
  • InelRCSetup -> PCH Configuration -> PCH Devices -> Restore AC after Power Loss
  • 设置为 Power On

设置断电恢复后启动,目的是设置远程启动。

系统

Centos 7。

配置

1
2
3
4
5
6
7
8
9
10
11
12
# 关闭 selinux
$ sudo vim /etc/selinux/config
SELINUX=enforcing -> SELINUX=disabled
$ sudo setenforce 0

# 关闭 swap
$ sudo vim /etc/fstab
注释掉行 /dev/mapper/centos-swap

# 关闭防火墙
$ systemctl stop firewalld
$ systemctl disable firewalld

程序

必备

1
sudo yum install git telnet -y

zsh

1
2
3
$ sudo yum install zsh
# on my zsh
$ sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

docker

1
2
# 一键安装脚本
$ curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun

参考

vnc

服务端

1
2
3
4
sudo apt install xfonts-base xfonts-75dpi xfonts-100dpi
sudo apt install tightvncserver

# centos

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# /etc/systemd/system/vncserver@:1.service
[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
#User=wii
#Group=wii
#WorkingDirectory=/home/wii
Type=forking

# Clean any existing files in /tmp/.X11-unix environment
ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'
# ExecStart=/sbin/runuser -l wii -c "/usr/bin/vncserver %i -geometry 1920x1080"
ExecStart=/bin/sh -c "/usr/bin/vncserver %i -geometry 1920x1080"
PIDFile=/home/wii/.vnc/%H%i.pid
ExecStop=/bin/sh -c '/usr/bin/vncserver -kill %i > /dev/null 2>&1 || :'

[Install]
WantedBy=multi-user.target

客户端

这里下载。

参考

jdk

手动下载

1
2
3
4
5
# 从这里 https://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html 下载 jdk

# 安装
$ sudo yum install jdk-8u301-linux-x64.rpm
$ sudo alternatives --config java

yum

1
2
$ yum install -y java-1.8.0-openjdk-devel  # 安装 jdk
$ yum install -y java-1.8.0-openjdk # 安装 jre

mvn

这里 下载。

1
2
3
4
5
6
7
8
9
# 修改 conf/settings.xml
# 注释掉如下内容
<mirror>
<id>maven-default-http-blocker</id>
<mirrorOf>external:http:*</mirrorOf>
<name>Pseudo repository to mirror external repositories initially using HTTP.</name>
<url>http://0.0.0.0/</url>
<blocked>true</blocked>
</mirror>

npm

1
2
3
4
5
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash
$ nvm install v12
# nrm
$ npm install nrm
$ nrm use taobao

mysql / mariadb

1
2
3
4
5
$ yum install mariadb mariadb-server
$ systemctl start mariadb #启动mariadb
$ systemctl enable mariadb #设置开机自启动
$ mysql_secure_installation #设置root密码等相关
$ mysql -uroot -p #测试登录

ambari (using MapR)

依赖

  • jdk

  • mvn

  • rpm-build(centos)

  • npm

  • python-devel

    • sudo yum install -y python-devel
  • ant

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/bin/bash
    set -ex
    ANT_VERSION=1.10.11
    wget http://archive.apache.org/dist/ant/binaries/apache-ant-${ANT_VERSION}-bin.tar.gz
    sudo tar xvfvz apache-ant-${ANT_VERSION}-bin.tar.gz -C /opt
    sudo ln -sfn /opt/apache-ant-${ANT_VERSION} /opt/ant
    sudo sh -c 'echo ANT_HOME=/opt/ant >> /etc/environment'
    sudo ln -sfn /opt/ant/bin/ant /usr/bin/ant

    ant -version
    rm apache-ant-${ANT_VERSION}-bin.tar.gz
  • gcc

下载

这里下载,或使用 git 克隆,git clone git@github.com:apache/ambari.git,切换分支 git checkout branch-2.7

安装

参考这里

1
2
3
4
5
# 添加 -Drat.skip=true
$ mvn -B clean install rpm:rpm -DnewVersion=2.7.5.0.0 -DbuildNumber=5895e4ed6b30a2da8a90fee2403b6cab91d19972 -DskipTests -Drat.skip=true -Dpython.ver="python >= 2.6"

# 需要修改所有 https://s3.amazonaws.com/dev.hortonworks.com/ 开头的连接
# 参照这个 mr 修改 https://github.com/apache/ambari/pull/3283/commits/3dca705f831383274a78a8c981ac2b12e2ecce85

异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 报错
[ERROR] Failed to execute goal com.github.eirslett:frontend-maven-plugin:1.3:npm (npm install) on project ambari-admin: Failed to run task: 'npm install --unsafe-perm' failed. (error code 1) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException
[ERROR]
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR] mvn <args> -rf :ambari-admin

# 处理
cd ambari-admin/src/main/resources/ui/admin-web
npm install --unsafe-perm

# 继续打包
mvn -B clean install rpm:rpm -DnewVersion=2.7.5.0.0 -DbuildNumber=5895e4ed6b30a2da8a90fee2403b6cab91d19972 -DskipTests -Drat.skip=true -Dpython.ver="python >= 2.6" -rf :ambari-admin

问题集锦

配置远程启动

整机无负载功率在 100w 左右,功率大且并不常用,工作的时候可能会用到。远程关闭、启动方案是通过设置 BIOS 的断电恢复后自动启动 + 小米智能插座实现。

使用

系统尝试了 centos 7、centos 8、ubuntu 20.04(desktop + server),尝试安装了 ambari、mapr、openstack、microstack。最终的使用方案是,ubuntu 20.04 + openstack Wallaby。

系统最开始打算用 centos 7,觉得可能会更稳定吧,公司服务器一般也是。

想搭一套大数据平台(zookeeper、hadoop、impala、yarn、spark、kudu 等),先是尝试了 ambari,但是现在 CDH 的时候遇到收费墙问题,放弃。后发现 MapR,惊喜,先是尝试在 centos 7 上装,后来发现最新版本不支持。然后尝试从 centos 7 直接升级到 centos 8,失败。重新安装 centos 8,再安装 MapR,配置后无法开机,又重新安装。

一出问题,买的那个亮机卡就不显示内容,需要搬机箱、拆换另外一台机器的显卡,崩溃。不想再在裸机上装太多东西,笨重的东西全部放虚拟机。考虑用 virtual box,但不太方便,最后选了 openstack。

先是尝试在 centos 7 装 openstack,每次创建卷时,cinder 都会报错,pip 锁死在 8.x.x。本打算用 centos 8 试下,最终放弃。

转战 Ubuntu 之后,开始倾向于 desktop 版本,有个界面也挺好,但是那个亮机卡装的时候好好的,一进系统就什么都不显示,随选择 server 版本。

Snap 有个 MicroStack,可以一键安装 openstack,试了下,可以。但是 snap 包内的文件只读,没办法改。最终,决定还是一步一步按官网教程来安装。

openstack 官方文档有一些细节没有覆盖到,总体还是很赞。

问题

硬件错误

intel ssd 兼容性问题

但凡能看到内核日志的地方,都在疯狂刷下面的内容。后排查原因是 inter 一款 nvme 的 ssd 硬盘导致的,换了一块好了。

1
2
3
4
5
6
pcieport 0000:80:02.0: Multiple Uncorrected (Non-Fatal) error received: 0000:80:02.0
pcieport 0000:80:02.0: PCIe Bus Error: severity=Uncorrected (Non-Fatal), type=Transaction Layer, (Request ID)
pcieport 0000:80:02.0: device [8086:bf] error status/mask=88100000/88000000
pcieport 0000:80:02.0: [28] UnsupReq (First)
pcieport 0000:80:02.0: TLP Header: 34000000 01000010 00000000 00000000
pcieport 0000:80:02.0: device recovery successful

image-20210831233753508

最终

image-20210831235937113

系统信息

获取发行版信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 当前发行版
$ cat /etc/issue
Linux Mint 20 Ulyana \n \l

# 当前发行版的 debian 版本
$ cat /etc/debian_version
bullseye/sid

# 当前发行版的上游版本信息
$ cat /etc/upstream-release/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu Focal Fossa"

maven common dependencies

Slf4j

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>

Lombok

1
2
3
4
5
6
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.14</version>
<scope>provided</scope>
</dependency>

Guava

1
2
3
4
5
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>29.0-jre</version>
</dependency>

Apache Commons

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.11</version>
</dependency>

Apache Commons IO

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>

Apache Common Pool

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.9.0</version>
</dependency>

maven

简介

在Maven工程中,POM(Project Object Model)是基本的工作单元,它是一个包含工程信息和配置详细信息的XML文件,Maven根据该文件构建工程。当Maven执行一个task或者goal,会查看当前文件夹下的POM文件,从中获取需要的配置信息。

配置

说明

结构

所有的编写的POM文件都继承自Super POM,不用maven版本的Super POM可能会有差异,附录是2.1.x版本Maven的Super POM。

Minimal POM

以下字段是编写POM必须的:

  • project root
    • modelVersion
    • groupId
    • artifactId
    • version

比如:

1
2
3
4
5
6
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>

groupId, artifactId 和 version 三个值组成了项目的完整名称,组合格式是<groupId>:<artifactId>:<version>,以上面示例配置为例,artifact名称为com.mycompany.app:my-app:1

项目继承

在继承(Project Inheritance)时,以下元素会被合并:

  • dependencies
  • developers and contributors
  • plugin lists (including reports)
  • plugin executions with matching ids
  • plugin configuration
  • resources

通过添加parent元素,配置parent POMs,实现POM文件的继承。比如:

  • 目录

    1
    2
    3
    4
    .
    |-- my-module
    | `-- pom.xml
    `-- pom.xml
  • POM配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <project>
    <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-module</artifactId>
    <version>1</version>
    </project>

可选地,如果希望groupid、version、/ 和parent相同,可以在子POM中去掉相应字段,上例POM则可改为:

1
2
3
4
5
6
7
8
9
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>

相对路径继承

如果目录结构如下:

1
2
3
4
5
.
|-- my-module
| `-- pom.xml
`-- parent
`-- pom.xml

需要添加<relativePath> 元素到parent字段:

1
2
3
4
5
6
7
8
9
10
<project>
<parent>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>my-module</artifactId>
</project>

项目集成

项目集成(Project Aggregation)类似于项目继承,相对于项目继承在子模块中配置parent POM信息,项目集成则是在parent POM中配置子模块信息,这样,parent POM就了解了子模块的信息。通过项目继承,parent POM调用的命令,也会应用在子模块中。

通过以下步骤实现Project Aggregation:

  • 把 parent POMs 的 packageing值改为 “pom”
  • 在 parent POM 中指定模块的路径

示例见附录。

Inheritance OR Aggregation

  • 继承:如果多个Maven工程,使用相似的配置,可以通过抽取相似的配置为parent对项目进行重构。这样通过继承parent POM,来应用parent POM中的项目。
  • 集成:如果多个工程一起被构建或处理,可以创建parent工程,在parent中声明他的modules。这样,只需要构建parent即可,其余的也会被构建。
  • 继承 && 集成:可以同时使用继承和集成。

Variables

模型定义中属于单个值元素的任何字段都可以作为变量引用,比如${project.groupId}, ${project.version}, ${project.build.sourceDirectory}

使用定义的变量

1
2
3
4
5
6
7
8
9
10
<!-- 定义 -->
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
</project>

<!-- 使用变量 project.version -->
<version>${project.version}</version>

特殊变量

  • project.basedir
    • 当前工程所在的文件夹
  • project.baseUri
    • 当前工程所在的文件夹,uri表示
  • maven.build.timestamp
    • 表示生成开始的时间戳

Properties

Maven中,属性(Properties)是值的占位符,他们的值在该POM内任意范围内可见,通过标记${X}使用。

属性设置有以下五种方式:

  • env.X
    • env.开头
    • shell的环境变量,比如${env.PATH}
  • elementName.X
    • 对应element的值,比如:<project><version>1.0</version></project> 通过 ${project.version} 访问
  • settings.x
    • 相应元素的值包含在settings.xml,比如:<settings><offline>false</offline></settings>通过${settings.offline}访问
  • Java系统属性
    • 所有通过java.lang.System.getProperties()可以获取的值都是POM文件的属性,可以使用${java.home} 语法获取
  • x
    • 设置在<properties /> 内的属性,比如:<properties><someVar>value</someVar></properties> 可以通过${someVar}使用

示例如下:

1
2
3
4
5
6
7
8
9
10
<project>
...
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
...
</project>

Build

根据POM 4.0.0 XSD规定,Build元素被分为两部分:

  • BaseBuild
    • 两个Build(project build 和 profile build,即分别为 project下的top-level build 和 profiles 下的 build)的通用元素集(上层配置会覆盖下层)
  • Build
    • 包含BaseBuild集合以及更多的 top-level 定义

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<!-- "Project Build" contains more elements than just the BaseBuild set -->
<build>...</build>

<profiles>
<profile>
<!-- "Profile Build" contains a subset of "Project Build"s elements -->
<build>...</build>
</profile>
</profiles>
</project>

BaseBuild 元素集合

1
2
3
4
5
6
7
8
9
<build>
<defaultGoal>install</defaultGoal>
<directory>${basedir}/target</directory>
<finalName>${artifactId}-${version}</finalName>
<filters>
<filter>filters/filter1.properties</filter>
</filters>
...
</build>
  • defaultGoal
    • 如果没有给定,则执行的默认目标或阶段
  • directory
    • 存储构建过程中产生的文件的目录,在Maven的说法中叫构建目标
    • 默认为${basedir}/target
  • finalName
    • 构建时绑定的项目名称,默认是${artifactId}-${version}
  • filter
    • filters文件夹下定义*.properties 文件,其包含一系列属性,作为resources的设置
    • maven默认filters文件夹是${basedir}/src/main/filters/
    • 示例:name=value 定义在 filter文件内, 在resources使用${name}访问

Resources

resources元素用于指定项目中包含的资源,资源通常不是代码,不会被编译,用于和工程绑定或其他原因。

比如,Plexus项目需要把配置文件configuration.xml放在META-INF/plexus内,尽管可以简单地放在src/main/resources/META-INF/plexus,但是有时会希望为Plexus建立它自己的文件夹src/main/plexus,并把配置文件放在该文件夹内。为了使jar文件可以正确地绑定该资源,可以使用如下的配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<build>
...
<resources>
<resource>
<targetPath>META-INF/plexus</targetPath>
<filtering>false</filtering>
<directory>${basedir}/src/main/plexus</directory>
<includes>
<include>configuration.xml</include>
</includes>
<excludes>
<exclude>**/*.properties</exclude>
</excludes>
</resource>
</resources>
<testResources>
...
</testResources>
...
</build>
</project>
  • resources
    • 一个资源元素列表,每个元素描述包含与此项目关联的文件的内容和位置
  • targetPaht
    • 指定构建时放置资源集的目录结构,默认是base directory
    • 打包在JAR中的资源的路径,通常是META-INF
  • filtering
    • true OR false
    • 表示是否要为此资源启用过滤
    • 不必单独定义properties文件,resources文件默认可以使用POM中定义的properties 以及 通过命令行参数(-D标记,比如-Dname=value)传入的参数
  • directory
    • 定义资源所在的文件夹,默认是${basedir}/src/main/resources
  • includes
    • 一组文件模式,使用*作为通配符,指定要包含在指定目录下的资源的文件
  • excludes
    • 结构和includes类似,但是指定忽略的文件,优先级大于includes(如果在includes也包含该文件,excludes同样生效)
  • testResources
    • testResources包含testResource元素
    • testResource
      • 定义类似resource,在测试阶段被使用
      • 默认test resources 路径在${basedir}/src/test/resources
      • test resources 不会被部署

Plugins

配置plugins示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.6</version>
<extensions>false</extensions>
<inherited>true</inherited>
<configuration>
<classifier>test</classifier>
</configuration>
<dependencies>...</dependencies>
<executions>...</executions>
</plugin>
</plugins>
</build>
</project>

配置项

project element

  • packaging
    • 打包方式
      • jar
      • war
      • pom

POM Relationships

maven可以管理项目间关系:

  • 继承(inheritance)
  • 集成(aggregation)
  • 依赖(dependencies)

依赖版本指定

  • 1.0: “Soft” requirement on 1.0 (just a recommendation, if it matches all other ranges for the dependency)
  • [1.0]: “Hard” requirement on 1.0
  • (,1.0]: x <= 1.0
  • [1.2,1.3]: 1.2 <= x <= 1.3
  • [1.0,2.0): 1.0 <= x < 2.0
  • [1.5,): x >= 1.5
  • (,1.0],[1.2,): x <= 1.0 or x >= 1.2; multiple sets are comma-separated
  • (,1.1),(1.1,): this excludes 1.1 (for example if it is known not to work in combination with this library)

依赖

依赖列表是POM的基础。大多数项目的正确运行,需要依赖其他项目。在编译和执行其他goal时,Maven会下载并且链接相应的依赖。

添加依赖示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
...
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<type>jar</type>
<scope>test</scope>
<optional>true</optional>
</dependency>
...
</dependencies>
...
</project>

字段说明

  • groupId, artifactId, version
    • 依赖包信息
    • groupId, artifactId:定义相应的Maven coordinates
    • version:依赖项目的版本号

dependencyManagement

dependencyManagement用于统一版本管理,在多模块项目中,如果父项目中dependencyManagement指定了依赖版本和scoope,那么在子模块中可以省略。

其他

依赖非Maven仓库中项目

有三种方式,可以在Maven项目中,引用非Maven库中的项目:

  • 使用maven的install插件
    • mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1 -Dpackaging=jar
  • 创建自己的maven仓库,并且将其部署在私有仓库中
  • 设置依赖的scopesystem,并且定义systemPath

Tips

  • 默认打包类型是jar
  • 默认依赖库地址http://repo.maven.apache.org/maven2

打包可执行jar

附录

Super POM

Super POM for maven 2.1.x.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
<project>
<modelVersion>4.0.0</modelVersion>
<name>Maven Default Project</name>

<repositories>
<repository>
<id>central</id>
<name>Maven Repository Switchboard</name>
<layout>default</layout>
<url>http://repo1.maven.org/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>

<pluginRepositories>
<pluginRepository>
<id>central</id>
<name>Maven Plugin Repository</name>
<url>http://repo1.maven.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
<releases>
<updatePolicy>never</updatePolicy>
</releases>
</pluginRepository>
</pluginRepositories>

<build>
<directory>${project.basedir}/target</directory>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<finalName>${project.artifactId}-${project.version}</finalName>
<testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
<sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
<!-- TODO: MNG-3731 maven-plugin-tools-api < 2.4.4 expect this to be relative... -->
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>${project.basedir}/src/test/resources</directory>
</testResource>
</testResources>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
</plugin>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.0</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.3.1</version>
</plugin>
<plugin>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.1</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.5</version>
</plugin>
<plugin>
<artifactId>maven-plugin-plugin</artifactId>
<version>2.4.3</version>
</plugin>
<plugin>
<artifactId>maven-rar-plugin</artifactId>
<version>2.2</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.0-beta-8</version>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>2.0-beta-7</version>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>2.0.4</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.4.3</version>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1-alpha-2</version>
</plugin>
</plugins>
</pluginManagement>
</build>

<reporting>
<outputDirectory>${project.build.directory}/site</outputDirectory>
</reporting>
<profiles>
<profile>
<id>release-profile</id>

<activation>
<property>
<name>performRelease</name>
<value>true</value>
</property>
</activation>

<build>
<plugins>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<inherited>true</inherited>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<updateReleaseInfo>true</updateReleaseInfo>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>

</project>

Project Aggregation Example

文件目录结构

1
2
3
4
.
|-- my-module
| `-- pom.xml
`-- pom.xml

./pom.xml

1
2
3
4
5
6
7
8
9
10
11
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-app</artifactId>
<version>1</version>
<packaging>pom</packaging>

<modules>
<module>my-module</module>
</modules>
</project>

./my-module/pom.xml

1
2
3
4
5
6
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.mycompany.app</groupId>
<artifactId>my-module</artifactId>
<version>1</version>
</project>

Project element

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<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>

<!-- The Basics -->
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>...</version>
<packaging>...</packaging>
<dependencies>...</dependencies>
<parent>...</parent>
<dependencyManagement>...</dependencyManagement>
<modules>...</modules>
<properties>...</properties>

<!-- Build Settings -->
<build>...</build>
<reporting>...</reporting>

<!-- More Project Information -->
<name>...</name>
<description>...</description>
<url>...</url>
<inceptionYear>...</inceptionYear>
<licenses>...</licenses>
<organization>...</organization>
<developers>...</developers>
<contributors>...</contributors>

<!-- Environment Settings -->
<issueManagement>...</issueManagement>
<ciManagement>...</ciManagement>
<mailingLists>...</mailingLists>
<scm>...</scm>
<prerequisites>...</prerequisites>
<repositories>...</repositories>
<pluginRepositories>...</pluginRepositories>
<distributionManagement>...</distributionManagement>
<profiles>...</profiles>
</project>

参考

maven plugins

maven-shade-plugin

pom

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-shade-plugin -->
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
</dependency>

使用

打包可执行 jar 包

通过设置主类的方式,打包可执行 jar 包。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<plugin>
<!-- ... -->
<executions>
<execution>
<!-- ... -->
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>pub.wii.cook.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

目标 jar 包含指定包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.google.protobuf</pattern>
<shadedPattern>shade.com.google.protobuf</shadedPattern>
</relocation>
</relocations>
<!-- 包含指定依赖, 注意: 包含的包也会被 relocation, 不能使用shade后的信息 shade.com.google.protobuf:protobuf-java -->
<artifactSet>
<includes>
<include>com.github.scopt:scopt_2.12</include>
<include>com.google.protobuf:protobuf-java</include>
<include>com.google.protobuf:protobuf-java-util</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<configuration>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>pub.wii.cook.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>

maven-assembly-plugin

pom

1
2
3
4
5
6
<!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-assembly-plugin -->
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
</dependency>

使用

maven-assembly-plugin 插件的使用需要打包配置(通常命名为 assembly.xml、release.xml 等,具体内容参考配置示例),插件内置了一部分配置,比如 jar-with-dependencies ,使用如下配置,来启用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<plugin>
<!-- ... -->
<executions>
<execution>
<!-- ... -->
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!-- ... -->
</configuration>
</execution>
</executions>
</plugin>

这里需要注意两点。

  • 如果指定了预设配置,那么再指定打包配置文件,会被忽略

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <plugin>
    <!-- ... -->
    <executions>
    <execution>
    <!-- ... -->
    <configuration>
    <descriptorRefs>
    <descriptorRef>jar-with-dependencies</descriptorRef>
    </descriptorRefs>

    <descriptors> <!-- 会被忽略 -->
    <descriptor>src/assemble/assembly.xml</descriptor>
    </descriptors>
    <!-- ... -->
    <finalName>libs</finalName> <!-- 输出路径 -->
    <appendAssemblyId>false</appendAssemblyId> <!-- 输出路径不包含 id -->
    </configuration>
    </execution>
    </executions>
    </plugin>
  • jar-with-dependencies 插件,并不会合并 META-INF 下的内容

    • 如果,我们依赖的多个包里面定义了同样的 SPI 接口,那么只会保留其中一个的内容,这样程序在运行时,可能会抛出异常,比如

      1
      Caused by: java.lang.IllegalStateException: Could not find policy 'grpclb'. Make sure its implementation is either registered to LoadBalancerRegistry or included in META-INF/services/io.grpc.LoadBalancerProvider from your jar files.
    • 遇到这种情况,需要自定义打包配置文件,参考配置示例

非配置文件示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>pub.wii.cook.scala.main</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<!-- <descriptorRefs>-->
<!-- <descriptorRef>jar-with-dependencies</descriptorRef>-->
<!-- </descriptorRefs>-->
<descriptors>
<descriptor>src/assemble/assembly.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>pub.wii.cook.Main</mainClass>
</manifest>
</archive>
</configuration>
</execution>
</executions>
</plugin>

assembly.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0
http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>jar-with-dependencies</id>
<formats>
<format>jar</format>
</formats>

<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>true</useProjectArtifact>
<unpack>true</unpack>
<scope>runtime</scope>
</dependencySet>
</dependencySets>

<containerDescriptorHandlers>
<containerDescriptorHandler>
<handlerName>metaInf-services</handlerName>
</containerDescriptorHandler>
<containerDescriptorHandler>
<handlerName>metaInf-spring</handlerName>
</containerDescriptorHandler>
<containerDescriptorHandler>
<handlerName>plexus</handlerName>
</containerDescriptorHandler>
<!-- 示例,其实不需要,metaInf-services handler 会做这件事情 -->
<containerDescriptorHandler>
<handlerName>file-aggregator</handlerName>
<configuration>
<filePattern>.*/META-INF/services/io.grpc.NameResolverProvider</filePattern>
<outputPath>META-INF/services/io.grpc.NameResolverProvider</outputPath>
</configuration>
</containerDescriptorHandler>
</containerDescriptorHandlers>
</assembly>

exec-maven-plugin

执行命令。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<build>
<plugins>
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<groupId>org.codehaus.mojo</groupId>
<version>3.3.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<id>Show PWD</id>
<executable>pwd</executable>
<arguments>
<argument>scripts/copy_protocols.sh</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>

参考

pom example

scala

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<!-- properties -->
<properties>
<scala.version>2.12.7</scala.version>
<scala.compat.version>2.12</scala.compat.version>
<encoding>UTF-8</encoding>
</properties>

<!-- dependencies -->
<dependencies>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>${scala.version}</version>
</dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-xml_${scala.compat.version}</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-parser-combinators_${scala.compat.version}</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.scala-lang.modules</groupId>
<artifactId>scala-swing_${scala.compat.version}</artifactId>
<version>2.0.3</version>
</dependency>
</dependencies>

<!-- plugins -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
<fork>true</fork>
<verbose>true</verbose>
<encoding>UTF-8</encoding>
<compilerArguments>
<sourcepath>
${project.basedir}/src/main/java
</sourcepath>
<sourcepath>
${project.basedir}/src/main/scala
</sourcepath>
</compilerArguments>
</configuration>
</plugin>
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.*.Class</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.neu.cse</groupId>
<artifactId>PowerCloud</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>PowerCloud Maven Webapp</name>

<!-- 集中定义依赖版本号 -->
<properties>
<junit.version>4.12</junit.version>
<spring.version>4.1.3.RELEASE</spring.version>
<mybatis.version>3.2.8</mybatis.version>
<mybatis.spring.version>1.2.2</mybatis.spring.version>
<mybatis.paginator.version>1.2.15</mybatis.paginator.version>
<mysql.version>5.1.32</mysql.version>
<slf4j.version>1.6.4</slf4j.version>
<jackson.version>2.4.2</jackson.version>
<druid.version>1.0.9</druid.version>
<httpclient.version>4.3.5</httpclient.version>
<jstl.version>1.2</jstl.version>
<servlet-api.version>2.5</servlet-api.version>
<jsp-api.version>2.0</jsp-api.version>
<joda-time.version>2.5</joda-time.version>
<commons-lang3.version>3.3.2</commons-lang3.version>
<commons-io.version>1.3.2</commons-io.version>
<commons-net.version>3.3</commons-net.version>
<pagehelper.version>3.4.2</pagehelper.version>
<jsqlparser.version>0.9.1</jsqlparser.version>
<commons-fileupload.version>1.3.1</commons-fileupload.version>
</properties>

<dependencies>
<!-- 时间操作组件 -->
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>
<!-- Apache工具组件 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>${commons-net.version}</version>
</dependency>
<!-- Jackson Json处理工具包 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<!-- 单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!-- 日志处理 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- Mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>${mybatis.spring.version}</version>
</dependency>
<dependency>
<groupId>com.github.miemiedev</groupId>
<artifactId>mybatis-paginator</artifactId>
<version>${mybatis.paginator.version}</version>
</dependency>

<!-- Pagehelper -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>${pagehelper.version}</version>
</dependency>

<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!-- 连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- Spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- JSP相关 -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>${servlet-api.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jsp-api</artifactId>
<version>${jsp-api.version}</version>
<scope>provided</scope>
</dependency>
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- 资源文件拷贝插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- java编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<url>http://127.0.0.1:8080/manager/text</url>
<username>tomcat</username>
<password>tomcat</password>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<!-- 如果不添加此节点mybatis的mapper.xml文件都会被漏掉。 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
<!-- 由于以上修改了resource目录,如果不添加此节点将无法扫描到applicationContext文件都会被漏掉。 -->
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
</project>

maven pom

Maven是什么

Apache Maven是一个软件项目管理和综合工具,基于项目对象模型(POM)的概念,Maven可以从一个中心资料片管理项目构建,报告和文件.

  • Maven提供给开发人员构建一个完整生命周期框架.开发团队可以自动完成项目的基础工具建设,Maven使用标准的目录结构和默认构建生命周期.
  • 在多个开发团队环境时,Maven可以设置按标准在非常短的时间里完成配置工作.由于大部分项目的设置都很简单,并且可重复使用,Maven让开发人员的工作更轻松,同时创建报表,检查,构建和测试自动化设置.
  • Maven提供了开发人员的方式来管理:
    • Builds
    • Documentation
    • Reporting
    • Dependencies
    • SCMs
    • Releases
    • Distribution
    • mailing list
  • 概括地说,Maven简化和标准化项目建设过程.处理编译,分配,文档,团队协作和其他任务的无缝连接.Maven增加可重用性并负责建立相关的任务.

Maven目标

Maven主要目标是提供给开发人员:

  • 项目是可重复使用,易维护,更容易理解的一个综合模型
  • 插件或交互的工具,这种声明性的模式

Maven项目的结构和内容在一个XML文件中声明,pom.xml 项目对象模型(POM),这是整个Maven系统的基本单元.有关详细信息,请参阅Maven POM的部分.

Apache Maven 是一种创新的软件项目管理工具,提供了一个项目对象模型(POM)文件的新概念来管理项目的构建,相关性和文档.最强大的功能就是能够自动下载项目依赖库.

Maven启用代理访问

  • 找到文件{M2_HOME}/conf/settings.xml

  • 找到下列代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <!-- proxies
    | This is a list of proxies which can be used on this machine to connect to the network.
    | Unless otherwise specified (by system property or command-line switch), the first proxy
    | specification in this list marked as active will be used.
    |-->
    <proxies>
    <!-- proxy
    | Specification for one proxy, to be used in connecting to the network.
    |
    <proxy>
    <id>optional</id>
    <active>true</active>
    <protocol>http</protocol>
    <username>proxyuser</</username>
    <password>proxypass</password>
    <host>proxy.host.net</host>
    <port>80</port>
    <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
    -->
    </proxies>
  • 修改将上述代码,设置代理服务器

Maven本地资源库

Maven的本地资源库是用来存储所有项目的依赖关系(插件jar和其他文件,这些文件被Maven下载)到本地文件夹.

更新Maven的本地库

  • 找到文件{M2_HOME}/conf/settings.xml

  • 修改如下代码:

    1
    2
    3
    4
    5
    6
    <settings><!-- localRepository
    | The path to the local repository maven will use to store artifacts.
    |
    | Default: ~/.m2/repository
    <localRepository>/path/to/local/repo</localRepository>
    --><localRepository>D:\software\apache-maven\repository</localRepository>

Maven中央储存库

当你建立一个 Maven 的项目,Maven 会检查你的 pom.xml 文件,以确定哪些依赖下载.首先,Maven 将从本地资源库获得 Maven 的本地资源库依赖资源,如果没有找到,然后把它会从默认的 Maven 中央存储库 查找下载.

从Maven远程存储库下载

Maven的依赖库查询顺序:

  1. 在 Maven 本地资源库中搜索,如果没有找到,进入第 2 步,否则退出

  2. 在 Maven 中央存储库搜索,如果没有找到,进入第 3 步,否则退出

  3. 在给定url的远程存储库搜索,如果没有找到,提示错误信息,否则退出

给定URL的远程库

1
2
3
4
5
6
<repositories>
<repository>
<id>java.net</id>
<url>https://maven.java.net/content/repositories/public/</url>
</repository>
</repositories>

如果不注明version, maven将保持包是最新版本

定制库到Maven本地资源库

将本地的jar包导入到Maven本地资源库(以kaptcha为例):

  1. 找到kaptcha jar包所在位置

  2. 使用mvn命令安装到本地资源库:

    1
    mvn install:install-file -Dfile=c:\kaptcha-{version}.jar -DgroupId=com.google.code -DartifactId=kaptcha -Dversion={version} -Dpackaging=jar

    示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    D:\>mvn install:install-file -Dfile=c:\kaptcha-2.3.jar -DgroupId=com.google.code 
    -DartifactId=kaptcha -Dversion=2.3 -Dpackaging=jar
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'install'.
    [INFO] ------------------------------------------------------------------------
    [INFO] Building Maven Default Project
    [INFO] task-segment: [install:install-file] (aggregator-style)
    [INFO] ------------------------------------------------------------------------
    [INFO] [install:install-file]
    [INFO] Installing c:\kaptcha-2.3.jar to
    D:\maven_repo\com\google\code\kaptcha\2.3\kaptcha-2.3.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: < 1 second
    [INFO] Finished at: Tue May 12 13:41:42 SGT 2014
    [INFO] Final Memory: 3M/6M
    [INFO] ------------------------------------------------------------------------
  3. 安装完毕后,就在pom.xml中声明kaptcha的坐标:

    1
    2
    3
    4
    5
    <dependency>
    <groupId>com.google.code</groupId>
    <artifactId>kaptcha</artifactId>
    <version>2.3</version>
    </dependency>

Maven依赖关系中Scope的作用

主要管理依赖的部署,目前scope可以有五个值:

  • **compile:**缺省值,适用于所有阶段,会随项目一期发布
  • **provided:**类似compile,期望JDK,容器或使用者会提供这个依赖
  • **runtime:**只在运行时使用,如JDBC驱动,适用于运行和测试阶段
  • **test:**只在测试时使用,用于编译和运行测试代码,不会随项目发布
  • **system:**类似provided,需要显式提供包含依赖的jar,Maven不会在Repository中查找它

使用

  • Run as -> Maven install
  • Run as -> Maven build... -> clean tomcat7:run

maven problems

项目RUL路径问题

解决访问WEB项目需要添加项目名称问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- 配置Tomcat插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
<url>http://127.0.0.1:8080/manager/text</url>
<username>tomcat</username>
<password>tomcat</password>
</configuration>
</plugin>

maven project

Maven项目实践。

组织结构

1
2
3
4
project-parent
- project-foo
- project-bar
pom.xml

项目包含一个父项目,所有子模块parent指定为该项目。

DependencyManagement

  • 统一依赖版本
  • 方便依赖版本变更

revision

项目版本定义在父项目中的properties中,变量名为revision,子模块版本使用${revision}变量,并在父项目引用 flatten-maven-plugin 插件,更多可参考这里。这样,整个项目的版本号可通过revision变量来设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>flatten-maven-plugin</artifactId>
<version>1.2.5</version>
<configuration>
<updatePomFile>true</updatePomFile>
<flattenMode>resolveCiFriendliesOnly</flattenMode>
</configuration>
<executions>
<execution>
<id>flatten</id>
<phase>process-resources</phase>
<goals>
<goal>flatten</goal>
</goals>
</execution>
<execution>
<id>flatten.clean</id>
<phase>clean</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>