- 如果使用的是Eclipse简单创建了Maven项目,maven中的JDK只是被Eclipse简单配置的,这样的配置,是没有任何实际意义的,在真正使用中,这样的配置会被Maven是会被所忽略的.
- 如果要使用开发框架,例如:Spring于MyBatis,这个时候往往需要大量的*.xml文件,此时的文件回报存在resources目录之中,而后在运行时会保存到classes目录之中.
- 而一个项目被使用会存在以下几种情况
- 开发者使用:使用的是开发者自己的本人电脑
- 集中地测试:
- 线上产品环境:需要围棋更换为公网的相关配置
- java开发的领域上所有的开发包的版本是一件非常头疼的问题, 当一个pom.xml文件非常庞大的时候,如何进行版本更换.
- 项目开发完成之后往往需要将其打包为*.jar和*.war文件
- Eclipse为Maven的简单的配置只是一个临时的配置,如果要想在真是的开发环境中,去使用Maven,那么就需要对pom.xml文件进行配置,也就是说这个pom.xml文件不但大只是一个依赖包的关系,包括插件等等项.
定义环境属性
- 所谓的环境属性相当于是在pom.xml文件里面定义一些基本的变量信息,例如将项目名称,版本编号,相关属性都作为变量进行整体的声明,这样对整个的开发程序都可以利用变量的引用实现内容的变更.
- 传统的pom.xml文件引入配置问题
- 如果直接将所有的maven依赖程序库复制到pom.xml文件中,当pom.xml文件中的jar包依赖越来越多的时候,就会出现难以维护的问题.
- 建议定义全局属性来进行相关内容的控制:
- 在pom.xml文件中的<properties>分支中添加全局属性
<properties>
<!-- 定义junit的jar包的版本-->
<junit.version>4.12</junit.version>
<!-- 定义spring的jar包版本-->
<spring.version>4.2.5.RELEASE</spring.version>
</properties>
- 引用全局属性:在向pom.xml文件中添加依赖包引用的时候,版本使用全局属性控制
- 使用全局属性格式为"${标签名称}
<!--junit开发包引用 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--spring开发包引用 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
- 保存pom.xml文件之后,就会更换对应的开发包
- 如果将一些公共的版本信息或是一些目录信息都设置为全局环境属性,这样对于日后的项目维护会非常方便.
- 以后要修改开发包版本只需要修改全局属性即可.
插件配置
- pom.xml除了可以配置一些jar包的依赖管理之外,还可以配置一些插件,例如对项目的打包,编译等插件
- 修改pom.xml文件,添加编译插件
- 插件定义在pom.xml文件中的<build>标签中
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source><!-- 源代码使用的开发版本 -->
<target>1.8</target><!-- 需要生成的目标class文件的编译版本 -->
<encode>utf-8</encode>
</configuration>
</plugin>
</plugins>
</build>
- 虽然已经为项目配置好了插件,但是这个时候插件没有实际的效果,如果要让配置项起作用,需要让项目更新
- 随后可以直接通过package进行程序的打包处理,项目右键选择 [Run As]–>[maven build]
- 然后在goals中输入"package"
- 点击 Run 开始打包
- 此时得到的是项目编译后的可执行文件"*.class"文件
- 很多的时候会发现在一些开源项目的时候,除了有*.jar文件之外,还会发布源代码,那么如果现在要想实现源代码的输出配置,那么就可以继续使用一个插件:
- 源码打包插件,打包之后可以得到项目的*.java源代码文件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <!-- 源码打包插件 -->
<configuration>
<encoding>utf-8</encoding>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
- 执行打包处理,打包之后会自动在target生成源文件,使用压缩文件管理器打开 Test-source.jar文件 就可以看到源代码
- 实际上也可以在运行的时候生成相关的程序文档,在执行的时候使用:javadoc:javadoc,前提是需要有文档注释
- 定义一个类
package mao.shu;
/**
* 该类描述一个用户的基本信息,以及定义了取得这些基本信息的getter方法,和设置基本信息的setter方法
* 其中基本信息为:
* name:用户名
* age:用户年龄
* sex:用户性别
* id:用户注册的唯一id
* password:用户登录时使用的登录密码,改密码使用的是MD5加密方式
* email:用户注册时填写的电子邮箱
* city:用户所在的城市
* job:用户的职业信息
* @author Xiemaoshu
*
*/
public class admin {
private String name;
private int age;
private String sex;
private String id;
private String password;
private String email;
private String city;
private String job;
//省略get和set方法
}
- 进行文档的生成,在执行的时候重新设置执行项
- 此时实际上会通过网络下载一些支持的程序包
- 得到的doc文档
- 此时的doc文档是以文件目录形式完成的,而很多的时候都会以*.jar形式文件的形式完成,所以这种情况下如果希望继续以打包的形式来实现输出,继续配置一个文档插件
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<encode>${project.build.sourceEncoding}</encode>
<executions>
<execution>
<id>javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</configuration>
</plugin>
- 执行 package 打包项目
- 得到的javadoc.jar文件
- 以压缩文件打开jar文件
依赖包管理
- 对于Maven项目而言,依赖包是核心所在,所有的开发项目都需要依赖包配置,但是对依赖包也需要注意两点问题:包的作用域,包的排除.
包的作用域
- 在进行WEB项目开发的时候,往往会将项目打包为一个*.war文件,这个文件中有一个lib目录保存所有的程序开发包文件,于是对一些重要的开发包那么需要进行保存,如果不需要的开发包则不希望保存到目录之中
- 例如junit往往只在测试的时候使用,而实际项目中不需要使用
- 为观察作用域的问题,首先建立一个新的web项目
- 建立一个web.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
id="WebApp_ID" version="3.0">
<display-name>MyWeb</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
</web-app>
- 编写项目中pom.xml文件
<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>mao.shu</groupId>
<artifactId>MyWeb</artifactId>
<packaging>jar</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Test Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<!-- 定义junit的jar包的版本-->
<junit.version>4.0</junit.version>
<!-- 定义spring的jar包版本-->
<spring.version>4.2.5.RELEASE</spring.version>
<jdk.version>1.8</jdk.version>
<project.encoding>UTF-8</project.encoding>
<servlet.version>4.0.0</servlet.version>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
<!--junit开发包引用 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<!--spring开发包引用 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
<build>
<finalName>Test</finalName>
<plugins>
<!--编译插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source><!-- 源代码使用的开发版本 -->
<target>1.8</target><!-- 需要生成的目标class文件的编译版本 -->
<encode>utf-8</encode>
</configuration>
</plugin>
<!-- 源码打包插件 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId> <!-- 源码打包插件 -->
<configuration>
<encoding>utf-8</encoding>
</configuration>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- javadoc插件-->
<plugin> <!-- 定义其中的一个插件 -->
<groupId>org.apache.maven.plugins</groupId> <!-- 定义插件的组织信息 -->
<artifactId>maven-javadoc-plugin</artifactId> <!-- 要使用的是编译插件 -->
<configuration>
<encode>utf-8</encode>
</configuration>
<executions> <!-- 进行执行的配置 -->
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 随后观察两个依赖包的定义情况
- junit开发包的maven引用定义
<!--junit开发包引用 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
- 而servlet的开发包的maven定义如下
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>compile</scope>
</dependency>
- 可以发现这个两个开发包maven定义中最大区别在于<scope>标签的内容不一致
- 而scope就属于开发包的作用域,当前的junit由于只是一个测试使用环境下,所以使用了一个test作用域,而对于servlet为"compile"
- 进行项目的打包处理
- web项目选择打包为war后缀结尾的文件,打包结果的类型有pom.xml文件中的 <packaging>war</packaging> 标签控制
- 这个时候输出到lib目录下的只有compile范围的开发包,而test范围的没有输出到lib目录下
- 得到的MyWeb.war文件中的MyWeb.war\WEB-INF\lib 的jar文件
- 但是基本上大部分的情况下都会使用test和compile范围,但是有些开发包,例如:servlet程序包,这个开发包本身都会有Tomcat容器提供,所以这个包只在编译项目的时候有效
- 将servlet程序包的作用域设置为provided
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
- 这个时候maven在打包的时候不会将servlet进行打包处理
- 再次打包是项目中的lib目录
依赖包的排除
发现在进行包的依赖控制的时候往往会发现会有其他的依赖关系.
例如A项目依赖B包的时候,B包又依赖C包,但是我们的配置之中发现项目A也要去引用C包,这就有可能包的冲突,所以不希望B包自动依赖C包,这就需要对包的依赖排除
- 原始的配置,存在依赖关系
<!--spring开发包引用 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.2.4.RELEASE</version>
</dependency>
- 打包后的得到的结果,发现maven会自动将于spring-context包相关的开发包一起打包到项目中,这个时候如果pom.xml文件中如果已经配置有了 spring-core等开发包,那么就会出现开发包重复冲突的情况
- 实现包的排除处理:
- 在eclipse中打开pom.xml文件,选择 dependency hierarchy打开pom.xml文件
- 在开发包上右键选择 Exclude Maven Artifact 排除重复的开发包
- 所以这个时候整个项目之中存在一个公共的 spring-core包存在
- 我们自己在项目之中所建立的maven项目之间也是可以进行互相导入处理的,只需要按照pom.xml文件导入要求处理即可
- 例如之前的Test项目中的pom.xml文件中该项目的引用为
<groupId>mao.shu</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
- 使用这个引用配置到MyWeb项目中的pom.xml中
<dependency>
<groupId>mao.shu</groupId>
<artifactId>Test</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
继承关系
- 通过之前的演示i现在可以发现一个问题,几乎每一个pom.xml文件都需要进行如下几个配置
- 版本属性和
- 相关的插件
- 于是这个时候就可能产生这样一个问题,假设说现在这个项目非常庞大,并且这个项目中存在多个子项目.那么就会出现大量重复的属性定义和插件配置.
- 假设现在最大的父项目为mao.shu.base,这个项目需要提供一个公共的pom.xml文件,所以这个项目在搭建的时候,只搭建一个最基础的maven项目环境,而重点应该放在pom.xml文件中,由于该项目只是具备有一个pom.xml的功能,所以这个项目的类型就应该设置为pom
- 建立Base项目
- 将base/pom.xml文件中的<packing>标签改为pom
- 在开发中将所有的版本控制交给base完成.
- 编写base项目的pom.xml文件
<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>mao.shu</groupId>
<artifactId>Base</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<name>Base</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!-- 父项目中控制开发包的版本-->
<jdk.version>1.8</jdk.version>
<junit.version>4.0</junit.version>
<servlet.version>4.0</servlet.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- 此时所有的核心的配置选项都定义在父项目之中,而后每一个子项目都要引用这个父项目中的相关定义
- 假设现在创建一个Oa的子项目,这个时候依然创建一个maven项目,为了方便该项目直接创建为一个web项目,这个项目的版本一定要由父项目来决定
- 修改oa/pom.xml文件,实现继承关系
- 在oa/pom.xml文件中添加<parent>标签,在<parent>标签中添加父项目groupId和artifactId与version标签.
- 并且在子项目中需要使用描述父项目的位置关系,例如此时Base项目和Oa项目都在同一个目录下,那么,此时对于Oa项目来说,Base中的pom.xml文件的位置就是
<relativePath>../Base/pom.xml</relativePath>
<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">
<!-- 定义父项目-->
<parent>
<groupId>mao.shu</groupId>
<artifactId>Base</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../Base/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>mao.shu</groupId>
<artifactId>Oa</artifactId>
<packaging>war</packaging>
<version>0.0.1-SNAPSHOT</version>
<name>Oa Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>Oa</finalName>
</build>
</project>
- 相关的属性以及配置的插件都会自动通过父项目更新而来.所以在子项目中开发包的版本可以直接使用父项目所定义好的属性.
- 实际上在整个的父项目开发里面也提供有一下依赖包的管理问题,也就是说在父项目中直接导入好包.
- 在base/pom.xml文件里面定义好需要的开发包
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${servlet.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</dependencyManagement>
- 但是这个时候对于子项目而言还是需要继续导入开发包,但是不需要控制版本,发现现在在子项目中依然需要导入开发包,唯一的区别是不需要导入版本号了.
构建设置
- 在实际的开发过程之中,你一定有自己的开发环境, 而整个组编写完成之后一定会有一个内部的测试环境,等真正项目上线之后,那么一定会有一套线上的配置环境,所以从实际的开发来说,项目的开发基本环境配置一般会有三类,例如以数据库的链接为例:一般进行框架开发的时候(SSM,Spring+Shiro+MyBatis),一般都需要建立一系列的*.properties文件以保存相关的环境属性,于是针对于这样的配置文件,那么就有可能会分为三个:
- dev(开发者):数据库的链接地址为:192.168.101:3306dev
- beta(综合测试环境):数据库的链接地址为:192.168.250:3308beta
- produce(上线环境):数据库的链接地址为:10.5.6.78:3308product
- 那么一般情况下会准备三个配置文件,而后将项目打包为*.war文件之后,希望可以根据不同的环境选择不同的配置属性(*.properties)文件,所以这样的配置就称之为构建配置,而maven支持这样的动态打包操作
- 实现动态打包
- 建立一个保存所有配置文件的原目录src/main/profiles
- 在此目录之中分别创建三个子目录
- dev/conf:保存开发阶段的环境配置
- bate/conf:保存所有测试相关环境配置
- product/conf:保存所有的线上环境的资源配置
- 为了方便观察,在每一个文件夹下都需要有一个conf子文件夹,保存有相应的资源文件项.
- 此时已经提供了三组不同的开发环境的配置项,如果要想使用需要在pom.xml文件中进行相关的定义.
- dev的开发环境配置
- bate环境配置
- product环境配置
- 此时还不能够进行打包控制,需要将一个环境配置目录设置为元目录
- 因为在实际开发中开发环境使用最多的就是生成环境,所以将dev的目录设置为源代码的元代码目录
- 修改项目中的build path,选择Source ,选择add Folder
- 选择dev为源目录,也可以设置为其他的
- 一旦要接触到框架开发,会面临一个新的问题,就是框架之中需要编写大量的*.xml配置文件,例如SSM开发框架,那么就需要编写有spring,mybatis,shiro的相关配置项
- 在src/man/resources目录下建立一个config的子目录,而后在这个子目录下分别建立三个子目录,:spring,shiro,mybatis,分别保存不同的框架配置文件.
- 如果需要这些配置文件起作用,那么就需要修改pom.xml配置文件
- 为了更方便的维护,将资源文件的路径作为属性的方式出现
<properties>
<profiles.dir>src/mian/profiles</profiles.dir>
<resources.dir>src/main.resources</resources.dir>
</properties>
- 而后使用<profiles> 标签定义每一个环境变量的配置
<profiles>
<profile><!-- 描述出要使用的不同环境的配置文件-->
<id>dev</id><!-- 描述本配置文件的编号,一般于文件目录重名-->
<properties>
<!-- 描述配置项对应的路径-->
<profile.dir>${profiles.dir}/dev</profile.dir>
</properties>
<activation>
<!-- 如果没有指派profile编号,默认使用此配置-->
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>bate</id>
<properties>
<profile.dir>${profiles.dir}/bate</profile.dir>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<id>product</id>
<properties>
<profile.dir>${profiles.dir}/product</profile.dir>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
- 定义资源文件是否输出
<build>
<!-- 定义在打包的时候使用-->
<defaultGoal>package</defaultGoal>
<resources>
<resource>
<directory>${resources.dir}</directory>
<!-- 设置是否使用资源文件中的内容替换,源资源文件内容-->
<filtering>false</filtering>
</resource>
<resource>
<directory>${profile.dir}</directory>
<filtering>false</filtering>
</resource>
</resources>
</build>
- 配置完成之后对项目进行更新,随后为期打包处理
- 在运行Maven命令的时候,不填写Profiles 一栏中的内容,因为在设置配置文件的时候,定义了一个默认的配置文件"dev",所以即使没有填写Profiles 这一栏,也会默认执行"dev"的配置文件,进行打包处理
- 打包之后,得到的war文件中,会将配置文件保存到,WEB-INF/classes/目录下
- 查看conf/目录下的database.properties 文件中的内容
- 可以在运行maven时,设置不同的 Profiles 值,来选择不同的配置打包
- 在进行资源配置的时候还可以设置必须包含的内容和排除的内容
- 修改 resources标签中的内容
<resources>
<resource>
<directory>${resources.dir}</directory>
<filtering>false</filtering>
<!-- 明确表示不包含的文件后缀-->
<excludes>
<exclude>**/.*.properties</exclude>
</excludes>
</resource>
<resource>
<directory>${profile.dir}</directory>
<filtering>false</filtering>
</resource>
</resources>
- 定义明确包含的资源文件
<resources>
<resource>
<directory>${resources.dir}</directory>
<filtering>false</filtering>
<!-- 明确表示不包含的文件后缀-->
<excludes>
<exclude>**/.*.properties</exclude>
</excludes>
<!--定义明确要包含的资源文件 -->
<includes>
<include>**/.*.xml</include>
</includes>
</resource>
<resource>
<directory>${profile.dir}</directory>
<filtering>false</filtering>
</resource>
</resources>
- 在实际的开发之中,这样的包含处理和不包含处理实际意义不大,在项目中编写需要的内容.
- 最好的做法就是在项目中只编写需要的配置文件,如果不需要的配置文件就不要放到项目中
Maven生命周期
- 在整个的Maven里面可以发现所有的功能都是围绕着项目的开发包的来管理,程序的编译打包处理,但是在Maven中有生命周期.
- 在进行项目的发布的时候,所有的*.java程序会自动进行编译处理,所有的编译过程都是由Maven自己完成的.编译完成之后,会发现自动使用cn.main.test下的测试程序进行测试.
- 示例:在cn/main/test包中编写一个测试类
package mao.shu;
import org.junit.Test;
import junit.framework.TestCase;
public class TestTrue {
@Test
public void test(){
TestCase.assertEquals(true, true);
}
}
- 进行打包处理
- 可以发现在打包的过程之中,执行了该测试程序
- 我们大部分处理的时候都会采用简单的模式来完成,例如:可以设置一些:命令clean compile test package
- 虽然maven可以单独使用命令行方式完成,但是在开发过程之中,往往会使用大量的管理工具,例如git.svn等等等等,所以一般都会将开发工具集成到IED中,进行开发