(二)Maven的坐标和依赖&利用Maven实现邮件发送

本文中将《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();			//停止
    }
}

猜你喜欢

转载自blog.csdn.net/wfy2695766757/article/details/81204854