环境配置。为了运行javamail。我们需要在classpath里导入两个包:mail.jar和activation.jar,这是在纯DOS里或者其它简单工具使用时才需要这个classpath。如果使用像eclipes这样的工具就不需要配置。因为myeclipes已经帮你做好了。
为了要发送邮件和接收邮件,我们必须要遵守smtp和pop3协议,不过还有其它协议也可执行(如IMAP)。如果把本机当作服务器来发送邮件请在
http://jakrata.apache.org网站里下载james邮件服务器,然后解压在本机上。运行james/bin里的run.bat就可以启动了服务器。
运行后在DOS里登录邮件服务器。具体命令如下:
系统管理员:root
密码:root
telnet localhost 4555
然后就可以增加邮箱用户名了。命令如下:
adduser 用户名 密码
例:adduser test test
这样就建立了这样一个邮箱test@localhost 密码为:test
如果想要更多功能用help命令
注意:如果在本机装了邮件服务器的话,只能在本机局域网里申请邮箱,发送和接收。不能发送到外部的邮箱里去。如果用外部的邮件服务器像比如163和126的服务器等就可以随心所欲的发邮件了。哈哈是不是很爽呢?
先看看用james邮件服务器在本机上发邮件吧。先简单看一个例子。
import javax.mail.*;
import java.util.*;
import javax.mail.internet.*;
public class MyFirstMail
{
protected Session mailSession;
public MyFirstMail()throws Exception
{
init();
}
public static void main(String[] args)
{
try
{
new MyFirstMail().sendMail();
System.out.print("邮件已发");
}
catch(Exception e)
{
e.printStackTrace();
}
}
//初始化服务器环境
public void init()throws Exception
{
Properties props=new Properties();
props.put("mail.transport.protocol","smtp");
props.put("mail.smtp.host","localhost");
props.put("mail.smtp.port","25");
mailSession=Session.getDefaultInstance(props, null);;
}
public void sendMail()throws Exception
{
try
{
//从哪里发的邮件
msg.setFrom(new InternetAddress("test@localhost"));
//发送到目标邮件 msg.setRecipients(Message.RecipientType.TO,InternetAddress.parse("wang@localhost"));
//抄送的接收者 msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse("wang@localhost"));
//暗送的接收者
msg.setRecipients(Message.RecipientType.BCC,InternetAddress.parse("wang@localhost"));
//设置发送时间
msg.setSentDate(new java.util.Date());
//设置邮件标题
msg.setSubject("a test mail");
//设置邮件内容
msg.setText("this is the email content");
//指定协议发送消息的对像
Transport transport=mailSession.getTransport("smtp");
//发送消息
Transport.send(msg);
}
catch(Exception e)
{
throw e;
}
}
发送完后想要看邮件就要到james->apps->james->var->mail->inboxes就可以看见每个邮箱里的邮件数了。由于发过来的是字节流,邮件包括一个邮件属性和消息,所以每一封邮件是由二个文件组成的。
也许没有学过的javamail的人看上去会一头雾水。不要紧,现在一一详解。先说初始化的内容的吧!
1、 mail.transport.protocol=smtp 这里主要说明的是邮件传输协议。
2、 mail.smtp.host=localhost 发送邮件的主机如果用外部邮件服务器的话,可以这样写
mail.smtp.host=smtp.163.com这样就以163.为服务器了。
3、mail.smtp.prot=25 smtp端口可以省略,缺省为25
javax.mail.session
session类定义了与远程邮件系统通信的邮件会话。需要注意的是这个session不同servlet中的会话。Servlet中的会话需要共享一些信息,而mail里的session里没有这个功能,它只是用于存储与服务器建立连接会话相关信息和逻辑。Session类是javamail api最高层入口类,所有其它类都必须经由session对象生效。Session对象它管理配置选项和用于与邮件系统交互的用认证信息息。它通过使用java.util.properties对象配置邮件会话的属性如邮件服务器,用户名,密码,及整个应用程序中共享的其它信息。
Session并不处现任何授权操作,它只是存储这些授权信息。Session类的构造器是私有的,它不能被继承,也不能用new语名创建实例。但它提供了两个静态方法getInstance 和getDefaultInstance来获取session实例,在创建session实例时需要提供一些属性。具体实现如下:
Properties props=new Properties()
Props.put(“mail.transport.protocol”,”smtp”)
Props.put(“mail.smtp.host”,”localhost”);
Props.put(“mail.smtp.prot”,”25”)
//不加以认证也可以这样写
//Session session=Session.getDefaultInstance(props,null)
//如果认证传入null那么它和不使用认证调用方式一样
Session session=Session.getDefaultInstance(props)
Javax.mail. Message
经过session配置后就可以进行发送消息任务了。这由Message类来完成。Message实现了Part接口,它表示一个邮件消息,包含一系列的属性和一个消息内容。消息属性包括了消息址址消息,定义了消息内容的结构(包括内容类型),消息内容使用DataHandler对象包装实际数据。当邮件消息位于目录(folder)中时,系统还使用了一个标志位集合来描述它的状态。
Message是抽象类,实际使用时必须用一个子类代替以表示具体的邮件格式。比如说javamail api提供了MimeMessage类,该类扩展了Message,实现了RFC822和MIME标准。有两个构造方法:
//一般使用第一种
Message msg=new MimeMessage(Session session)
Message msg=new MimeMessage(MimeMessage msg)
获得消息后,就可以设置消息各个部份了。在设置之前因为要涉及地址。所以讲一下地址类
javax.mail.Address
Address类表示电子邮件类,它是一个抽象类,它的子类InternetAddress提供具体实现且通常可串行化。若创建的地址只包含电子邮件,只要传递电子邮件到构造器即可如
InternetAddress addr=new InternetAddress();
addr.setAddress(“wang@126.com”)
或者是:InterntAddress addr=new InternetAddress(“wang@126.com”)
另外,InternetAddress类还提供了地址解析方法如
Address[] addrs=InternetAddress.parse(“wang@163.com,f@126.com,zuo@126.com”);
地址之后就可以发送消息了。
//设置发送者
Msg.setFrom(new InternetAddress(“test@126.com”));
//设置接收者,并还具有解析功能
Msg.setRecipients(Message.RecipientType.To,InternetAddress.parse(“zuolin0806@163.com”));
//抄送的接收者
Msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse(“zuolin0806@163.com”));
//暗送的接收者
Msg.setRecipients(Message.RecipientType.CC,InternetAddress.parse(“zuolin0806@163.com”));
//设置消息主题
msg.setSubject(“我的爱”)
//设置内容的基本机制,其参数Mime类型
msg.setContent(“这是我的内容”,”text/html;charset=gb2312”)
其中的text/html表示消息内容采用的是HTML格式。如果消息格式是(text/plain),而且使用的是MimeMessage,那么setText()方法设置邮件内容的参数(Mime类型默认为text/plain)
//设置邮件内容
msg.setText();
//设置发送时间
msg.setSentDate(new java.util.Date());
最后一步是就是发送了
javax.mail.Transport
该类也是抽象类,它可通过静态方法和实便方法发送消息。Transport断承service类。所以它提供了通用方法,如命名传输,连接服务器和监听传输事件等。
//默认
Transport.send(msg);
最后看一下使用外部邮件服务器的使用方法。先看程序再讲解,注意在使用外部邮件服务器时一定要有一个类来认证。到时在讲。
public class MySecondMail
{
protected Session session = null;
//邮件用户名
String mailUser = "zuolin0806";
String host = "smtp.163.com";
String pwd = "用户名的密码";
public MySecondMail()
{
init();
}
public void init()
{
Properties props = new Properties();
props.put("mail.transpost.protocol", "smtp");
props.put("mail.smtp.host", "smtp.163.com");
//必须要有一个类来认证
props.put("mail.smtp.auth", "true");
props.put("mail.smpt.port", "25")
Email_Autherticatorbean auth = new Email_Autherticatorbean(mailUser,pwd);
//session认证
session = Session.getInstance(props,auth);
//这个是跟踪后台消息。打印在控制台
session.setDebug(true);
}
public static void main(String[] args)
{
new MySecondMail().sendMails();
System.out.println("send mail success!");
}
public void sendMails()
{
try
{
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress("zuolin0806@163.com"));
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse("javaboy@126.com"));
msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse("javaboy@126.com"));
msg.setSentDate(new Date());
msg.setSubject("this is my Threee mail");
msg.setContent("this is my mail","text/html");
msg.setText("我成功了。哈哈");
Transport transport = session.getTransport("smtp");
与发送者的邮箱相连
transport.connect(host,mailUser,pwd);
transport.send(msg);
}
catch (SendFailedException e)
{
e.printStackTrace();
}
catch (Exception ee)
{
ee.printStackTrace();
}
}
}
认证类必须继承Authenticator 例子如下:
import javax.mail.*;
public class Email_Autherticatorbean extends Authenticator
{
private String m_username = null;
private String m_userpass = null;
public void setUsername(String username)
{
m_username = username;
}
public void setUserpass(String userpass)
{
m_userpass = userpass;
}
public Email_Autherticatorbean(String username, String userpass)
{
super();
setUsername(username);
setUserpass(userpass);
}
public PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication(m_username,m_userpass);
}
}
经过成功发送邮件后是不是有点成就感呢!但还有很多疑问比如怎么读邮件呢?看了下面章节你就会知道了
JSF开发实战(一)
JSF将是J2EE5.0中所包含的web开发框架,这应该是第一个成为jcp标准,并且随j2eesdk一起发布的web框架,可以看出sun对它的期望很高。JSF最大的竞争对手是tapestry,是apache的产品,但是apache又弄出了个myfaces,是对jsf标准的一个实现。也许你也和我一样,在jsf和tapestry之间犹豫很久,将来从apache的态度上应该可以看出二者的走向。在tss上有一篇比较jsf 1.0与tapestry 3.0的文章,内容很扎实到位:
http://www.theserverside.com/articles/article.tss?l=JSFTapestryJSF的竞争对手不是struts/webwork之流,它们基本上已经是不同阶段上的东西了,放在一起比较意义不大。
JSF的开发流程和asp.net中所倡导的code behind方式很相似,核心是事件驱动,组件和标签的封装程度非常高,很多典型应用已经不需要开发者去处理http。页面操作会被自动映射到对应的java bean中,后台逻辑只需要同java bean发生交互。整个过程是通过“依赖注入(DI)”来实现的,看来这是目前解偶合的最佳途径啊,spring的影响真是深远。不过正式因为jsf采用了这样的方式,导致开发工作和以前的jsp/struts等都有非常大的不同,需要一定的时间去学习。学习之前建议先对依赖注入有比较清楚的认识,可以参考我的learn Spring in spring系列的第一篇。
本系列将以两个例子来讲解jsf的基本开发,第一个例子当然是hello world。目前可用的jsf ide不多,ibm要到06年才能放出支持jsf的wtp版本。所以我们的例子基本以手写为主,这样也能让我们有更清楚的认识,同时推荐目前最好的jsf开发工具:myeclipse 4.0 GA。后面的例子将会有jsf和hibernate的内容,它都能给予很好的支持。由于myeclipse并不免费,所以我们除了讲解在ide中如何操作外,还会叙述手动操作的具体内容,以免过于依赖开发工具。用什么服务器都可以,这里采用了jboss 4.0.2。如果你的服务器是高版本的tomcat(5.5+),那么必须要删除它自带的一些包才能很好的支持jsf,具体细节请查看它的文档。
请自行下载jsf ri和JSTL 1.1。
废话少说,开始了。
在myeclipse 4.0GA中新建一个web项目,命名为hello,为项目增加对JSTL的支持:
在JSTL的版本中选择1.1。
该操作实际上是把jstl.jar和standard.jar加到工程中。
采用类似的操作为项目添加对jsf的支持:myeclipse?add jsf capabilities
如图:
其中的jsf implementation是选择使用哪中JSF实现,我们采用的是sun的jsf ri
JSF config path是配置文件的位置,保持不变
URL pattern是jsf servlet的映射方式,有两种选择,具体细节后面说明。
以上操作上是为项目加入了jsf需要的jar和tld文件,并且创建了一个faces-config.xml的配置文件。涉及到的jar有:commons-beanutils.jar commons-collections.jar commons-digester.jar commons-logging.jar jsf-api.jar jsf-impl.jar
涉及到了jsf中所有的tld文件。
当前的faces-config.xml文件的内容是:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
</faces-config>
环境已经建立好了,现在我们要建立一个程序,它的功能是让用户在表单中输入名字,提交后系统会返回一个问候。使用jsf的以后好处是,开发人员会很自然的把mvc各层分开,不会像使用strtus那样别扭,这一点在后面的开发中感觉得到。
首先开发model层,它是个很简单的bean:
package org.bromon.jsf.model.hello;
public class SayHello {
public String say(String name)
{
return "你好,"+name;
}
}
在model层中你可以随意的实现业务的数据逻辑,不需要与web层有任何的关系。
下面开发控制层,它负责存取web层的数据,并且调用model层的逻辑:
/**
* jsf的控制层方法
* @author bromon
*/
package org.bromon.jsf.control.hello;
import org.bromon.jsf.model.hello.*;
public class HelloDelegater {
//------属性---------
private String name;//表单中的文本框数据会传到这里
private String result;//web页会从这里取得运行结果
private SayHello sayHello;//model层的对象,并不事例化,由系统注入
//-----set/get--------
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public SayHello getSayHello() {
return sayHello;
}
public void setSayHello(SayHello sayHello) {
this.sayHello = sayHello;
}
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
//-----逻辑方法---------
public String say()
{
this.setResult(sayHello.say(this.getName()));
return "ok";
}
}
需要注意的是,属性的名字、set/get方法的名字必须严格按照java bean规范编写,因为它们要被注入依赖时使用。sayHello对象并没有被实例化,它会在运行时由系统注入。
这两个bean当然要在系统中申明,否则无法实现DI。在faces-config.xml文件中添加内容:
<managed-bean>
<managed-bean-name>SayHello</managed-bean-name>
<managed-bean-class>
org.bromon.jsf.model.hello.SayHello
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>HelloDelegater</managed-bean-name>
<managed-bean-class>
org.bromon.jsf.control.hello.HelloDelegater
</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>sayHello</property-name>
<value>#{SayHello}</value>
</managed-property>
</managed-bean>
在后一个bean中,它的sayHello属性被指定要在运行时注入一个org.bromon.jsf.model.hello.SayHello的实例。
下面要编写表示层的页面,只有一个index.jsp:
需要引入两个标签库:
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
下面是构造jsf标签:
<body>
<f:view>
<h:form>
<h:panelGrid columns="3">
<h:outputLabel for="name" value="姓名:"/>
<h:inputText id="name" value="#{HelloDelegater.name}" required="true"/>
<h:message for="name"/>
<h:outputLabel value="#{HelloDelegater.result}"/>
</h:panelGrid>
<h:panelGroup>
<h:commandButton action="#{HelloDelegater.say}" value="提交"/>
</h:panelGroup>
</h:form>
</f:view>
</body>
页面中包含了一个文本框和一个label,他们分别被绑定到了HelloDelegater类的两个属性上,具体的绑定工作有系统通过翻转控制的方式调用对应的set/get方式实现。提交按钮被绑定到了HelloDelegater.say方法,该方法会把计算结果赋给result属性,它会在页面中显示出来。
因为我们在url pattern中选择了*.faces,所以我们应该访问如下地址来查看程序:
http://localhost:8080/hello/index.faces
相应的,如果你选择了/faces/*,那么就应该是:
http://localhost:8080/hello/faces/index.jsp
程序执行结果如下:
bromon原创