java构建xml参数_Java中使用XML创建EMAIL模板

邮件模板

让我们来看看邮件模板的格式。模板是XML文件,它包含一个根元素和一系列根的子元素。根元素是。必要的子元素是, , 和 。可选的子元素是 , , 和 。如果你使用过邮件系统,那么你可以推导出这些元素实际包含的内容。可选的元素有多个实例,所以你可以为每种类型的接收者指定多个地址。我待会会在描述消息处理的时候来解释运行机制。以下是一个模板文件的例子。

rafe@rafe.us

someone@example.com

someoneelse@example.com

rafe@rafe.us

This is the subject

可定制的模板

属性文件的一个有用的特性是你可以使用MessageFormat 类用动态传入的值替代属性文件里的被指定参数。比如说,如果你需要在属性文件里指定errors,其中一个errors是file not found, 你可以这样写:

file.not.found.error=Error, could not find file {0}.

然后,在运行时刻,你这样使用MessageFormat:

ResourceBundle bundle = ResourceBundle.getBundle(

"MyProperties", currentLocale);

Object[] arguments    = { "some_file.txt" };

String newString      = MessageFormat.format(

bundle.getString("file.not.found.error"), arguments);

最后,newString 将包含Error, could not find file some_file.txt.我在这个系统里加入了类似的灵活性。 可以格式化所有的字符串,所以你可以在邮件模版的subject 和body元素里内嵌在属性文件使用的同样的令牌。

在某种情形下,你希望在发送邮件的时候插入个人化的信息。比如,你希望在邮件内容里或者订单的内容里包含收件人的姓。本系统使用MessageFormat 来处理邮件模版的内容和主题,从而解决这个问题。处理内容和主题的时候只使用一个参数数组。这样主题里可以包含令牌{0}, {2}, {3},  内容可以包含令牌{0}, {1}, {4} 。我之所以采用这种方式是因为在很多情形下主题和内容使用相同的参数,同时这种方式也简化了传递给EmailSender所需要的参数。

处理模版

创建完模版,下一步所要做的就是处理它。我们知道,现在有很多的XML处理包可供选择。Commons Digester是Jakarta的公共项目,最初是为了在Struts项目中快速方便的解析Struts的的配置文件而产生的。它提供了从XML文件里的元素到使用类似于XPath  语法的数据结构的映射。 好处在于为了从        XML文件里得到某个元素你不必用SAX一个节点一个节点的解析,也不必使用DOM处理树状数据结构。

下面这个方法从XML文件里读取数据,然后把数据拷贝到EmailTemplate对象中。

public static EmailTemplate getEmailTemplate(InputStream aStream)

{

Digester digester = new Digester();

digester.setValidating(false);

digester.addObjectCreate("email", EmailTemplate.class);

digester.addBeanPropertySetter("email/subject", "subject");

digester.addBeanPropertySetter("email/body", "body");

digester.addBeanPropertySetter("email/from", "from");

digester.addCallMethod("email/to", "addTo", 0);

digester.addCallMethod("email/cc", "addCc", 0);

digester.addCallMethod("email/bcc", "addBcc", 0);

try

{

return (EmailTemplate)digester.parse(aStream);

}

catch (IOException e)

{

logger.error("Error: ", e);

return null;

}

catch (SAXException e)

{

logger.error("Error: ", e);

return null;

}

}

让我们来逐行研究这段代码。Commons Digester工作的原理是由你来指定解析文件的一些规则。因为没有规范邮件模版的DTD文件,所以在指定处理规则之前,我将validating flag设定为false。开始处理文件的时候,我实例化Digester对象然后调用方法建立数据映射规则。首先,我调用addObjectCreate()方法来建立创建EmailTemplate对象的规则。email是XML模版文件的根元素。因此模版文件和EmailTemplate 对象一一对应。

我使用addBeanPropertySetter()来处理在模版文件中只出现一次的元素。这个方法有两个参数,元素的路径和要调用的赋值方法。在第一次调用的时候,我指定在文件中符合email/subject 模式的元素应该赋值给EmailTemplate 类的subject 。我们用 “/”来描速XML文件的内嵌关系。在这个例子中,符合subject模式的元素是email 子元素。为了提供更多的灵活性我们可以使用Wildcards。参考Commons Digester的JavaDoc 你可以了解详细的模式的构成方式。

使用赋值方法处理在模版文件中出现多次的元素是不可行的。我们使用addCallMethod()来处理这种情形,这个方法从元素中取值并且调用指定的方法。我使用这个方法有三个参数的版本,它们是:匹配的模式,调用的方法,调用方法所使用的参数数量。在例子的三种情形中第三个参数都是0,说明符合模式的元素是调用方法的唯一参数。在EmailTemplate类中我定义了三个方法:addTo(), addCc(),  addBcc(),这三个方法将模版文件中的收件人列表加入到模版类的收件人集合中。

邮件元素的六种类型的子元素的规则都被指定好之后,我开始解析这个文件。在这个例子中, 我传入getEmailTemplate 方法的输入参数InputStream 。parse方法可以解析File,SAX InputSource, InputStream,  Reader, 目标文件的URI。我使用InputStream。 由调用这个方法的代码取得XML文件并且把它转化为InputStream 。为了让这个方法更加通用,我可以用Object作为参数,并且在方法内部使用instanceof 来确定参数的类型,再用相应的方式来处理。

方法parse 抛出IOException 或者SAXException。把这些异常传给Log4J,由它来处理,返回null. 如果没有异常抛出, 将返回由Digester创建的EmailTemplate对象。

EmailTemplate类剩下的部分

getEmailTemplate()方法是类EmailTemplate的核心。其他的部分是一些属性值和一些辅助性的方法。有3个String 类型的属性值:内容,主题,寄件人地址,3个ArrayList属性值:to, CC, BCC 列表,这3个值都以String作为基本元素。还有相应的get,set和加入集合的方法。还有3个附加的方便的方法:getToAddresses(), getCcAddresses(), 和 getBccAddresses()。JavaMail接口需要InternetAddress 数组作为地址集合的参数,这些方法可以把对象的String数组转化为JavaMail接口需要的数组形式。

类EmailSender

当模版文件被解析成EmailTemplate对象,下一步就是发送邮件信息。EmailSender 类包含一个静态的,重载的方法-sendEmail()。 这个方法可以通过很多种方式调用,所有的方式都是对下面这个完全参数方法的一个引用:

public static void sendEmail(

String aTo,

EmailTemplate aTemplate,

String[] aArgs)

参数不需要过多的解释。第一个是邮件的发送地址。你可以在邮件模版里指定很多接收人地址,但是在运行时刻,大多数情况下,系统只需要一个接收人。比如说,你发送一封密码提醒的邮件,只需要指定申请密码的用户的邮件地址。在邮件模版里指定的收件人列表在某种情况下适用:作为测试,系统需要发送邮件到特定收件人列表或者发送时需要包含特定收件人列表。比如说,假设一个系统每当订单提交的时候需要通过一封邮件触发一个workflow,在这种情形下邮件模版种特定的接收人地址是有意义的。

第二个参数是EmailTemplate自身。第三个参数是MessageFormat解析邮件主题和内容所需要的参数集。由调用这个方法的代码来创建个性化邮件模版所需要的信息数组。也有其他申明的方法简化了这个方法的调用(所以你可以在不指定收件人,或者在没有参数的情况下调用这个方法)。

方法内部由使用JavaMail发送邮件所需要的一系列调用组成。我觉得使用JavaMail会造成许多冗余,我们来具体看一下。首先,我要通过检测来确定EmailTemplate是否为空。如果为空,什么都不能做。设定的第一步是使用SMTP server的设置创建一个Properties对象(Hashtable)。我把SMTP server的设置设定在 文件里,所以我把这个值从属性文件里读出来然后放到我创建的properties对象里去。

接着我创建了一个JavaMail Session 对象传入Properties 对象。Session对象在创建MimeMessage对象的时候需要。这个是我待会要做的。然后我将From:的值指定到传入参数EmailTemplate对象的相应栏位。下一步我把To:的值设定到我构建的消息中。这里会有一些技巧,因为用户可以传入To: 地址,同时邮件模版里也包含一些To:地址。问题在于JavaMail 喜欢使用数组描速地址列表,所以由我来决定接收人列表的有多大,然后构建传入的参数。

因为CC: BCC:的地址必须在模版里指定,我们可以直接来处理它们。我使用EmailTemplate类里的方法把其他的收件人加入到消息里。就像我开始提到的,我使用MessageFormat解析处理邮件主题和内容的方法所需要的参数集。做完之后,我把新的主题拷贝到消息主体里。如此处理消息的内容。剩下的就是调用Transport.send()并且传入MimeMessage 对象。

使用这个系统

我刚才已经解释了系统的运作原理,现在我来解释如何通过 servlet来使用它,在其他程序里调用的方式是类似的。以下是代码:

// Grab the email template.

InputStream template =

getServlet()

.getServletConfig()

.getServletContext()

.getResourceAsStream(

"/WEB-INF/email/registrationNotification.xml");

EmailTemplate notification = EmailTemplate.getEmailTemplate(template);

// Create the section of the email containing the actual user data.

String[] args = { "Rafe" };

EmailSender.sendEmail("rafe@rafe.us", notification, args);

使用这个系统的第一步是把你的XML模版文件转化成InputStream。 因为我使用的是servlet,我从ServletContext取得这个文件。当然还有其他的方式取得这个文件,但是在servlet环境里,这种方式很好用。我只用把InputStream 传给刚才所描述的EmailTemplate.getEmailTemplate()方法就可以了。下一步,建立个性化邮件所需要的参数数组,然后调用方法EmailSender.sendEmail()。

更多

这个系统还可以更多的优化,有两个比较明显的需要改善的地方:系统应该同时支持纯文本和HTML;支持附件。创建这种类型的信息需要使用类型javax.mail.MimeMultipart。还有在何处存储附件和如何指定附件的问题。在我的系统里,我没有在模版文件里处理附件,因为我的附件是在邮件发送的时候创建的。

Rafe Colburn 是一个Java开发工程师,同时也是一名计算机图书的作者,他使用过Perl,CGI, HTML, JAVA

posted on 2006-02-28 09:53 黑咖啡 阅读(469) 评论(3)  编辑  收藏 所属分类: tec

465e1e664303d22c5f3f702b35dcadec.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442576.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 多目录 编译jar_javac编译多个包下的、依赖其他jar包的java文件

问题:多个*.java文件编译*.java文件依赖其他的jar包如下文件结构:F:\jar_prachild--child01--MyChild.java--child02--MyChild.javaparent--MyParent.javaMyParent.javapackage parent;public class MyParent{public void show(){System.out.println(&qu…

java11创建项目_2019-04-11 使用IDEA创建SpringBoot项目

一. 使用IDEA新建项目根据需要选择starter这样使用IDEA搭建的一个SpringBoot项目就可以了。同样可以通过https://start.spring.io/构建。二. 结构分析1.Springboot01Application:运行Springboot01Application就可以启动Spring Boot工程。2. pom.xml中则配置好了选中的starter的…

微博php sdk,php sdk微博第三方授权登入简单使用

简单说一下OAuth协议:OAUTH是一种开放的协议,为桌面、手机或web应用提供了一种简单的,标准的方式去访问需要用户授权的API服务。下面我们去微博开发者平台登入微博。如图填写信息:网站接入->创建新应用填写信息后可以拿到微博给…

php xml数据拼接,在PHP中合并XML文件

我有2个文件,1.xml并且2.xml两个文件的结构相似,我想拥有一个。我尝试了许多解决方案,但只有错误-坦白地说,我不知道这些脚本是如何工作的。1.xml:1Title 1Author 1...2.xml:190Title 190Author 190...我想…

java中document解析jsp,JSP基于dom解析xml实例详解

本文实例讲述了JSP基于dom解析xml的方法。分享给大家供大家参考,具体如下:初次学习用dom操作xml文件,有很多不足之处,牛人多给点建议,练习时我没对中文做乱码处理,也没做验证哦!O(∩_∩)O~实体类…

php导出excel不完整,急:php导出excel时,因数据比较多,经常导出不完整就结束了【php系统数据导出excel表格】...

急:php导出excel时,因数据比较多,经常导出不完整就结束了设置超在服务器上设置也可以,在当前文件写代码也可以服务器上找到php安装下的php.ini找到max_execution_time这句,将值改为你想要的时间,或者该为0表…

php禁用eval,zp blog

最新版的suhosin需要php版本大于5.4,对于5.4以下版本则需要安装补丁,尴尬之处在于安装补丁需要重新编译PHP并安装…… 总感觉莫名的不好干货:1、suhosin-0.9.36版本可以支持PHP5.3 且不用安装补丁2、安装步骤wget https://download.suhosin.…

php 堵塞 消息队列,PHP的并发处理

PHP如何处理并发什么是进程、线程、协程进程 Process计算机中的程序关于某数据集合上的一次运行活动,“一个执行中的程序”系统进行资源分配和调度的基本单位三态模型:多道程序系统中,进程在处理器上交替运行,状态不断地发生变化运…

php中节点值怎么获取,php – 节点更新:获取旧值

我正在使用nodeapi更新更新节点,但是我需要在幕后进行更多操作,这需要我知道字段的旧值/是否有一种方法可以在覆盖之前获取字段的旧值. 最佳答案 编辑hook_nodeapi()只对新的$node对象起作用,所以我之前的回答对你没用.相反,您需要在提交时访问节点.为此,您需要注册自己的提交处…

php 购物车封装代码,PHP中封装Redis购物车功能

// 服务层namespace Common\Service;use Vendor\Func\Red;class CartService extends CommonService {protected $redis;protected $pre_key;public function __construct(){parent::__construct();$this->redis Red::create();$this->pre_key C(USER.CART).C(APPID).:…

matlab pca和逆pca函数,matlab_PCA,训练集与测试集分开,原理和用法

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼PCA基本流程:1、训练集矩阵算协方差矩阵A;2、算协方差矩阵特征值与特征向量;3、按特征值的大小排列特征矩阵,得B,对应的特征值(按从大到小排列)组成向量a;4、A*B得到去关联的新矩阵C,…

w3cschool php 调整图片尺寸,PHP_php修改上传图片尺寸的方法,本文实例讲述了php修改上传图 - phpStudy...

php修改上传图片尺寸的方法本文实例讲述了php修改上传图片尺寸的方法。分享给大家供大家参考。具体实现方法如下:// This is the temporary file created by PHP$uploadedfile $_FILES[uploadfile][tmp_name];// Create an Image from it so we can do the resize$…

matlab频域低通滤波程序,低通频域滤波器在Matlab中的设计与实现.pdf

低通频域滤波器在Matlab中的设计与实现’ … … … … … ’ ’实用第一..智‘‘慧密集. . . . . . . . … … . . . … &…

matlab做比例积分微分控制,PID控制器的微积分分析matlab代码

PID 控制器由比例环节(Proportional)、积分环节(Integral )和微分环节(Differential )组成,连续PID 控制器的一般形式:dt de K d e K t e K t u D tI p )()()()()(0τττ? 一、比例控制及性能分析比例控制器的传递函数为:p p K s G )( 例题…

php引用对象方法吗,在PHP中引用容器对象的方法?

您必须修改代码才能提供关系.在OOP中,我们称之为aggregation.假设PHP 4,以及“一系列条形图”的想法class foo {var $bars array();function __construct() {"Foo Exists!";}function magic_bullet($id) {switch($id) {case 1:echo "There is no spoon! "…

数据合并计算php,各位大神,求助如果用VBA实现以下数据合并以及数量计算

Option ExplicitModuleName"模块1"Dim aData, dic As Object, aResSub start()Dim i&, n&, aTmp, minNum, maxNumDim spNum&, strData, id, numaData Range("a1").CurrentRegionSet dic CreateObject("Scripting.Dictionary")For …

python执行文件函数,python如何运行函数

运行Python的函数,只需要调用函数名,在传递参数就可以,不必关心函数体内部的代码块。函数是带名字的代码块,用于完成具体的工作需要在程序中多次执行同一项任务时,你无需反复编写完成该任务的代码,而只需调…

php小白书,php小白的自学第一天

虽然我还没有学会Python,但是已经开学了……然后老师要验收以php编写的网页……(wdnmd )这两天先把这个网页设计处理了,Python也会学,Linux还没开始,web更是啥也不会……谁再和我说大学比高中轻松我跟他拼命(听说只要先熟悉了HTML…

linux配置文件为yum,yum的配置文件说明

1、网上的可供yum的链接,要求里面有repodata目录,该目录就是分析 RPM 软体后所产生的软体属性相依资料放置处。2、配置文件:/etc/yum.repos.d/CentOS-Base.repo,也可以此目录下建别的以.repo后缀的文件就行[base]:代表…

linux的命令窗口,(翻译)Linux命令行(二)

文件和目录操作cd /home 进入/home目录cd .. 返回上一层目录cd ../.. 返回上两层目录cd 回到用户目录cd ~utente 回到用户目录cd - 后退到刚才目录pwd …