dependence
optional
如果需要做一个数据库组件,而且这个数据库组件需要支持多个数据库的话,应用服务不太可能同时使用多种不同的数据库,它只需要自己用到的数据库的驱动包就可以了。比如一个使用了 mysql 的服务,是没有必要引入 oracle 的驱动包的。这时候 optional 就派上用处了。optional 表示该依赖是可选的,意味着构建后,标记为 optional 的依赖是不会被一起打入 jar 包的,也不会发生依赖传递。这样不仅我们自己的组件端体积变小了,应用服务也解决了引入过多无用依赖的问题。
如果依赖没有带入,那么程序运行期间,会不会发生类找不到的问题?确实是这样的,实际上 optional 表示可选,它将选择权交给了上层应用服务。假如我的服务使用了 mysql,那么我就在服务自己的 pom.xml 中引入 mysql 的驱动包;如果用的是 oracle,同理也是自己引入 oracle 的驱动包,也就是按需使用。如果服务没有引入任何数据库驱动,那么最坏的情况应该是不会使用数据库相关的功能,而不是报错。
optional 更是一种规范,规范了以下行为:
optional 通常用于组件端应用,即一个 jar 包,而不是一个应用服务;
optional 的依赖不会一起被打包,不会经过依赖传递而引入上层应用服务中;
optional 的依赖,表示可选,及时没有该依赖,也不影响程序运行,这里需要程序进行一些额外的判断逻辑;比如Spring的@Condition注解
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>
开发生产配置文件切换
根据当前环境编译指定的配置文件
根据需要,可以将环境设置为以下几种:
在resources目录下,建立三个文件夹,分别存储不同环境下的配置文件:
定义三个配置,配置中定义了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放到私服中了。
方式三:使用页面操作上传
略