一、依赖包查询
所有的依赖都是通过坐标来进行存储的(GAV groupId artifactId version
)。在上一节中我们创建了一个小的示例工程(user-core
),那下面我们以此示例进行说明。对于工程中需要用到的依赖我们可以上网去查询,查询地址有:
http://mvnrepository.com/
-
http://www.sonatype.org/
默认的中央仓库是上面一个,如果我们此仓库由于网络原因连接不上,那么我们可以按照下面的方式配置中央仓库,只需要将地址换掉即可(https://nexus.sourcesense.com/nexus/content/respositories/public
):
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
比如本示例中需要用到hibernate模块,我们直接搜索出hibernate的配置信息:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
当然我们还可以选择其他版本。然后我们将此配置信息直接加入到pom.xml
文件中即可。maven会自动去仓库中下载。
此时的配置文件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>org.konghao.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<name>user-core</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
二、user-core模块
对于项目中要发布的资源文件应该放在一个资源文件夹
src/main/resources
(在/user-core/src/main/java
下),而测试用到的资源文件应该放在/user-core/src/test/java
下的src/test/resources
中。
我们拷贝一份配置文件:hibernate.cfg.xml
和log4j.properties
到此文件夹中。然后我们还需要加入log4j的配置。下面给出两个配置文件的内容:
hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 下面这些字符串在.property配置文件中都能查到 -->
<property name="hibernate.connection.url">
<![CDATA[jdbc:mysql://localhost:3305/maven_user?useUnicode=true&characterEncoding=utf8]]>
</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">walp1314</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property><!-- 这是一个适配器 -->
<property name="hibernate.show_sql">true</property><!-- 显示sql语句,默认是false -->
<property name="hbm2ddl.auto">update</property>
<!-- 设置方言 -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<mapping class="org.konghao.vo.User"/>
</session-factory>
</hibernate-configuration>
log4j.properties
### direct log messages to stdout ###
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### direct messages to file hibernate.log ###
#log4j.appender.file=org.apache.log4j.FileAppender
#log4j.appender.file.File=hibernate.log
#log4j.appender.file.layout=org.apache.log4j.PatternLayout
#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
### set log levels - for more verbose logging change 'info' to 'debug' ###
log4j.rootLogger=warn, stdout
#log4j.logger.org.hibernate=info
#log4j.logger.org.hibernate=debug
### log HQL query parser activity
#log4j.logger.org.hibernate.hql.ast.AST=debug
### log just the SQL
#log4j.logger.org.hibernate.SQL=debug
### log JDBC bind parameters ###
#log4j.logger.org.hibernate.type=info
#log4j.logger.org.hibernate.type=debug
### log schema export/update ###
log4j.logger.org.hibernate.tool.hbm2ddl=debug
### log HQL parse trees
#log4j.logger.org.hibernate.hql=debug
### log cache activity ###
#log4j.logger.org.hibernate.cache=debug
### log transaction activity
#log4j.logger.org.hibernate.transaction=debug
### log JDBC resource acquisition
#log4j.logger.org.hibernate.jdbc=debug
### enable the following line if you want to track down connection ###
### leakages when using DriverManagerConnectionProvider ###
#log4j.logger.org.hibernate.connection.DriverManagerConnectionProvider=trace
注意:对于log4j.properties
,一般都不需要太大的改动,以后可以直接用。
- 新建一个数据库
maven_user
,然后直接新建一个实体类User.java
:
package org.konghao.vo;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="t_user")
public class User {
private int id;
private String username;
private String nickname;
private String email;
private String password;
@Id
@GeneratedValue
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
注意:这里我们只是一个简单的例子,在运行的过程中会自动生成相关的数据库表。同时这里很显然要加入log4j
和mysql驱动
的相关配置。此时的配置文件为:
<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>org.konghao.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>user-core</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.1.0.Final</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
</dependencies>
</project>
- 测试
我们在src/test/java
下新建一个测试类TestUser.java
package org.konghao.vo;
import org.hibernate.Session;
import org.junit.Assert;
import org.junit.Test;
import org.konghao.util.HibernateUtil;
public class TestUser {
@Test
public void testAdd(){
Session session = HibernateUtil.openSession();
session.beginTransaction();
User user = new User();
user.setUsername("admin");
user.setPassword("123");
user.setNickname("超级管理员");
user.setEmail("admin@admin.com");
session.save(user);
Assert.assertTrue(user.getId() > 0);//判断是否成功
session.getTransaction().commit();
}
}
同时这里还给出其他一些类,在src/main/java
下:
HibernateUtil.java
package org.konghao.util;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class HibernateUtil {
private static SessionFactory factory = null;
static {
factory = new Configuration().configure().buildSessionFactory();
}
public static Session openSession(){
return factory.openSession();
}
}
然后我们直接选中pom.xml
右键-->Run As-->Maven build
,输入clean test
就可以进行测试。
注意:MyEclipse中为我们提供了一些命令我们可以直接使用,如果没有想要的命令则可以利用上面这种方式输入命令进行运行。然后我们在数据库表中发现存入有数据表示测试成功了。然后我们需要打包安装,使用命令
clean install
,但是在测试一遍之后再执行的话需要将test中的相关代码注释掉,不然又要存入数据库表中相同的数据。
注意:这里如果出现了错误,可以在window-->preference-->java-->install JREs-->选择自己的jre然后点击edit
,在default vm arguments
中填入:-Dmaven.multiModuleProjectDirectory=$M2_HOME
打包完之后这个模块就算完成了。
三、user-log模块
我们再次新建一个maven项目模块,而此模块不需要依赖上面那个user-core模块,这里我们假设有一个类:
Log.java
package org.konghao.user.log;
import java.util.Date;
public class Log {
public static void log(String str){
System.out.println(new Date() + "---" + str);
}
}
配置文件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>org.konghao.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>user-log</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</project>
注意:这里我们只是做个试验。
四、user-dao模块
当然对于dao模块来说,当然就需要日志模块和user-core模块。我们需要将此两个模块的jar引入进来。
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>org.konghao.user</groupId>
<artifactId>user-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>user-dao</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
注意:加入配置之后我们发现hibernate的相关包也被引入进来了,这就是传递性依赖。而依赖传递主要是针对compile作用域。
注意:scope这个标签。如上,我们并没有加入scope,就表示这个包是依赖user-core
的编译范围,如果user-dao
中没有对junit的依赖,那么此时user-core
中的junit的包是不会被传递到user-dao
中的,即不会被传递。如果有加scope则表示测试范围,那么会将junit传递过来。
依赖的范围:
test:
测试的范围。也就是不会打如到包中。在编译和打包时都不会使用此依赖。
compile:
编译范围。就是在编译和打包时都会用到这个依赖。(默认)
provided:
在编译和测试的过程有效,在最后生成war包时不会加入,比如servlet的api,因为在服务器中有其api。
runtime:
运行范围。即在运行的时候依赖,在编译的时候不依赖。
import和system:
暂时不研究。-
传递的冲突
- (1)如果a依赖b1.0, 而c依赖b1.2, 而d依赖于a和c。此时在d的配置文件中先写的是a的依赖,那么d就依赖b1.0,反之则依赖b1.2。也就是谁先写就依赖谁。
- (2)如果a依赖b1.0, 而c依赖b1.2, 而d依赖于a和c, f依赖于d和c,如果路径长短不一致,那么就选择路径短的那个依赖,此处f就依赖于b1.2。也就是谁的路径短依赖谁。当然我们也可以控制使用那个版本,如下面的我们不想使用某个模块中的
log4j
,那么我们可以将其排除掉:
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
可以看到我们使用exclusions
和exclusion
将此模块中的log4j排除掉了。此时这个模块就会从其他模块而不是这个模块中去找log4j这个依赖。如果我们所有模块中的版本都不用,那么我们可以将其都去掉,然后自己单独写一个依赖。而单独写的依赖的优先级最高,不管其他模块有没有排除。
五、user-service模块
这里我们先给出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>org.konghao.user</groupId>
<artifactId>user-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>user-service</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-dao</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
暂时不添加任何类。
- 依赖的聚合问题
聚合问题就是如上面我们新建了好几个模块,那本别进行编译打包会很麻烦,所以这里我们需要将多个模块聚合起来。聚合我们可以使用两种方式:一种是在MyEclipse中新建一个maven工程(工程user-aggregation
),然后将不用的包和文件都删除,留下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>org.konghao.user</groupId>
<artifactId>user-aggregation</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<modules>
<module>../user-core</module>
<module>../user-log</module>
<module>../user-dao</module>
<module>../user-service</module>
</modules>
</project>
注意:这个工程只是用来方便我们将所有模块一起打包编译,其实只需要一个pom.xml
文件即可。可以看到我们只需要将四个模块配置进去,同时注意<packaging>
标签中必须为pom
。然后使用clean install
命令进行编译打包即可。当然我们也可以直接将此文件放在上面各模块的上一级目录中,然后手工进行编译,但是MyEclipse不支持。如果在工程上出现一个叉我们可以尝试选中工程右键-->Maven4MyEclipse-->Update Project
进行修正。
一般我们可以在<properties>
配置一些属性,例如:
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.10</junit.version>
</properties>
然后在下面配置junit的时候可以这样:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
- 继承问题
从上面这些模块中我们可以看到我们配置了很多重复的信息,于是我们可以使用继承进行解决。就是多个模块中的有些配置项目基本一样,我们可以建一个工程(工程user-parent
),和上面的聚合工程一样,在配置文件中:
<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>org.konghao.user</groupId>
<artifactId>user-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</project>
注意:*这里的packaging
属性也是pom
,同时我们可以将一些公共的配置放在此文件中,比如上面配置的内容,我们在其子模块中继承此模块就不需要再次配置上面这些重复的内容了。这里我们通过user-core
模块来进行说明:
<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>
<parent>
<groupId>org.konghao.user</groupId>
<artifactId>user-parent</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../user-parent/pom.xml</relativePath>
</parent>
<!-- <groupId>org.konghao.user</groupId> -->
<artifactId>user-dao</artifactId>
<!-- <version>0.0.1-SNAPSHOT</version> -->
<packaging>jar</packaging>
<name>user-dao</name>
<!-- <url>http://maven.apache.org</url> -->
<!-- <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> -->
<dependencies>
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-core</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.konghao.user</groupId>
<artifactId>user-log</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
可以看到对于打包方式不一样我们还是需要配置,但是对于一些属性我们是不需要进行配置的, 而父模块中我们配置了junit,而在子模块中配置就是
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- <version>4.10</version> -->
<scope>test</scope>
</dependency>
这样我们可以对一些重用的包统一在父模块中统一进行管理。但是这样有个问题,就是子模块会将父模块中的所有配置都继承下来,而如果几个子模块中的包有冲突就会出现问题。于是我们一般在父模块中这样对模块进行管理:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
</dependency>
</dependencies>
</dependencyManagement>
然后在子模块中我们进行引用即可:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<!-- <version>4.10</version> -->
<scope>test</scope>
</dependency>
其中对于版本统一交给父模块进行管理。我们可以将所有要用的包全部配置进来。