2 系统分析
2.1 需求分析
企业快信的作用是帮助企业解决企业内部、企业与外部沟通难、信息不能及时传播等问题。为此,企业快信系统需要提供邮件群发、短信群发等功能。通过对多数企业日常业务的考察、分析,并结合短信及邮件自身的特点,得出本系统要求具有以下功能。
用于管理客户和员工信息的名片夹管理功能。
用于对常用短语及其类别进行管理的信息库管理功能。
短信群发功能。
邮件群发功能。
发送邮件附件的功能。
2.2 可行性研究
开发任何一个基于计算机的系统,都会受到时间和资源上的限制。因此,在接受任何一个项目开发任务之前,必须根据客户可能提供的时间和资源条件进行可行性分析,以减少项目开发风险,避免人力、物力和财力的浪费。可行性分析与风险分析在很多方面是相互关联的,项目风险越大,开发高质量的软件的可行性就越小。
2.2.1 经济可行性
采用短信作为企业的移动通信手段,将给企业对内、对外进行信息传递与沟通带来革命性的变化,从而使得移动办公、客户服务、员工沟通等运作效率显著提升,而成本则显著下降。值得说明的是,虽然短信有以上诸多优点,但它还是有一定的不足,例如信息内容单一和受到字数限制等。为解决这一问题,在企业快信中提供了邮件群发功能。通过邮件进行沟通也是目前比较流行的方式,它也具备实用、方便和廉价等优点。
2.2.2 技术可行性
开发一个企业快信系统,涉及到的技术问题不会太多,主要用到的技术就是使用短信猫和Java Mail组件来实现收发短信和群发邮件等功能。Java Mail 组件是Sun 公司发布的一种用于读取、编写和发送电子邮件的包,利用它可以方便地实现邮件群发。
2.3 开发环境
在开发企业快信时,需要具备下面的软件环境。
服务器端:
操作系统:Windows 7。
Java 开发包:JDK 1.5 以上。
Web服务器:Tomcat6.0。
Java Mail 开发包:Java Mail 1.4。
数据库:MYSQL。
浏览器:IE 10.0。
分辨率:最佳效果为1024×768 像素。
客户端:
浏览器:IE 10.0。
分辨率:最佳效果为1024×768 像素。
由于本系统中需要使用Java Mail 组件,下面将详细介绍如何配置及Java Mail 的开发环境。
由于目前Java Mail 还没有被加在标准的Java 开发工具中,所以在使用前必须另外下载Java MailAPI,以及Sun 公司的JAF(JavaBeans Activation Framework),Java Mail 的运行必须信赖于JAF 的支持。
下载并构建Java Mail API
Java Mail API 是发送和接收E-mail 的核心API。需自行下载后解压缩到硬盘上,并在系统的环境变量CLASSPATH 中指定activation.jar 文件的放置路径。
下载并构建JAF
目前Java Mail API 的所有版本都需要JAF(JavaBeans Activation Framework)的支持。JAF 为输入的任意数据块提供了支持,并能相应地对其进行处理。下载后解压缩到硬盘上,并在系统的环境变量CLASSPATH 中指定activation.jar 文件的放置路径。
如果不想更改环境变量,也可以把activation.jar 添加到工程的构建路径中。
3 系统总体设计
3.1 系统目标
根据前面所作的需求分析及用户的需求可知,企业快信属于小型的企业通信软件,在系统实施后,应达到以下目标。
界面设计友好、美观。
操作灵活、方便。
提供功能强大的信息库管理,方便用户进行短信息的编写。
提供邮件群发功能,提高工作效率。
在发送短信时,可以直接从现有信息库中获取信息内容。
对用户输入的数据,进行严格的数据检验,尽可能地避免人为错误。
数据存储安全、可靠。
3.2 系统功能结构
根据企业快信的特点,可以将其分为名片夹管理、信息库管理、短信群发、邮件群发、系统参数设置、系统设置6个部分,其中各个部分及其包括的具体功能模块如图3-1 所示。
图3-1 系统功能结构
3.3 业务流程图
企业快信的系统流程如图3-2 所示。
图3-2 系统流程图
3.4 系统预览
企业快信由多个程序页面组成,下面仅列出几个典型界面。
系统登录页面如图3-3所示,该页面用于实现管理员登录功能;主页如图3-4所示,该页面用于实现显示系统导航、操作业务流程和版权信息等功能。
图3-3 系统登录页面
图3-4 主 页
发送短信页面如图3-5所示,该页面用于实现将短信息同时发给多个接受者的功能;同时,为方便用户还提供了从客户及员工列表中选择接收者及从信息库中选择指定信息的功能。
图3-5 发送短信页面
邮件群发页面如图3-6所示,该页面用于实现将邮件同时发给多个接受者的功能;同时,为方便用户还提供了从客户及员工列表中选择接收者的功能。
图3-6 邮件群发
3.5 文件夹组织结构
在编写代码之前,需要把系统中可能用到的文件夹先创建出来(例如创建一个名为img 的文件夹,用来保存程序中使用的效果图片),这样不但方便以后的开发工作,也可以规范软件的整体架构。本人在开发企业快信时,设计了如图3-7 所示的文件夹架构。在开发时,只需要将所创建的文件保存在相应的文件夹中就可以了。
图3-7 企业快信文件夹组织结构
4 系统详细设计
4.1 数据库设计
4.1.1 数据库分析
由于本系统是一个小型实用的信息群发系统,提供了名片夹和信息库的功能,用户可以将常用的人员保存到名片夹中,将常用的短语保存到信息库中,以方便使用。基于这个特点以及语言特点,本系统将采用MySQL 数据库作为底层数据库,以方便用户使用本系统。
4.1.2 数据库概念设计
根据以上对系统所作的需求分析和系统设计,规划出本系统中使用的数据库实体分别为类型实体、档案实体、常用短语实体、管理员实体。下面将给出几个关键实体的E-R 图。
档案实体
档案实体包括编号、客户名称、地址、邮政编码、所属区域、手机号码、邮件地址、银行账户、开户银行和联系人属性,档案实体的E-R 图如图4-1 所示。
图4-1 档案实体E-R 图
短信实体
短信实体包括编号、收信人的手机号码、短信内容、发信人和发送时间属性,短信实体的E-R 图如图4-2 所示。
常用短语
常用短语实体包括编号、类型和内容,常用短语实体的E-R 图如图4-3 所示。
添加图片注释,不超过 140 字(可选)
图4-2 短信实体E-R 图图4-3 类型实体E-R 图
4.1.3 数据库逻辑结构设计
在数据库概念设计中已经分析了档案实体、常用短语实体和类型实体,这些实体对象是数据表结的基本模型,最终的数据模型都要实施到数据库中,形成整体的数据结构。图4-4 为通过PowerDesigner创建完成的数据库模
图4-4 数据库模型图
表tb_customer 的表结构如表4-1 所示。
表4-1 表tb_customer 的表结构
字 段 名 | 数 据 类 型 | 是 否 为 空 | 是 否 主 键 | 默 认 值 | 描 述 |
---|---|---|---|---|---|
ID | int | No | Yes | ID(自动编号) | |
name | varchar(50) | No | NULL | 客户名称 | |
address | varchar(100) | No | NULL | 地址 | |
postcode | varchar(6) | No | NULL | 邮政编码 | |
area | varchar(20) | Yes | NULL | 所属区域 | |
mobileTel | avarchar(15) | No | NULL | 手机号码 | |
| varchar(100) | No | NULL | 邮件地址 | |
bankNo | varchar(30) | Yes | NULL | 银行帐号 | |
bankName | varchar(20) | Yes | NULL | 开户银行 | |
linkName | varchar(10) | No | NULL | 联系人 |
表tb_shortLetter 的表结构如表4-2 所示。
表4-2 表tb_shortLetter 的表结构
字 段 名 | 数 据 类 型 | 是 否 为 空 | 是 否 主 键 | 默 认 值 | 描 述 |
---|---|---|---|---|---|
ID | int | No | Yes | ID(自动编号) | |
toMan | varchar(200) | No | NULL | 发信人手机号码 | |
content | varchar(500) | No | NULL | 短信内容 | |
fromMan | varchar(30) | No | NULL | 发信人 | |
sendTime | datetime | No | getdate() | 发送时间 |
4.2 公共模块设计
在开发过程中,经常会用到一些公共模块,如数据库连接及操作的类、字符串处理的类及Struts配置等,因此,在开发系统前首先需要设计这些公共模块。下面将具体介绍企业快信系统中所需要的公共模块的设计过程。
4.2.1 数据库连接及操作类的编写
数据库连接及操作类通常包括连接数据库的方法getConnection()、执行查询语句的方法executeQuery()、执行更新操作的方法executeUpdate()、关闭数据库连接的方法close().下面将详细介绍如何编写企业快信系统中的数据库连接及操作的类ConnDB。
(1)定义ConnDB类
定义用于进行数据库连接及操作的类ConnDB,并将其保存到com.wgh.core包中,同时定义该类中所需的全局变量及构造方法。代码如下:
public class ConnDB {
public Connection conn = null; // 声明Connection对象的实例
public Statement stmt = null; // 声明Statement对象的实例
public ResultSet rs = null; // 声明ResultSet对象的实例
private static String propFileName = "/com/connDB.properties"; // 指定资源文件保存的位置
private static Properties prop = new Properties(); // 创建并实例化Properties对象实例
private static String dbClassName = " ";//定义保存数据库驱动的变量
private static String dbUrl = " ";
private static String dbUser = "sa";
private static String dbPwd = "";
public ConnDB() {//定义构造方法
try {//捕捉异常
//将Properties文件读取到InputStream对象中
InputStream in = getClass().getResourceAsStream(propFileName);
prop.load(in); // 通过输入流对象加载Properties文件
dbClassName = prop.getProperty("DB_CLASS_NAME");//获取数据库驱动
dbUrl = prop.getProperty("DB_URL", dbUrl);//获取URL
dbUser = prop.getProperty("DB_USER", dbUser);//获取登录用户
dbPwd = prop.getProperty("DB_PWD", dbPwd);//获取密码
} catch (Exception e) {
e.printStackTrace(); // 输出异常信息
}
}
}
(2)将数据保存到资源文件中
为了方便程序移植,将数据库连接所需信息保存到properties文件中,并将该文件保存在com包中。connDB.properties文件的内容如下:
DB_CLASS_NAME=com.mysql.jdbc.Driver
DB_URL=jdbc:mysql://127.0.0.1:3306/db_expressLetter
DB_USER=sa
DB_PWD=
(3)创建数据库连接
创建连接数据库的方法getConnection(),该方法返回connection对象的一个实例。getConnection()方法的实现代码如下:
public static Connection getConnection() {
Connection conn = null;
try {
Class.forName(dbClassName).newInstance();
conn = DriverManager.getConnection(dbUrl, dbUser, dbPwd);
} catch (Exception ee) {
ee.printStackTrace();
}
if (conn == null) {
System.err.println("警告: DbConnectionManager.getConnection() 获得数据库链接失败.\r\n\r\n链接类型:"+ dbClassName+ "\r\n链接位置:"+ dbUrl+ "\r\n用户/密码"+ dbUser + "/" + dbPwd);
}
return conn;
}
(4)创建查询方法
创建执行查询语句的方法exccuteQuery(),返回值为Resultset结果集。executeQuery()方法的代码如下:
public ResultSet executeQuery(String sql) {
try { // 捕捉异常
conn = getConnection(); // 调用getConnection()方法构造Connection对象的一个实例conn
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery(sql);
} catch (SQLException ex) {
System.err.println(ex.getMessage()); // 输出异常信息
}
return rs; // 返回结果集对象
}
(5)创建更新操作方法
创建执行更新操作的方法executeUpdate(),返回值为int型的整数,代表更新的行数。executeUpdate()方法的代码如下:
public int executeUpdate(String sql) {
int result = 0; // 定义保存返回值的变量
try { // 捕捉异常
conn = getConnection(); // 调用getConnection()方法构造Connection对象的一个实例conn
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
result = stmt.executeUpdate(sql); // 执行更新操作
} catch (SQLException ex) {
result = 0; // 将保存返回值的变量赋值为0
}
return result; // 返回保存返回值的变量
}
(6)关闭数据库连接
创建关闭数据库连接的方法close()。close()方法的代码如下:
public void close() {
try { // 捕捉异常
if (rs != null) { // 当ResultSet对象的实例rs不为空时
rs.close(); // 关闭ResultSet对象
}
if (stmt != null) { // 当Statement对象的实例stmt不为空时
stmt.close(); // 关闭Statement对象
}
if (conn != null) { // 当Connection对象的实例conn不为空时
conn.close(); // 关闭Connection对象
}
} catch (Exception e) {
e.printStackTrace(System.err); // 输出异常信息
}
}
4.2.2 字符串处理类的编写
字符串处理类主要用于解决程序中经常出现的有关字符串处理的问题,包括将数据库中及页面中有中文问题的字符串进行正确地显示和对字符串中的空值进行处理的方法。其代码如下:
public class ChStr {
public static String toChinese(String strvalue) {
try {
if (strvalue == null) {
return "";
} else {
strvalue = new String(strvalue.getBytes("ISO8859_1"), "GBK").trim();
return strvalue;
}
} catch (Exception e) {
return "";
}
}
//处理字符串中的空值
public static final String nullToString(String v, String toV) {
if (v == null || "".equals(v)) {
v = toV;
}
return v;
}
4.2.3 配置Struts
Struts框架需要通过一个专门的配置文件来控制,就是struts-config.xml。那么网站是怎么找到这个Struts的配置文件的呢?只要在web.xml中配置一下就可以了。具体实现代码如下:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>action_tmp</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- 设置默认文件名称 -->
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
在web.xml中配置Struts的配置文件,实际就是一个servlet的配置,即在配置serylet的config参数中定义struts的配置文件(包括相对路径)及在servlet的URL访问里使用后缀名。接下来的工作就是如何配置struts-config.xml文件。Struts-config.xml文件的关键代码如下:
<?xml version="1.0" encoding="UTF-8"?>
<struts-config>
<data-sources />
<form-beans >
<form-bean name="managerForm" type="com.wgh.actionForm.ManagerForm" />
…//此处省略其他<form-bean>代码
</form-beans>
<action-mappings >
<!-- 管理员 -->
<action name="managerForm" path="/manager" scope="request" type="com.wgh.action.Manager" validate="true">
<forward name="managerLoginok" path="/main.jsp" />
<forward name="managerQuery" path="/manager.jsp" />
<forward name="managerAdd" path="/manager_ok.jsp?para=1" />
<forward name="pwdQueryModify" path="/pwd_Modify.jsp" />
<forward name="managerDel" path="/manager_ok.jsp?para=3" />
<forward name="modifypwd" path="/main.jsp" />
<forward name="error" path="/error.jsp" />
</action>
…//此处省略其他<action >代码
</action-mappings>
</struts-config>
4.3 主页设计
4.3.1 主页概述
管理员通过系统登录模块的验证后,可以登录到企业快信的系统主页。系统主页主要包括系统导航栏、显示区和版权信息3部分。其中,导航栏中的功能菜单将根据登录管理员的权限进行显示。例如,系统管理员tsoft登录后,将拥有整个系统的全部功能,因为他是超级管理员。系统主页的运行效果如图4-5 所示。
图4-5 企业快信主页运行效果
4.3.2 主页技术分析
在实现系统主页时,最关键的就是如何实现导航菜单.本系统中采用的方法是通过Javascript+CSS样式控制<div>标记来实现。其具体实现方法如下:
(1)在要显示导航菜单的位置添加相应的主菜单项。具体代码如下:
<a href="main.jsp">首页</a> |
<a οnmοuseοver=showmenu(event,cardClip) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand" >名片夹管理</a> |
<a οnmοuseοver=showmenu(event,infoLibrary) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand" >信息库管理</a> |
<a οnmοuseοver=showmenu(event,shortLetter) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand" >发送短信</a> |
<a href="sendMail.do?action=addMail">邮件群发</a> |
<%if(purview.equals("1")){%>
<a href="sysParameterSet.do?action=parameterQuery" >系统参数设定</a> |
<%}%>
<a οnmοuseοver=showmenu(event,sysSet) οnmοuseοut=delayhidemenu() class='navlink' style="CURSOR:hand">系统设置</a>
| <a href="#" onClick="quit()">退出系统</a>
在Javascript中指定各个子菜单的内容,并根据登录管理员的权限控制要显示的菜单项.关键代码如下:
<script language="javascript">
var cardClip='<table width=56><tr><td id=customer onMouseOver=overbg(customer) onMouseOut=outbg(customer)><a href=customer.do?action=customerQuery>客户管理</a></td></tr>\
<tr><td id=personnel onMouseOver=overbg(personnel) onMouseOut=outbg(personnel)><a href=personnel.do?action=personnelQuery>员工管理</a></td></tr>\
</table>'
var infoLibrary='<table width=86><tr><td id=infoType onMouseOver=overbg(infoType) onMouseOut=outbg(infoType)><a href=infoType.do?action=infoTypeQuery>信息类别管理</a></td></tr>\
<tr><td id=shortInfo onMouseOver=overbg(shortInfo) onMouseOut=outbg(shortInfo)><a href=shortInfo.do?action=shortInfoQuery>常用短语管理</a></td></tr>\
</table>'
<%if(purview.equals("1")){%>
var shortLetter='<table width=86><tr><td id=sendLetter onMouseOver=overbg(sendLetter) onMouseOut=outbg(sendLetter)><a href=sendLetter.do?action=addLetter>发送短信</a></td></tr>\
<tr><td id=historyQ onMouseOver=overbg(historyQ) onMouseOut=outbg(historyQ)><a href=sendLetter.do?action=historyQuery>查看发送日志</a></td></tr>\
</table>'
<%}else{%>
var shortLetter='<table width=56><tr><td id=sendLetter onMouseOver=overbg(sendLetter) onMouseOut=outbg(sendLetter)><a href=sendLetter.do?action=addLetter>发送短信</a></td></tr>\
</table>'
<%}if(purview.equals("1")){%>
var sysSet='<table width=70><tr><td id=manager onMouseOver=overbg(manager) onMouseOut=outbg(manager)><a href=manager.do?action=managerQuery>操作员管理</a></td></tr>\
<tr><td id=changePWD onMouseOver=overbg(changePWD) onMouseOut=outbg(changePWD)><a href="manager.do?action=queryPWD">更改口令</a></td></tr>\
</table>'
<%}else{%>
var sysSet='<table width=70><tr><td id=changePWD onMouseOver=overbg(changePWD) onMouseOut=outbg(changePWD)><a href="manager.do?action=queryPWD">更改口令</a></td></tr></table>'
<%}%>
</script>
4.4 名片夹管理模块设计
4.4.1 名片夹管理模块概述
名片夹管理模块主要包括客户信息管理和员工信息管理,其中,客户信息管理包括查看客户列表、添加客户信息、修改客户信息和删除客户信息4个功能:员工信息管理包括查看员工列表、添加员工信息、修改员工信息和删除员工信息4个功能。
4.4.2 名片夹管理模块技术分析
名片夹管理模块主要包括客户管理和员工管理两部分,由于这两部分的买现方法大致相同,所以本节将以客户管理为例介绍名片夹管理模块。在实现客户管理时,需要编写客户管理对应的ActionForm类和Action实现类。下面将详细介绍如何编写客户管理的ActionForm类和创建客户管理的Action实现类。
-
编写客户管理的ActionForm类 在客户管理中,只涉及到一个数据表,即tb_customer(客户信息表),根据这个数据表可以得出客户管理的ActionForm类。客户管理的ActionForm类的名称为CustomerForm,具体代码如下: public class CustomerForm extends ActionForm { private String bankNo;//银行账号 private String area;//所属区域 private String email;//邮箱 private String address;//地址 private String mobileTel;//手机号码 private String name;//客户全称 private int ID;//编号 private String bankName;//开户银行 private String postcode;//邮政编码 private String linkName;//联系人 public String getBankNo() { return bankNo; } public void setBankNo(String bankNo) { this.bankNo = bankNo; } … //此处省略其他控制客户信息的get()和set()方法 }
-
创建客户管理的Action实现类
客户管理的Action实现类Customer继承了Action类.在该类中,首先需要在该类的构造方法中实例化客户管理的CustomerDAO类(该类用于实现与数据库的交互)。Action实现类的主要方法是execute(),该方法会被自动执行其本身没有具体的事务,是根据通过HttpservletRequest的getParamer()方法获取的action参数值执行相应方法的。客户管理的Action实现类的关键代码如下:
public class Customer extends Action{
private CustomerDAO customerDAO = null;
private ChStr chStr=new ChStr();
public Customer() {
this.customerDAO = new CustomerDAO();
}
public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){
String action = request.getParameter("action");
System.out.println("获取的查询字符串:" + action);
if (action == null || "".equals(action)) {
request.setAttribute("error","您的操作有误!");
return mapping.findForward("error");
}else if ("customerQuery".equals(action)) {
return customerQuery(mapping, form, request,response);
}else if("customerAdd".equals(action)){
return customerAdd(mapping, form, request,response);
}
else if("customerModify".equals(action)){
return customerModify(mapping, form, request,response);
}
request.setAttribute("error", "操作失败!");
return mapping.findForward("error");
}
……//此处省略了该类中其他方法,这些方法将在后面的具体过程中给出。
}
4.4.3 查看客户信息列表的实现过程
查看客户信息列表使用的数据表:tb_customer
管理员登录后,选择“名片夹管理/客户管理”命令,进入到查看客户列表页面,在该页面中将以列表形式显示全部客户信息,同时提供添加客户信息、修改客户信息、删除客户信息的超链接。查看客户信息列表页面的运行效果如图4-6 所示。
图4-6 客户信息列表页面
在查看客户信息列表的方法customerQuery()中,首先调用CustomerDAO类中的query()方法查询全部客户信息,再将返回的查询结果保存到HttpServletRequest对象的CustomerQuery参数中.查看客户信息列表的方法CustomerQuery()的具体代码如下:
private ActionForward customerQuery(ActionMapping mapping, ActionForm form,
HttpServletRequest request,HttpServletResponse response) {
request.setAttribute("customerQuery", customerDAO.query(0));
return mapping.findForward("customerQuery");
}
查看客户信息列表使用的CustomerDAO类的方法是query()。该方法只有一个用于指定客户ID的参数id(如果记的值为null,则查询全部客户信息),然后将查询结果保存到List集合中并返回该集合的实例。Query()方法的具体代码如下:
public List query(int id) {
List customerList = new ArrayList();
CustomerForm cF = null;
String sql="";
if(id==0){
sql = "SELECT * FROM tb_customer";
}else{
sql = "SELECT * FROM tb_customer WHERE ID=" +id+ "";
}
ResultSet rs = conn.executeQuery(sql);
try {
while (rs.next()) {
cF = new CustomerForm();
cF.setID(rs.getInt(1));
cF.setName(rs.getString(2));
……//此处省略获取并设置其他属性的代码
cF.setLinkName(rs.getString(10));
customerList.add(cF);
}
} catch (SQLException ex) {}
finally{
conn.close();//关闭数据库连接}
return customerList;
}
4.4.4 添加客户信息的实现过程
添加客户信息使用的数据表:tb_customer.
管理员登录后,选择“名片夹管理/客户管理”命令,进入到查看客户列表页面。在该页面中,单击“添加客户信息”超链接,进入到添加客户信息页面。添加客户信息页面的运行效果如图4-7 所示。
图4-7 添加客户信息页面
-
设计添加客户信息页面 添加客户信息页面主要用于收集输入的客户信息及通过自定义的Javascript函数验证输入信息是否合法,该页面中所涉及的表单元素如表4-3 所示。 表4-3 表tb_customer的表结构
名 称 | 元 素 类 型 | 重 要 属 性 | 含义 |
---|---|---|---|
title | form | action="customer.do?action=customerAdd" method="post" onSubmit="return checkform(form1) | 表单 |
name | text | size=”50” | 客户全称 |
area | text | size=”30” | 所在区域 |
address | text | size=”60” | 地址 |
postcode | text | size=”6” | 邮政编码 |
linkName | text | size=”20” | 联系人 |
mobileTel | text | size=”30” | 手机号码 |
| text | size=”50” | 邮箱 |
bankName | text | size=”20” | 开户银行 |
bankNo | text | size=”30” | 银行帐号 |
Submit | submit | value=”提交” | “提交”按钮 |
Submit2 | reset | value=”重置” | “重置”按钮 |
Submit3 | button | onClick="window.location.href='customer.do?action=customerQuery'" value="返回" | “返回”按钮 |
-
修改客户的Action实现类 在添加客户信息页面中输入合法的客户信息后,单击“提交”按钮,网页会访问一个URL,即customer.do?action=customerAdd从该URL地址中可以知道添加客户信息模块涉及到的action的参数值为customerAdd,也就是当action=customerAdd时,会调用添加客户信息的方法customerAdd()。具体实现代码如下 if("customerAdd".equals(action)){ return customerAdd(mapping, form, request,response); } 在添加客户信息的方法customerAdd()首先需要将接收到的表单信息强制转换成ActionForm类型,并用获得指定属性的getXXX()重新设置该属性的setXXX()方法,然后调用customerDAO类中的insert()方法,将添加的客户信息保存到数据表中,并将返回值保存到变量ret中.如果返回值为l,表示信息添加成功,将页面重定向到添加信息成功页面:如果返回值为2,表示该客户信息己经添加,将错误提示信息“该客户信息己经添加!”保存到HttpServletRequest对象的error参数中,然后将页面重定向到错误提示信息页面;否则将错误提示信息“客户信息添加失败里”保存到HttpServletRequest对象的error参数中,并将页面重定向到错误提示页面.添加客户信息的方法customerAdd()的具体代码如下: private ActionForward customerAdd(ActionMapping mapping, ActionForm form, HttpServletRequest request,HttpServletResponse response) { CustomerForm customerForm = (CustomerForm) form; //此处需要进行中文转码 customerForm.setName(chStr.toChinese(customerForm.getName())); customerForm.setAddress(chStr.toChinese(customerForm.getAddress())); customerForm.setArea(chStr.toChinese(customerForm.getArea())); customerForm.setBankName(chStr.toChinese(customerForm.getBankName())); customerForm.setLinkName(chStr.toChinese(customerForm.getLinkName())); int ret = customerDAO.insert(customerForm); System.out.println("返回值ret:"+ret); if (ret == 1) { return mapping.findForward("customerAdd"); } else if(ret==2){ request.setAttribute("error","该客户信息已经添加!"); return mapping.findForward("error"); }else { request.setAttribute("error","添加客户信息失败!"); return mapping.findForward("error"); } }
-
编写添加客户信息的CustomerDAO类的方法 添加客户信息使用的customerDAO类的方法是insert()。在insert()方法中,首先从数据表tb_customer中查询输入的客户全称是否存在,如果存在,将标志变最设置为2,否则将输入的信息保存到客户信息表中,并将返回值赋给标志变量,最后返回标志变量。Insert()方法的具体代码如下: public int insert(CustomerForm cF) { String sql1="SELECT * FROM tb_customer WHERE name='"+cF.getName()+"'"; ResultSet rs = conn.executeQuery(sql1); String sql = ""; int falg = 0; try { if (rs.next()) { falg=2;} else { sql = "INSERT INTO tb_customer (id,name,address,area,postcode,mobileTel,email,bankName,bankNo,linkName) values(null,'" + cF.getName() + "','" +cF.getAddress() +"','"+cF.getArea()+"','"+cF.getPostcode()+"','"+cF.getMobileTel()+"','"+ cF.getEmail()+"','"+cF.getBankName()+"','"+cF.getBankNo()+"','"+cF.getLinkName()+"')"; falg = conn.executeUpdate(sql); System.out.println("添加客户信息的SQL:" + sql); conn.close(); } } catch (SQLException ex) { falg=0;} return falg; }
-
Struts-config.xml文件配置
在struts-config.xml文件中配置添加客户信息所涉及的<forward>元素。代码如下:
<forward name="managerAdd" path="/manager_ok.jsp?para=1" />
4.4.5 删除客户信息的实现过程
在删除客户信息的方法customerDel()中,首先需要将接收到的表单信息强制转换成ActionForm类型,并用获得的记参数的值重新设置该ActionForm的setId()方法,再调用customerDAO类中的delete()方法,删除指定的客户信息,并根据执行结果将页面转到相应页面.删除客户信息的方法customerDel()的具体代码如下:
private ActionForward customerDel(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) {
CustomerForm customerForm = (CustomerForm) form;
customerForm.setID(Integer.parseInt(request.getParameter("id")));
int ret = customerDAO.delete(customerForm);
if (ret != 0) {
request.setAttribute("error","删除客户信息失败!!");
return mapping.findForward("error");
} else { return mapping.findForward("customerDel"); }
}
删除客户信息使用的CustomerDAO类的方法是delete()。在delete()方法中,将从客户信息表tb_customer中删除符合条件的数据,并返回执行结果。delete()方法的具体代码如下:
public int delete(CustomerForm customerForm) {
int flag=0;
try{
String sql = "DELETE FROM tb_customer where id=" + customerForm.getID() +"";
flag = conn.executeUpdate(sql);
}catch(Exception e){
System.out.println("删除客户信息时产生的错误:"+e.getMessage());
}finally{conn.close();//关闭数据库连 }
return flag;
}
在struts-config.xml文件中配置添加客户信息所涉及的<forward>元素。代码如下:
<forward name="managerDel" path="/manager_ok.jsp?para=3" />
4.5 发送短信模块设计
4.5.1 发送短信模块功能概述
发送短信模块主要包括发送短信、查看发送日志两个功能。这两个功能之间的业务流程如图4-8 所示。
图4-8 业务流程图
发送短信模块是企业快信系统的核心模块之一,操作员可以通过该模块对企业内部的所有或者部分员工,以短信的形式发送企业通知、工资条、具体技术、开会等信息,并且这个信息是群体发送的。
4.5.2 发送短信的实现过程
发送短信使用的数据表:tb_shortLetter、tb_shortIfo、tb_info、tb_infoType、tb_customer和tb_personnel。
管理员登录后,选择“发送短信”命令,进入到发送短信页面。在该页面中展开“名片夹”中的客户列表或员工列表,将显示相应的客户名称或员工姓名,单击指定的客户名称或员工姓名,系统会自动将该客户或员工的手机号码添加到右侧的“接收方手机号码”文本框中。如果用户想从信息库中选择常用短语直接添加到“短信内容”文本框中,可以先在“添加常用短语”下拉列表框中选择相应的类别,然后单击“确定”按钮,在打开的网页对话框中单击要添加的信息,即可将该信息添加到“短信内容”文本框中。短信内容填写完毕,单击“发送”按钮即可发送。发送短信页面的运行效果如图图4-9 所示。
图4-9 企业快信的短信发送界面
4.5.3 发送短信模块技术分析
在实现发送短信模块时,需要编写发送短信模块对应的ActionForm类和Action实现类。下面将详细介绍如何编写发送短信模块的ActionForm类和创建发送短信的Action实现类。
-
编写收发短信的ActionForm类 在发送短信模块中,涉及到tb_shortLetter(短信表)、tb_customer(客户信息表)、tb_personnel(员工信息表)、tb_shortInfo(常用短语表)、tb_infoType(信息类型表)和tb_Parameter(系统参数表)6个数据表,与这6个数据表相对应的ActionForm类分别为ShortLetterForm、CustomerForm、PerrsonnelForm、shortInfoForm、InfoTypyForm、ParameterForm,这些类都是由属性及对应的getXXX()和setXX()方法组成,不再详细介绍。
-
创建发送短信的Action类 收发短信模块的Action实现类SendLetter维承了Action类.在该类中.首先需要在该类的构造方法中分别实例化收发短信模块的SendLetterDAO类、员工管理摸块的PersonnelDAO类、客户管理模块的CustomerDAO类和信息类别管理模块的InfoTypeDAO类。Action实现类的主要方法是execute(),该方法会被自动执行其本身没有具体的事务,是根据HttpServletRequest的getParameter()方法获取的Action参数值执行相应方法的。发送短信模块Action实现类的关健代码如下: public class SendLetter extends Action{ private SendLetterDAO sendLetterDAO = null; private PersonnelDAO personnelDAO=null; private CustomerDAO customerDAO=null; private InfoTypeDAO infoTypeDAO=null; private ChStr chStr=new ChStr(); public SendLetter() { this.sendLetterDAO = new SendLetterDAO(); this.personnelDAO=new PersonnelDAO(); this.customerDAO=new CustomerDAO(); this.infoTypeDAO=new InfoTypeDAO(); } public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){ String action = request.getParameter("action"); System.out.println("获取的查询字符串:" + action); if (action == null || "".equals(action)) { request.setAttribute("error","您的操作有误!"); return mapping.findForward("error"); }else if ("addLetter".equals(action)) { return addLetter(mapping, form, request,response); }else if("sendLetter".equals(action)){ return sendLetter(mapping, form, request,response); }else if("historyQuery".equals(action)){ return queryHistory(mapping, form, request,response); } request.setAttribute("error", "操作失败!"); return mapping.findForward("error"); } //编写短信页面应用的查询方法,用于查询收信人列表信息类别 private ActionForward addLetter(ActionMapping mapping, ActionForm form, HttpServletRequest request,HttpServletResponse response) { request.setAttribute("personnelQuery",personnelDAO.query(0)); request.setAttribute("customerQuery",customerDAO.query(0)); request.setAttribute("shortInfo",infoTypeDAO.query(0)); return mapping.findForward("addLetter"); } //群发短信 private ActionForward sendLetter(ActionMapping mapping, ActionForm form, HttpServletRequest request,HttpServletResponse response){ SendLetterForm sendLetterForm=(SendLetterForm) form; sendLetterForm.setContent(chStr.toChinese(sendLetterForm.getContent())); sendLetterForm.setFromMan(chStr.toChinese(sendLetterForm.getFromMan())); String ret=sendLetterDAO.sendLetter(sendLetterForm); if(ret.equals("ok")){ return mapping.findForward("sendLetter"); }else{ request.setAttribute("error",ret); return mapping.findForward("error"); } } //查看历史记录 private ActionForward queryHistory(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) { request.setAttribute("history",sendLetterDAO.query()); return mapping.findForward("queryHistory"); } } (3) 编写发送短信的SendLetterDAO类的方法 发送短信使用的sendLetterDAO类的方法是sendLetter()。在sendLettr()方法中,首先从数据表tb_parameter中查询出系统参数(即使用飞信接口发送短信所使用的端口、帐号、密码等参数),然后调用发送短信的方法mySend(),最后将发送短信的日志信息保存到数据表tbshortLetter中。sendLetter()方法的具体代码如下: public class SendLetterDAO { private ConnDB conn=new ConnDB(); List parameter = ParameterDAO.query(); ParameterForm parameterForm = (ParameterForm) parameter.get(0); private smssend smssendinformation = null; // 发送短信 public String sendLetter(SendLetterForm s) { String ret = ""; String info=""; String sendnum=""; String flag=""; try { String sql_p="SELECT * FROM tb_parameter"; ResultSet rs=conn.executeQuery(sql_p); if(rs.next()){ String phone=parameterForm.getDevice(); String pwd=parameterForm.getBaud(); info=s.getContent(); sendnum=s.getToMan(); flag=mySend(phone,pwd,sendnum,info);//发送短信 if(flag.equals("ok")){ String sql = "INSERT INTO tb_shortLetter values(null,'" +s.getToMan() +"','"+s.getContent()+"','"+s.getFromMan()+"',now())"; int r= conn.executeUpdate(sql); System.out.println("添加短信发送历史记录的SQL:" + sql); if(r==0){ ret="添加短信发送历史记录失败!"; }else{ ret="ok"; } }else{ ret=flag; } }else{ ret="发送短信失败!"; } } catch (Exception e) { System.out.println("发送短信产生的错误:" + e.getMessage()); ret = "发送短信失败!"; }finally{ conn.close(); } return ret; } public static String mySend(String phone,String pwd,String to,String msg) throws HttpException, IOException{ String ret=""; HttpClient client = new HttpClient(); PostMethod post = new PostMethod("http://quanapi.sinaapp.com/fetion.php"); post.addRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=utf-8");//在头文件中设置转码 NameValuePair[] data ={ new NameValuePair("u", phone), new NameValuePair("p", pwd), new NameValuePair("to",to), new NameValuePair("m",msg), }; post.setRequestBody(data); client.executeMethod(post); Header[] headers = post.getResponseHeaders(); int statusCode = post.getStatusCode(); System.out.println("statusCode:"+statusCode); for(Header h : headers){ System.out.println(h.toString()); } post.releaseConnection(); ret = "ok"; return ret;} //中间省略查询日志的代码 } (4) struts-config.xml文件配置 在struts-config.xml文件中配置发送短信所设计的<forward>元素。代码如下: <forward name=”sendLetter” path=”/sendLetter_ok.jsp”/> 4.5.4 单元测试 在开发完收发短信模块后,为了保证程序正常运行,要对模块进行单元测试.单元测试在程序开发中非常重要,只有通过单元测试才能发现模块中的不足之处,才能及时地纠正程序中出现的错误。进入到发送短信页面,在“接收方手机号码”文本框中 输入相应的手机号码(多个手机号码间用逗号分隔),在“短信内容”文本框中输入短信内容后,单击“发送”按钮,正常情况下,会弹出“短信发送成功”的提示对话框,如果发送失败,则会弹出“短信发送失败”的提示对话框。 4.6 发送邮件模块设计 4.6.1 发送邮件模块功能概述 发送邮件模块也是企业快信系统的核心模块之一,操作员可以通过该模块对企业内部的所有或者部分员工,以E-mail 电子邮件的形式发送企业通知、工资条等。另外,由于E-mail 有信息容量大、包含附件的两大优点,使它支持更多的信息内容,可以携带更丰富的资料,比较适合发送技术信息、会议主题、工作内容等信息,并且这个信息是群体发送的。该模块的运行效果如图4-10 所示。
图4-10 企业快信的邮件发送界面 4.6.2 发送邮件模块技术分析 在实现邮件发送模块时,需要编写邮件发送模块对应的ActionForm类和Action实现类。下面将详细介绍如何编写邮件发送模块的ActionForm类和创建邮件发送的Action实现类。 (1) 编写邮件群发的ActionForm类 虽然在邮件发送模块中,只涉及到tb_customer(客户信息表)和tb_personnel(员工信息表)两个数据表,但是邮件群发并不是只涉及到与这两个数据表相对应的ActionForm类--CustomerForm和PcrsonnelForm,本模块中还涉及到用于获取发送邮件所需的表单信息的ActionForm类―sendMailForm. (2) 创建邮件发送的Action实现类 邮件发送模块的Action实现类SendMail继承了Action类。在该类中,首先需要在该类的构造方法中分别实例化邮件发送模块的SendMailDAO类、员工管理模块的PersonnelDAO类和客户管理模块的customerDAO类.Action实现类的主要方法是execute(),该方法会被自动执行.这个方法本身没有具体的事务,它是根据HttpServletRequest的getParameter()方法获取的action参数值执行相应方法的。邮件发送模块Action实现类的关键代码如下: public class SendMail extends Action{ private SendMailDAO sendMailDAO = null; private PersonnelDAO personnelDAO=null; private CustomerDAO customerDAO=null; private ChStr chStr=new ChStr(); public SendMail() { this.sendMailDAO = new SendMailDAO(); this.personnelDAO=new PersonnelDAO(); this.customerDAO=new CustomerDAO(); } public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response){ String action = request.getParameter("action"); System.out.println("获取的查询字符串:" + action); if (action == null || "".equals(action)) { request.setAttribute("error","您的操作有误!");//将错误信息保存到error中 return mapping.findForward("error");//转到显示错误信息的页面 }else if ("addMail".equals(action)) { return addMail(mapping, form, request,response); }else if("sendMail".equals(action)){ return sendMail(mapping, form, request,response); } request.setAttribute("error", "操作失败!"); return mapping.findForward("error"); } } 4.6.3 发送邮件模块实现过程 (1) 发送邮件的Action实现类 在邮件群发页面中填写相应的邮件信息后,单击“发送”按钮,网页会访问一个URL,即sendMail.do?action=sendMail。从该URL地址中可以知道发送邮件时涉及到的action的参数值为sendMail,也就是当action=sendMail时,会调用群发邮件的方法sendMail()。具体代码如下: if("sendMail".equals(action)){ return sendMail(mapping, form, request,response); } 在发送邮件的方法sendMail()中,首先需要将接收到的表单信息强制转换成ActionForm类型,并用获得指定属性的getXXX()方法获取主题、附件、内容属性并进行转码后,再使用setXXX()方法重新设置该属性,然后调用SendMailDAO类中的sendMail()方法发送邮件,并将返回值保存到变量ret中。如果返回值为ok,则表示邮件发送成功,将页面重定向到邮件发送成功页面:否则,将错误提示信息保存到HttpservletRequest对象的errror参数中,并且将页面重定向到错误提示信息页面.群发邮件的方法sendMail()的具体代码如下: private ActionForward sendMail(ActionMapping mapping, ActionForm form, HttpServletRequest request,HttpServletResponse response){ SendMailForm sendMailForm=(SendMailForm) form; sendMailForm.setTitle(chStr.toChinese(sendMailForm.getTitle())); sendMailForm.setAdjunct(chStr.toChinese(sendMailForm.getAdjunct())); sendMailForm.setContent(chStr.toChinese(sendMailForm.getContent())); int ret=sendMailDAO.sendMail(sendMailForm); if(ret==0){ request.setAttribute("error","邮件发送失败!"); return mapping.findForward("error"); }else{ return mapping.findForward("sendMail"); } } (2) 编写发送邮件的SendMailDAO类的方法 发送邮件使用的SendMailDA0类的方法是sendMail()。具体代码如下: public int sendMail(SendMailForm s) { int ret = 0; String from = s.getAddresser(); String to = s.getAddressee(); String subject = s.getTitle(); String content = s.getContent(); String password = s.getPwd(); String path = s.getAdjunct(); try { String mailserver ="smtp."+from.substring(from.indexOf('@')+1,from.length());//在Internet上发送邮件时的代码 Properties prop = new Properties(); prop.put("mail.smtp.host", mailserver); prop.put("mail.smtp.auth", "true"); Session sess = Session.getDefaultInstance(prop); sess.setDebug(true); MimeMessage message = new MimeMessage(sess); message.setFrom(new InternetAddress(from));// 给消息对象设置发件人 //设置收件人 String toArr[]=to.split(","); InternetAddress[] to_mail=new InternetAddress[toArr.length]; for(int i=0;i<toArr.length;i++){ to_mail[i]=new InternetAddress(toArr[i]); } message.setRecipients(Message.RecipientType.BCC,to_mail); //设置主题 message.setSubject(subject); Multipart mul = new MimeMultipart(); // 新建一个MimeMultipart对象来存放多个BodyPart对象 BodyPart mdp = new MimeBodyPart(); // 新建一个存放内容的BodyPart对象 mdp.setContent(content, "text/html;charset=gb2312"); mul.addBodyPart(mdp); // 将含有信件内容的BodyPart加入到MimeMulitipart对象中 if(!path.equals("") && path!=null){//当存在附件时 // 设置信件的附件(用本机上的文件作为附件) mdp = new MimeBodyPart(); // 新建一个存放附件的BodyPart String adjunctname = new String(path.getBytes("GBK"), "ISO-8859-1"); // 此处需要转码,否则附件中包括中文时,将产生乱码 path = (System.getProperty("java.io.tmpdir") + "/" + path).replace("\\", "/"); System.out.println("路径:" + path); FileDataSource fds = new FileDataSource(path); DataHandler handler = new DataHandler(fds); mdp.setFileName(adjunctname); mdp.setDataHandler(handler); mul.addBodyPart(mdp); } message.setContent(mul); // 把mul作为消息对象的内容 message.saveChanges(); Transport transport = sess.getTransport("smtp"); // 以smtp方式登录邮箱,第1个参数是发送邮件用的邮件服务器SMTP地址,第2个参数为用户名,第3个参数为密码 transport.connect(mailserver, from, password); transport.sendMessage(message, message.getAllRecipients()); transport.close(); ret = 1; } catch (Exception e) { e.printStackTrace(); System.out.println("发送邮件产生的错误:" + e.getMessage()); ret = 0;} return ret; } 4.6.4 单元测试 在开发完邮件群发模块后,为了保证程序正常运行,一定要对模块进行单元测试,下面是原始的实现邮件发送的代码: if(!path.equals("") && path!=null){//当存在附件时 // 设置信件的附件(用本机上的文件作为附件) mdp = new MimeBodyPart(); // 新建一个存放附件的BodyPart String adjunctname=path; path = (System.getProperty("java.io.tmpdir") + "/" + path).replace("\\", "/"); System.out.println("路径:" + path); FileDataSource fds = new FileDataSource(path); DataHandler handler = new DataHandler(fds); mdp.setFileName(adjunctname); mdp.setDataHandler(handler); mul.addBodyPart(mdp); } 通过上面的代码实现的邮件群发会存在以下问题:当发送带有中文名称的邮件后.使用Outlook软件接收邮件时,附件的名称将产生乱码。这是因为在邮件群发的Action类中,己经将接收到的附件名称转换为GBK编码格式,而在OutLook接收附件时,采用的编码格式为ISO-8859-1,所以此处还需要将其转换为巧IOS-8859-1编码格式。那为什么还要在Action类中进行转码呢?这是因为如果不进行转换,在类中通过文件名获取文件路径时,将不能正常获取。修改后的完成邮件群发的代码如下: if(!path.equals("") && path!=null){//当存在附件时 // 设置信件的附件(用本机上的文件作为附件) mdp = new MimeBodyPart(); // 新建一个存放附件的BodyPart String adjunctname = new String(path.getBytes("GBK"), "ISO-8859-1"); // 此处需要转码,否则附件中包括中文时,将产生乱码 path = (System.getProperty("java.io.tmpdir") + "/" + path).replace("\\", "/"); System.out.println("路径:" + path); FileDataSource fds = new FileDataSource(path); DataHandler handler = new DataHandler(fds); mdp.setFileName(adjunctname); mdp.setDataHandler(handler); mul.addBodyPart(mdp);
5 技术分析 5.1 开发技巧与难点分析 5.1.1 添加收信人 为了方便用户,系统中需要提供通过单击客户列表(或员工列表)中的客户全称(或员工姓名),即可将该客户(或员工)的联系手机号码添加到“接收方手机号码”文本框中的功能。实现该功能时.需要编写自定义的JavaScript函教add(),在该函数中需要对手机号码进行验证并实现累加手机号码到“接收方手机号码”文本框中的功能。Add()函数的具体代码如下: function add(mobileTel){ if(checkTel(mobileTel)){ s=form1.toMan.value; if(s.length>=11){ arrS=s.split(","); flag=false;//标记是否已经添加 for(i=0;i<arrS.length;i++){ if(arrS[i]==mobileTel){//判断该手机号码是否已经添加 flag=true; break; } } if(!flag){ form1.toMan.value=s+","+mobileTel; } }else{form1.toMan.value=mobileTel;} } } 5.1.2 插入短信 为了方便用户,系统中需要提供将信息库中保存的常用短语添加到“短信内容”文本框中的功能。实现该功能的具体步骤如下: (1)在发送短信页面的“添加常用短语”下拉列表框的右侧添加一个“确定”按钮,在该按钮的onClick事件中调用自定义的Javascript函数deal()。关键代码如下: function deal(infoType,text){ var someValue; var str="window.showModalDialog('shortInfo.do?action=selectShortInfo&id="+infoType+"','','dialogWidth=520px;\ dialogHeight=430px;status=no;help=no;scrollbars=no')"; someValue=eval(str); if(someValue!=undefined){text.value=text.value+someValue; } (2)创建选择指定类别的常用短语的页面selectShortInfo.jsp,并且在该页面中添加用于将选择的常用短语返回到打开该窗口的交量,并且关闭当前窗口的自定义JavaScript函数selectInfo().selectInfo()函数的具体代码如下: <script language="javascript"> function selectInfo(info){ window.returnValue=info; window.close();} </script> (3)在selectShortInfo.jsp中显示常用短语的代码上添加一个空的超链接,并且在其onClick事件中调用selectInfo()函数。具体代码如下: <a href="#" onClick="selectInfo('<%=s.getContent()%>')"><%=s.getContent()%></a> 5.2 使用Java Mail 组件 Java Mail 是Sun 公司发布用来处理E-mail 的API,是一种可选的、用于读取、编写和发送电子消息的包(标准扩展)。使用Java Mail 可以创建MUA(Mail User Agent,邮件用户代理的简称)类型的程序,它类似于Eudora、Pine 及Microsoft Outlook 等邮件程序。其主要目的不是像发送邮件或提供MTA(Mail Transfer Agent,邮件传输代理)类型程序那样用于传输、发送和转发消息,而是可以与MUA 类型的程序交互,以阅读和撰写电子邮件。MUA 依靠MTA 处理实际的发送任务。Java Mail API 中提供很多用于处理E-mail 的类,其中比较常用的有Session(会话)类、Message(消息)类、Address(地址)类、 Authenticator(认证方式)类、Transport(传输)类、Store(存储)类和Folder(文件夹)类7 个类。这7 个类都可以在Java Mail API 的核心包mail.jar 中找到,下面进行详细介绍。 5.2.1 Session 类 Java Mail API 中提供了Session 类,用于定义保存诸如SMTP 主机和认证的信息的基本邮件会话。通过Session 会话可以阻止恶意代码窃取其他用户在会话中的信息(包括用户名和密码等认证信息),从而让其他工作顺利执行。 每个基于Java Mail 的程序都需要创建一个Session 或多个Session 对象。由于Session 对象利用java.util.Properties 对象获取诸如邮件服务器、用户名、密码等信息,以及其他可在整个应用程序中共享的信息, 所以在创建Session 对象前, 需要先创建java.util.Properties 对象的实例。创建java.util.Properties 对象的实例的代码如下: Properties props=new Properties(); 创建Session 对象可以通过以下两种方法,不过通常情况下会使用第二种方法创建共享会话。 (1)使用静态方法创建Session 的语句如下: Session session = Session.getInstance(props, authenticator); (2)创建默认的共享Session 的语句如下: Session defaultSession = Session.getDefaultInstance(props, authenticator); 如果在进行邮件发送时,不需要指定认证方式,可以使用空值(null)作为参数authenticator 的值。例如创建一个不需要指定认证方式的Session 对象的代码如下: Session mailSession=Session.getDefaultInstance(props,null); 5.2.2 Address 类 Address 类用于设置电子邮件的响应地址。Address 类是一个抽象类,要使用该抽象类可以使用其子类InternetAddress,该类保存在javax.mail.internet 包中,可以按照指定的内容设置电子邮件的地址。如果想对InternetAddress 类进行操作,首先要实例化该类的一个对象。在实例化该类的对象时,有以下两种方法。 创建带有电子邮件地址并显示其他标识信息的地址,可以将电子邮件地址和附加信息同时传递给InternetAddress 类的构造方法。代码如下: InternetAddress address = new InternetAddress("wgh717@sohu.com","WangGuoHui"); 5.2.3 Authenticator 类 Authenticator 类通过用户名和密码来访问受保护的资源。Authenticator 类是一个抽象类,要使用该抽象类首先需要创建一个Authenticator 的子类,并重载getPasswordAuthentication()方法。具体代码如下: class WghAuthenticator extends Authenticator { public PasswordAuthentication getPasswordAuthentication() { String username = "wgh"; //邮箱登录账号 String pwd = "111"; //登录密码 return new PasswordAuthentication(username, pwd); } } 然后再通过以下代码实例化新创建的Authenticator 的子类,并将其与Session 对象绑定。 Authenticator auth = new WghAuthenticator (); Session session = Session.getDefaultInstance(props, auth); 5.2.4 Transport 类 Transport 类用于使用指定的协议(通常是SMTP)发送电子邮件。Transport 类提供了以下两种发送电子邮件的方法: (1)只调用其静态方法send(),按照默认协议发送电子邮件。代码如下: Transport.send(message); (2)首先从指定协议的会话中获取一个特定的实例,然后传递用户名和密码,再发送信息,最后关闭连接。代码如下: Transport transport =sess.getTransport("smtp"); transport.connect(servername,from,password); transport.sendMessage(message,message.getAllRecipients()); transport.close(); 在发送多个消息时,建议采用第二种方法,因为它将保持消息间活动服务器的连接,而使用第一种方法时,系统将为每一个方法的调用建立一条独立的连接。