本文中将《Maven实战》中对坐标和依赖的定义展示给初学Maven的程序猿们,并加上书中实例展示,具体详细请购买《Maven实战》--许晓斌著,更加详细的学习Maven。
坐标详解
groupld:定义当前Maven项口隶属的实际项口。首先,Maven 项目和实际项目不一定是一对一的关系。比如SpringFramework这实际项目, 其对应的Maven项口会有很多,如spring-core、spring-context 等。这是由于Maven中模块的概念,因此,一个实际项目往往会被划分成很多模块。其次,groupld不应该对应项目隶属的组织成公同。原因很简单,一个组织下会有很多实际项目,如果groupld 只定义到组织级别,而后面我们会看到、arifactld 只能定义Maven项目(模块),那么实际项目这个层将难以定义。最后,groupld 的表示方式与Java包名的表示方式类似,通常与域名反向一一对应。 上例中,groupld 为ong. sonatype. nexus, ong sonatype 表示Sonatype公司建立的一个非盈利性组织,nexus 表示Nexus这实际项目,该groupld 与城名nerus sonatype. ong对应。
artifactld: 该元素定义实际项目中的一个Maven项目(模块),推荐的做法是使用实际项目名称作为artifactld的前级。比如上例中的artifaectld是nexus-indexer,使用了实际项目名nexus作为前级,这样做的好处是方便寻找实际构件。在默认情况下,Maven生成的构件,其文件名会以artifaetld作为开头,如nexus-indexer-2.0.0. jar,使用实际项目名称作为前缀之后,就能方便从一个lib文件夹中找到某个项目的组构件。考虑有5个项目,每个项目都有一个core模块,如果没有前级,我们会看到很多core-1.2. jar这样的文件,加上实际项目名前级之后,便能很容易区分foo-core-1.2. jar、bar-core-1. 2. jar......
version:该元素定义Maven项目当前所处的版本,如上例中nexus-indexer的版本是2.0.0。需要注意的是,Maven 定义了一套完整的版本规范,以及快照(SNAPSHOT)的概念。
packaging:该元素定义Maven项目的打包方式。首先,打包方式通常与所生成构件的文件扩展名对应,如上例中packaging为jar,最终的文件名为nexus-indexer-2.0.0. ar,面使用war打包方式的Maven项目,最终生成的构件会一个.war文件,不过这不是地对的。其次,打包方式会影响到构建的生命用期,比如jar打包和war打包会使用不同的命令。最后,当不定义packogne的时候,Maven会使用默认值jar。
上述4个元素中,goupld. arifaeld version 是必须定义的,packaging 是可选的(默认为jar)。
同时,项目构件的文件名是与坐标相对应的,一般的规则为 atifactld-version [ -classifi-er] . packaging, [-classifer] 表示可选。比如上例nexus-indexer的主构件为nexus-indexer-2.0.0. jar,附属构件有nexus-indexer-2.0.0-javadoc. jar。这里还要强调的一点是,packaging非一定与构件扩展名对应,比如packaging为maven-plugin的构件扩展名为jar.
依赖范围
compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依精范围的Meven依赖,对于编译、测试、运行三种classpath 都有效。典型的例子局spring-core,在编译、测试和运行的时候都需要使用该依赖。
test:测试依赖范围。使用此依赖范围的Maven依赖,只对于测试classpath有效,在编译主代码成者运行项目的使用时将无法使用此类依赖。典型的例子基JUnit,它只有在编译测试代码及运行测试的时候才需要。
provided:已提供依赖范围。使用此依赖范围的Maven依赖,对于编译和测试claerpath有效,但在运行时无效。典型的例子是servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要Maven重复地引入。
runtime:运行时依赖范围。使用此依赖范围的Maven依赖,对于测试和运行clapath有效,但在编译主代码时无效。典型的例子是JDBC驱动实现,项目主代码的编译只需要JDK提供的JDBC接口,只有在执行测试成者运行项目的时候才需要实现上述接口的具体JDBC驱动。
system:系统依赖范围。该依赖与三种casspath的关系,和provided依赖范围完全一致。但是,使用system范围的依顿时必须通过systemPath 元素显式地指定依赖文件的路径。由于此类依赖不是通过Maven 仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植,因此应该谨慎使用。systemPath 元素可以引用环境变量,如:
<dependency>
<groupId >javax.sql</groupId >
<artifactId>jdbe-stdext</artifactId>
<version>2.0 </version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
利用Maven实现邮件发送
文件结构
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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>com.feiyu.web</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>2.5.6</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail</artifactId>
<version>1.3.1b</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
一个很简单的接口AccountEmailService.java
package com.feiyu.account.email;
public interface AccountEmailService {
void sendMail(String to, String subject,String htmlText) throws AccountEmailException;
}
接口的实现类AccountEmailServiceImpl.java
package com.feiyu.account.email;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
public class AccountEmailServiceImpl implements AccountEmailService{
private JavaMailSender javaMailSender;
private String systemEmail;
public void sendMail(String to, String subject, String htmlText) throws AccountEmailException {
try{
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
messageHelper.setFrom(systemEmail);
messageHelper.setTo(to);
messageHelper.setSubject(subject);
messageHelper.setText(htmlText,true);
javaMailSender.send(mimeMessage);
} catch (MessagingException e) {
throw new AccountEmailException("Faild to send mail.", e);
}
}
public JavaMailSender getJavaMailSender() {
return javaMailSender;
}
public void setJavaMailSender(JavaMailSender javaMailSender) {
this.javaMailSender = javaMailSender;
}
public String getSystemEmail() {
return systemEmail;
}
public void setSystemEmail(String systemEmail) {
this.systemEmail = systemEmail;
}
}
异常捕获类AccountEmailException.java
package com.feiyu.account.email;
public class AccountEmailException
extends Exception
{
public AccountEmailException( String message )
{
super( message );
}
public AccountEmailException( String message, Throwable throwable )
{
super( message, throwable );
}
}
配置文件email.properties
email.protocol = smtps
email.host = smtps.qq.com
email.port = 456
email.username = [email protected]
email.password = your_password
email.auth = true
email.systemEmail = [email protected]
Spring配置文件email.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:email.properties" />
</bean>
<!--定义邮件服务器的一些配置、包括协议、端口、主机、用户名、密码,是否需要认证等属性-->
<bean id="javaMailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="protocol" value="${email.protocol}" />
<property name="host" value="${email.host}" />
<property name="port" value="${email.port}" />
<property name="username" value="${email.username}" />
<property name="password" value="${email.password}" />
<property name="javaMailProperties">
<props>
<prop key="mail.${email.protocol}.auth">${email.auth}</prop>
</props>
</property>
</bean>
<!--注入javaMailSender-->
<bean id="accountEmailService"
class="com.feiyu.account.email.AccountEmailServiceImpl">
<property name="javaMailSender" ref="javaMailSender" />
<property name="systemEmail" value="${email.systemEmail}" />
</bean>
</beans>
测试类AccountEmailServiceTest.java
package com.feiyu.account.email;
import static org.junit.Assert.*;
import javax.mail.Message;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.GreenMailUtil;
import com.icegreen.greenmail.util.ServerSetup;
public class AccountEmailServiceTest {
private GreenMail greenMail; // 使用GreenMail作为测试服务器
@Before
// Before注解表示会先于测试方法@Test执行
public void startMailServer() throws Exception {
greenMail = new GreenMail(ServerSetup.SMTP);
greenMail.setUser("[email protected]", "your_password"); // 创建邮件账户
greenMail.start(); // 启动邮件服务
}
@Test
public void testSendMail() throws Exception {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext(
"email.xml");
AccountEmailService accountEmailService = (AccountEmailService) classPathXmlApplicationContext
.getBean("accountEmailService");
String subject = "your_Test_subject"; //邮件主题
String htmlText = "<h3>your_content</h3>"; //邮件内容
accountEmailService.sendMail("[email protected]", subject, htmlText); // 发送
greenMail.waitForIncomingEmail(3000, 1); // 最多等待3s
Message[] msgs = greenMail.getReceivedMessages(); // 读取收到的邮件
assertEquals(1, msgs.length); // 检查数目
assertEquals(subject, msgs[0].getSubject());
assertEquals(htmlText, GreenMailUtil.getBody(msgs[0]).trim());
}
@After
public void stopMailServer()
throws Exception {
greenMail.stop(); //停止
}
}