Maven

dependence

optional

如果需要做一个数据库组件,而且这个数据库组件需要支持多个数据库的话,应用服务不太可能同时使用多种不同的数据库,它只需要自己用到的数据库的驱动包就可以了。比如一个使用了 mysql 的服务,是没有必要引入 oracle 的驱动包的。这时候 optional 就派上用处了。optional 表示该依赖是可选的,意味着构建后,标记为 optional 的依赖是不会被一起打入 jar 包的,也不会发生依赖传递。这样不仅我们自己的组件端体积变小了,应用服务也解决了引入过多无用依赖的问题。

如果依赖没有带入,那么程序运行期间,会不会发生类找不到的问题?确实是这样的,实际上 optional 表示可选,它将选择权交给了上层应用服务。假如我的服务使用了 mysql,那么我就在服务自己的 pom.xml 中引入 mysql 的驱动包;如果用的是 oracle,同理也是自己引入 oracle 的驱动包,也就是按需使用。如果服务没有引入任何数据库驱动,那么最坏的情况应该是不会使用数据库相关的功能,而不是报错。

optional 更是一种规范,规范了以下行为:

  1. optional 通常用于组件端应用,即一个 jar 包,而不是一个应用服务;

  2. optional 的依赖不会一起被打包,不会经过依赖传递而引入上层应用服务中;

  3. optional 的依赖,表示可选,及时没有该依赖,也不影响程序运行,这里需要程序进行一些额外的判断逻辑;比如Spring的@Condition注解

  4. optional 的依赖,由上层应用服务来选择是否引入。

provider

provided 其实与 optional 非常像,因为从结果来看,二者基本上没有什么区别:标记为 provided 的依赖,和 optional 其实效果是一样的,都不会被直接的打入包中,不会通过依赖传递而传递到上层应用服务的依赖中。那么为什么这里需要把 provided 与 optional 区分开呢?

这里其实,二者虽然在效果上没有直接的区别,但是二者的使用场景不一样。上面说了 optional 主要用于“可选依赖”的场景,依赖是否引入,都不会影响服务正常运行。而 provided 表示的不是依赖可选,它表示这个依赖是必须的,但是这个依赖通常是已经提供的,应用服务不需要额外引入,通常也不用关心。例如很多人使用 tomcat 作为服务运行容器,tomcat 自己会提供一些必备的依赖项,这些依赖项对于服务正常运行必须的,但是对于应用服务来说,这些依赖项是已经提供好的,不需要自己关心。

所以很多时候,会有人将 optional 与 provided 弄混,甚至一起使用,而且通常情况下是没有什么问题的。不过我们还是需要明白二者的区别。虽然二者的行为是一致的,但是对于二者规定的规范确实不同的:

optional 表示某个依赖可选,该依赖是否使用都不会影响服务运行。例子:吃面时候,酱油就是可选的,加不加都不会影响面的正常使用。 provided 表示某个依赖必须,不过该依赖通常是由系统或者容器提供,不需要自己关系。例子:吃面时候,筷子、碗这样的东西都是必须的,不过这些一般是店家给顾客备好,不需要顾客自带。

常用命令

打包命令

# 清理打包
mvn clean package

# 打包跳过单元测试,但是编译测试用例类生成相应的class文件至target/test-classes下
mvn clean package -DskipTests=true

# 打包跳过单元测试,并且不编译测试用例
mvn clean package -Dmaven.test.skip=true

常用的settings.xml

阿里云仓库

<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
    <localRepository>D:/alirepository</localRepository>
    <mirrors>
        <!-- 阿里云仓库 -->
        <mirror>
            <id>alimaven</id>
            <mirrorOf>central</mirrorOf>
            <name>aliyun maven</name>
            <url>http://maven.aliyun.com/nexus/content/repositories/central/</url>
        </mirror>
    
        <!-- 中央仓库1 -->
        <mirror>
            <id>repo1</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo1.maven.org/maven2/</url>
        </mirror>
    
        <!-- 中央仓库2 -->
        <mirror>
            <id>repo2</id>
            <mirrorOf>central</mirrorOf>
            <name>Human Readable Name for this Mirror.</name>
            <url>http://repo2.maven.org/maven2/</url>
        </mirror>
    <!-- 阿里云的maven路径, -->
    <mirror>
        <id>nexus-aliyun</id>
        <mirrorOf>*</mirrorOf>
        <name>Nexus aliyun</name>
        <url>http://maven.aliyun.com/nexus/content/groups/public</url>
        </mirror>
    </mirrors> 
</settings>

开发生产配置文件切换

根据当前环境编译指定的配置文件

根据需要,可以将环境设置为以下几种:

  • dev 本地开发环境

  • test 测试环境

  • pro 线上环境

在resources目录下,建立三个文件夹,分别存储不同环境下的配置文件:

  • dev

  • test

  • pro

  • public 代表公共配置

定义三个配置,配置中定义了properties,通过更改属性(properties),更改当前环境:

<profiles>
    <profile>
        <id>dev</id>
        <activation>
            <!--默认环境-->
            <activeByDefault>true</activeByDefault>
            </activation>
        <properties>
            <package.environment>dev</package.environment>
        </properties>
    </profile>
    <profile>
        <id>test</id>
        <properties>
            <package.environment>test</package.environment>
        </properties>
    </profile>
    <profile>
        <id>online</id>
        <properties>
            <package.environment>pro</package.environment>
        </properties>
    </profile>
</profiles>

指定构建时的resources目录:

<resources>
    <resource>
        <directory>src/main/resources/${package.environment}</directory>
        <filtering>true</filtering><!--是否进行过滤-->
    </resource>
    <resource><!--添加公共配置文件目录-->
        <directory>src/main/resources/public</directory>
    </resource>
</resources>

编译之后的效果:

根据当前环境替换占位符

需要以来插件 maven-resources-plugin,目前根据公司项目可以将环境大致分为开发环境、SIT环境 、UAT环境以及生产环境,定义如下profile:

    <profiles>
        <profile>
            <id>dev</id>
            <activation>
                <activeByDefault>true</activeByDefault> <!--默认启用dev配置-->
            </activation>
            <properties>
                <configEnv>dev</configEnv>
                <jsfConfigEnv>dev</jsfConfigEnv>
            </properties>
        </profile>
        <profile>
            <id>sit</id>
            <properties>
                <configEnv>test</configEnv>
                <jsfConfigEnv>sit</jsfConfigEnv>
            </properties>
        </profile>
        <profile>
            <id>uat</id>
            <properties>
                <configEnv>test</configEnv>
                <jsfConfigEnv>uat</jsfConfigEnv>
            </properties>
        </profile>
        <profile>
            <id>pro</id>
            <properties>
                <configEnv>pro</configEnv>
                <jsfConfigEnv>pro</jsfConfigEnv>
            </properties>
        </profile>
    </profiles>

定义插件maven-resources-plugin,指定占位符编码信息:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.5</version>
    <configuration>
        <useDefaultDelimiters>false</useDefaultDelimiters>
        <delimiters>
            <delimiter>${*}</delimiter> <!-- 占位符匹配  ${xxx}--> 
        </delimiters>
        <encoding>UTF-8</encoding>
    </configuration>
</plugin>

<resources/>标签下指定要替换占位符的资源:

<resource>
    <filtering>true</filtering>
    <directory>src/main/resources</directory>
    <includes>
        <include>jsf/jsf-consumer.xml</include>
    </includes>
</resource>

指定占位符的properties文件:

<filters>
    <filter>src/main/resources/config/jsf-config-${jsfConfigEnv}.properties</filter>
</filters>

文件定义如下:

经过maven再次编译,可以看到,对应的占位符被替换为<filters>定义的相应环境的properties文件的值了:

配置setting.xml

nexus私服不同于中央仓库,大部分是需要进行登陆验证的,所以需要先在setting.xml配置nexus私服的用户名和密码:

需要配置两个不同版本的仓库,releases用来上传正式版本,即线上要使用的版本,snapshots是用于测试的版本,可能会经常修改:

<servers>
    <server>
        <id>nexus-releases</id>
        <username>admin</username>
        <password>admin123</password>
    </server>
    <server>
        <id>nexus-snapshots</id>
        <username>admin</username>
        <password>admin123</password>
    </server>
</servers>

发布jar到私服

方式一:直接使用deploy命令

windows下使用^给命令换行,linux下使用反斜杠\换行:

mvn deploy:deploy-file ^
-DgroupId=me.feathers.demo ^
-DartifactId=demo ^
-Dversion=1.0SNAPSHOT ^
-Dpackaging=jar ^
-Dfile=.\demo-1.0-SNAPSHOT.jar ^
-Durl=http://127.0.0.1:8081/nexus/content/repositories/snapshots ^
-DrepositoryId=nexus-snapshots

repositoryId 指定 setting.xml和pom.xml中私服的id。

方式二:在maven项目内使用 mvn deploy

该种方式需要在pom.xml种配置distributionManagement元素:

<distributionManagement>
    <repository>
        <!--需要对应setting.xml种server的id-->
        <id>nexus-releases</id>
        <url>
            http://127.0.0.1:8081/nexus/content/repositories/releases/
        </url>
    </repository>
    <snapshotRepository>
        <id>nexus-snapshots</id>
        <url>
            http://127.0.0.1:8081/nexus/content/repositories/snapshots/
        </url>
    </snapshotRepository>
</distributionManagement>

然后使用 mvn reploy 命令就可以将jar放到私服中了。

方式三:使用页面操作上传

最后更新于