用Java程序生成文本的捷径

2016-02-19 14:58 7 1 收藏

清醒时做事,糊涂时读书,大怒时睡觉,无聊时关注图老师为大家准备的精彩内容。下面为大家推荐用Java程序生成文本的捷径,无聊中的都看过来。

【 tulaoshi.com - 编程语言 】

  大多数程序都需要输出一些文本,比如邮件消息、HTML文件或控制台输出。但是,计算机本质上只能处理二进制数据,程序员必须让软件来生成可理解的文本。在这篇文章中,我要介绍的是在生成和输出文本时,为何使用模板引擎能够节省时间。你将了解模板的优点,如何针对不同的情形创建高效的模板。和System.println说再见!

  虽然程序员可以很轻松地编写出输出文字信息的代码(因为这毕竟是从Hello World范例学到的第一件事情),但通常而言,程序员不是写作或组织文字信息(如邮件)的最佳人选。因此,我们常常让市场部门或公关部门去做那些事情。但遗憾的是,即使对于最普通的邮件,编写者也常常依赖程序输出来完成任务。无论是对于邮件编写者还是程序员,这种合作方式都很容易带来误解和造成失误。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  请看一个例子:一个Java程序从某个数据源收集一些客户信息,通过email给公司的每一个客户发送帐户余额信息。下面是完成这个任务的Java程序(完整的示例程序代码可以从本文最后下载):

  

 for (int i=0; i
 {
   Customer customer = (Customer)customers.get(i);
   StringBuffer message = new StringBuffer();
   message.append ("尊敬的先生/女士: ");
   message.append (customer.getCustName());
   message.append ("n");
   message.append ("n");
   message.append ("您的帐户余额是 ");
   message.append (customer.getAccountTotal());
   message.append ("n");
   message.append ("n");
   message.append ("致礼!");
   message.append ("n");
   message.append ("某某装饰品公司");
   // 发送email
   mm.sendMail (customer.getFirstName(), customer.getEmail(),
     "Account", message.toString());
 }

  上面的例子可谓发送消息最差劲的方法之一。由于消息嵌入到了程序代码之中,如果没有程序员的帮助,其他人几乎不可能对消息进行编辑。同时,即使对于专业的程序员,如果他不了解代码,要进行编辑也很困难。如果你预见了这些麻烦,把代码写成下面这种形式:

  

 static public final String STR_HELLO="尊敬的先生/女士: ";
 static public final String STR_MESSAGE="您的帐户余额是 ";
 static public final String STR_BEY="致礼!n某某装饰品公司";

  如果说上述代码使得消息编辑更容易,那么这种帮助也不会很多。很难要求一个不搞程序设计的人理解static和final的含义。此外,如果要改变消息的结构,上面这种代码也不够灵活。例如,人们可能要求你在邮件消息中加入更多来自数据源的信息,这时,你就得修改构造邮件的代码,或许还要添加更多的static final String对象。

  模板简介

  从文本文件装入消息文本可以解决部分问题但不能提供动态内容,而这对于系统来说是很重要的。你需要有一种方法把动态内容插入到预先编写好的文本消息。但是,如果使用某种文本模板引擎,它就能够帮助你完成所有复杂的工作。

  模板引擎解决了把动态内容插入文本消息的问题。使用模板引擎时,我们不再把消息直接嵌入程序,而是创建一个包含文本内容的简单文本文件,称为文本模板。模板引擎解析文本模板,借助一些简单的模板指令,把动态内容插入模板输出结果。

  我选择的模板引擎是Jakarta Project的Velocity,但你可以任意选择其他许多模板引擎之一。Velocity和WebMacro或许是当前功能最丰富、最受欢迎的两个引擎,而且两者都按照源代码开放协议免费提供。虽然我在本文例子中使用Velocity,你可以方便地把这些例子移植到不同的模板引擎,只需遵照目标引擎的语法即可。

  我们来看看用Velocity完成的email程序例子。要编译和运行修改后的程序,你必须下载Velocity并把它加入到classpath。如果要让email部分也能正常运行,你还需要JavaMail。

  

 for (int i=0; i<customers.size(); i++)
 {
   Customer customer = (Customer)customers.get(i);
   // 创建一个环境,并加入所有的对象
   VelocityContext context = new VelocityContext();
   context.put ("CustName",customer.getCustName());
   context.put ("total", new Double (customer.getAccountTotal()));
   context.put ("customer", customer );
   // 解析模板,生成结果字符串
   StringWriter message = new StringWriter();
   template.merge(context, message);
   // 发送email
   mm.sendMail (customer.getFirstName(), customer.getEmail(),
     "Account", message.toString());
 }

本文示例代码或素材下载

  首先,你应该理解上面的Java源代码。这里我们不再象第一个例子那样生成文本,上面的代码引用一个称为Velocity模板的文本文件,然后把结果发送给收件人。Velocity模板可以是任何文本文件,但一般它包含一些用来插入动态内容的指令。

  和VelocityContext相关的部分是上述代码中最值得注意的地方。VelocityContext提供了Java程序和Velocity文本模板之间的连接,而Velocity文本模板可以由其他人来编写。在模板中,所有加入到VelocityContext的对象都可以通过put()方法第一个参数指定的名字访问。为了解其工作过程,请看下面的模板文件:

  

尊敬的先生/女士: $CustName
您的帐户余额是 $total
致礼!
某某装饰品公司

  Velocity引擎读取模板文件时,它直接输出文件中所有的文本,但以$字符开头的除外。$符号标识着一个位置,在模板的输出结果中,对象的值应该插入到$符号所指示的位置。例如,Java代码中有一个context.put ("CustName",customer.getCustName())语句,当Velocity模板引擎解析并输出模板的结果时,模板中所有出现$CustName的地方都将插入客户的名字;即,被加入到VelocityContext的对象的toString()方法返回值将替代Velocity变量(模板中以$开头的变量)。

  模板引擎中最强大、使用最频繁的功能之一是它通过内建的映像(Reflection)引擎查找对象信息的能力。这个映像引擎允许用一种方便的Java.类似的操作符,提取任意加入到VelocityContext的对象的任何公用方法的值,或对象的任意数据成员。映像引擎还带来了另外一个改进:快速引用JavaBean的属性。使用JavaBean属性的时候,我们可以忽略get方法和括号(欲知详细信息,请参考模板引擎的说明文档)。请看下面这个模板的例子。由于在前面的Java代码示例中,我把Customer对象加入到了VelocityContext,所以我可以把模板改写成下面这种形式:

  

尊敬的先生/女士: $customer.CustName
您的帐户余额是 $customer.AccountTotal
致礼!
某某装饰品公司

  除了替换变量之外,象Velocity和WebMacro这类高级引擎还能做其他许多事情。它们有用来比较和迭代的内建指令(尽管比较和迭代功能是两个模板引擎之间的共同点,但它们的语法差异很大,不能完全兼容。在选择模板引擎或者更换模板引擎时,务必注意这一点)。

  举一个例子。十二月份,你的老板想要向所有的客户发一个圣诞节问候的email。你可以把这个消息加入到模板,以后再删除它。但这样的话,你得在新年那一天上班工作,以便删除圣诞问候消息。

  一种更好的办法是指示模板何时显示圣诞问候消息。为此,你首先要把当前的月份加入到VelocityContext:

  

 int month = (new GregorianCalendar()).get(Calendar.MONTH);
 // 把month值加1,因为它从0开始计算
 context.put ("month", new Integer(month+1) );

  现在,你只需在模板中进行比较:

  

尊敬的先生/女士: $customer.CustName
您的帐户余额是 $customer.AccountTotal
致礼!
某某装饰品公司
#if ($month == 12)
祝您和您的家人圣诞节快乐!
#end

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/bianchengyuyan/)

  #if指令的作用很清楚:对一个逻辑表达式进行测试,从而决定是否在模板输出结果中包含该指令块内的内容。除了简单的等于比较之外,你还可以执行更复杂的比较,但这方面的功能都与特定的模板引擎密切关联,所以这里我不再介绍。

  迭代指令和#if指令一样简单。模板引擎支持迭代Java Collections Framework的任意实现,包括Array、List和Iterator。对于JDK 1.2或者更高版本,Java的Vector和ArrayList都实现了List接口,因此它们也适合在模板引擎的迭代指令中使用。

  假设我们现在不想输出帐户余额,而是想通过迭代遍历帐户的交易记录,输出详细的报表。Customer对象的getTransactions()方法(参见下载包中完整的示例代码)返回一个List对象,List对象包含零个或者多个Transaction对象。由于List属于Java Collections Framework的一部分,我们可以用#foreach指令迭代其内容。我们不用担心如何定型对象的类型映像引擎会为我们完成这个任务。从下面这个例子中,我们可以看出迭代的工作过程:

  

尊敬的先生/女士: $customer.CustName
#foreach ($transaction in $customer.Transactions)
$transaction.Description $transaction.Amount
#end
您的帐户余额是 $customer.AccountTotal
致礼!
某某装饰品公司

本文示例代码或素材下载

来源:http://www.tulaoshi.com/n/20160219/1608478.html

延伸阅读
public void frame_windowclose_windowClosing(WindowListener e){ this.close(); } ///////////////////////////////////////////////////////// public void text_mouseClicked(MouseEvent e){ if(e.getModifiers()==InputEvent.BUTTON3_MASK){ pop.show((Component)e.getSource(),e.getX(),e.getY()); } ...
用vc++写console程序时,整天对着黑纸白字的屏幕,感觉很郁闷吧?很多人想用CONIO.H/GRAPHICS.H中的一些函数来实现,却发现VC++根本没有这些头文件。当然了CONIO.H/GRAPHICS.H是BORLAND TC/BC专有的头文件,所以vc++中根本没有这些文件。把这两个头文件COPY过来,然后用??答案当然是否定的。其实VC++中也有相关的函数来实现console彩色文...
Ajax(即异步 JavaScript 和 XML)是一种 Web 应用程序开发的手段,它采用客户端脚本与 Web 服务器交换数据。所以,不必采用会中断交互的完整页面刷新,就可以动态地更新 Web 页面。使用 Ajax,可以创建更加丰富、更加动态的 Web 应用程序用户界面,其即时性与可用性甚至能够接近本机桌面应用程序。 Ajax 不是一项技术,而更像是一个 模式 —...
标签: Java JAVA基础
本技巧将向您讲述如何编写可通过代理访问因特网上的Web服务器的Java应用程序。在Java应用程序中加入代理支持只需额外编写几行代码,且不依赖任何安全性“漏洞”。 几乎所有的公司都十分关注保护自己的内部网络,以防黑客及入窃者。一种常见的安全措施是完全断开与因特网的连接。如果黑客们不能连接到您的任何一台机器,他们...
代码如下: package com.qhdstar.java.pdf; import java.awt.Color; import java.io.FileOutputStream; import com.lowagie.text.Chapter; import com.lowagie.text.Document; import com.lowagie.text.Font; import com.lowagie.text.FontFactory; import com.lowagie.text.PageSize; import com.lowagie.text.Paragraph; import com.lowag...

经验教程

25

收藏

8
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部