B2C电子商务网站使用S2SH发送激活账号的电子邮件
1、 邮箱服务器的设置
在此使用的是QQ邮箱服务器来实现的,下面的操作就以QQ邮箱服务器为例
如果你的QQ邮箱还未开通pop3和smtp服务的话,你需要按照下面的操作来开通服务:
第一步
第二步:
2、 引入相应的jar文件:
在我们的B2C电子商务网站中,在lib下出除了之前我们引入的jar文件之外,我们还需要两个jar文件,分别是:
activation.jar和mail.jar
3、 在dao层新建一个SendEmailDao接口:
public interface SendEmailDao { public void sendMail(Customers entity);// 括号里面的参数是会员的一个实体 public interface SenderMailDao { // 给会员发送email的方法 public void sendMail(Customers entity); } }
4、 接下来就是这个接口的实现类:SendEmailDaoImpl
public class SendEmailDaoImpl implements SendEmailDao { private JavaMailSenderImpl mailSender;// 这个类中封装了邮箱服务器的一些配置,包括host,用户名,密码等 // 下面在配置文件中会有详细的说明 public void setMailSender(JavaMailSenderImpl mailSender) { this.mailSender = mailSender; }// 通过set方法注入 public void sendMail(Customers entity) { // 通过MailSender创建一个邮件 MimeMessage message = mailSender.createMimeMessage(); try { // 这里的MimeMessageHelper是用来封装邮件的一些基本信息 MimeMessageHelper helper = new MimeMessageHelper(message, true, "UTF-8"); helper.setFrom("[email protected]");// 发件人的地址 helper.setTo(entity.getEmail());// 收件人的地址 helper.setSubject("账户激活邮件");// 邮件的主题 MimeBodyPart body = new MimeBodyPart();// 邮件体 body .setContent( "<a href='http://localhost:8080/sendemail/csdn/customers_activation.action?entity.lname=" + entity.getLname() + "&entity.ctype=2'>尊敬的 " + entity.getName() + " 用户,您好!!欢迎您使用我们的电子商务网站!!" + " 请点击激活您的账户</a>", "text/html;charset=UTF-8");// 这个邮件体是一个超链接,是用来设置会员的状态的;(补充:在我们的数据库中的会员表中应该添加一个会员账号激活状态的字段,我的表中叫“ctype“) MimeMultipart mp = new MimeMultipart(); mp.addBodyPart(body); message.setContent(mp); mailSender.send(message);// 发送邮件 System.out.println("邮件发送中......"); } catch (MessagingException e) { System.out.println("发送失败。。。。。"); e.printStackTrace(); } } }
5、在我们的Service层新建一个SendEmailService接口,同时这个接口继承dao层的接口
public interface SendEmailService extends SendEmailDao { }
6、 然后就是新建一个实现service层的接口的实现类SendEmailService
public class SendEmailServiceImpl implements SendEmailService { private SendEmailDaoImpl sendEmailDaoImpl;// 真正的业务实现类 private TaskExecutor taskExecutor;// 异步线程执行器 在文档的最后有说明 // 分别用set方法注入 public void setSendEmailDaoImpl(SendEmailDaoImpl sendEmailDaoImpl) { this.sendEmailDaoImpl = sendEmailDaoImpl; } public SendEmailDaoImpl getSendEmailDaoImpl() { return sendEmailDaoImpl; } public void setTaskExecutor(TaskExecutor taskExecutor) { this.taskExecutor = taskExecutor; } // 下面是关键部分,为了将会员的注册和发送邮件不在一个线程下执行我们需要将发送邮件的操作另开启一个线程去完成,这样一来会员的注册就不会因为发送邮件而发生等待的过程。 public void sendMail(final Customers entity) { taskExecutor.execute(new Runnable() { public void run() { sendEmailDaoImpl.sendMail(entity); } }); } }
7、 配置文件的相关配置
首先是dao层的配置,这里我们需要配置我们真正的和业务实现bean以及邮箱服务器的配置
<bean id="hibernateDaoSupport" class="org.springframework.orm.hibernate3.support.HibernateDaoSupport" scope="singleton" abstract="true"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <bean id="customersDaoImpl" class="cn.dxl.dao.CustomersDaoImpl" scope="singleton" parent="hibernateDaoSupport"></bean> <!-- 真正的业务实现类--> <bean id="sendEmailDaoImpl" class="cn.dxl.dao.SendEmailDaoImpl" scope="singleton"> <property name="mailSender" ref="mailSender" /> </bean> <!-- 邮箱服务器配置 --> <bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl"> <!--邮箱服务器的主机地址 --> <property name="host" value="smtp.qq.com" /> <!--默认的编码方式 --> <property name="defaultEncoding" value="UTF-8" /> <!--服务器的端口号 --> <property name="port" value="25" /> <!-- 连接服务器的用户名 也就是你的QQ邮箱的地址名例如[email protected] --> <property name="username" value="[email protected]" /> <!-- 密码 就是你登陆邮箱的密码 --> <property name="password" value="yatou123" <!-- 下面就是smtp的一些设置 --> <property name="javaMailProperties"> <props> <!-- 设置自动登录 --> <prop key="mail.smtp.auth">true</prop> <!-- 设置端口的进入优先命令状态 --> <prop key="mail.smtp.starttls.enable">true</prop> </props> </property> </bean>
8、 接下来是service层的配置
在这里我们需要对我们service层的业务实现类进行配置,以及异步执行器的配置
//bean的配置 <bean id="customersServiceImpl" class="cn.dxl.service.CustomersServiceImpl" scope="singleton"> <property name="customersDaoImpl" ref="customersDaoImpl"></property> </bean> <!-- service层的业务实现类 --> <bean id="sendEmailServiceImpl" class="cn.dxl.service.SendEmailServiceImpl" scope="singleton"> <!-- 为真正的业务实现类 进行注入 --> <property name="sendEmailDaoImpl" ref="sendEmailDaoImpl" /> <!-- 为异步线程执行器 进注入 --> <property name="taskExecutor" ref="taskExecutor" /> </bean> <!-- 配置异步线程执行器 --> <bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 设置核心池子的大小 --> <property name="corePoolSize" value="10" /> <!-- 设置最大池子的大小 --> <property name="maxPoolSize" value="30" /> </bean>
9、 最后就是action的配置
在会员的action中我们要引入service层的业务接口(代理都是面向接口的编程)
Action配置文件中的代码
<bean id="customersAction" class="cn.dxl.action.CustomersAction" scope="prototype"> <property name="customersServiceImpl" ref="customersServiceImpl"/> <property name="sendEmailServiceImpl" ref="sendEmailServiceImpl"/> </bean>
action类中的代码:
public class CustomersAction extends ActionSupport { /** * @author DXL_xiaoli */ private static final long serialVersionUID = 1L; private CustomersService customersServiceImpl; private SendEmailService sendEmailServiceImpl; private Customers entity; // set方法注入 public SendEmailService getSendEmailServiceImpl() { return sendEmailServiceImpl; } public void setSendEmailServiceImpl(SendEmailService sendEmailServiceImpl) { this.sendEmailServiceImpl = sendEmailServiceImpl; } public void setCustomersServiceImpl(CustomersService customersServiceImpl) { this.customersServiceImpl = customersServiceImpl; } public CustomersService getCustomersServiceImpl() { return customersServiceImpl; } public Customers getEntity() { return entity; } public void setEntity(Customers entity) { this.entity = entity; } // 会员注册 public String register() { entity.setCtype(1+""); customersServiceImpl.insert(entity); // 注册完成后自动发送激活邮件 sendEmailServiceImpl.sendMail(entity); return "register"; } //激活邮箱操作 public String activation(){ Customers customers=customersServiceImpl.findByLname(entity.getLname()); customers.setCtype(2+""); customersServiceImpl.update(customers); return "activation"; } }、
这样我们就完成了通过Spring实现用户注册发送激活账号的邮件的整个过程,我的观点是:Spring实现发送邮件的方式基本和javaMail的方式一样,只不过在javaMail的基础上多了一些bean的配置;在使用Spring发送邮件的时候,处理邮件的两个最核心的配置就是邮件服务器的配置和异步线程执行器的配置。
邮件服务器的配置:是往容器中装配一个JavaMailSender Bean,它就是JavaMail的封装,其中最关键的是装配过程的属性参数,这些属性既要严格遵照JavaMail规范,又要满足邮件提供商的要求,例如SMTP服务器端口是多少、发送时是否要身份验证、服务器是否采用安全连接、连接时是否加密以及采用什么样的加密方式,邮件服务商提供的这些参数直接影响到上述的配置,因此配置之前一定要到邮件提供商的站点上详细了解邮箱的技术参数。
TaskExecutor抽象:
Spring 2.0 为执行器(Executor)处理引入了一个新的抽象层。Executor是Java 5的名词,用来表示线程池的概念。之所以用这个奇怪的名词,是因为实际上不能保证底层实现的确是一个池。实际上,很多情况下,executor只是单线程。Spring的抽象层帮助你把线程池引入到Java 1.3和1.4环境中,同时隐藏了 1.3, 1.4, 5, 和 Java EE环境中线程池实现的差异。
TaskExecutor接口:
Spring的TaskExecutor
接口等同于java.util.concurrent.Executor
接口。实际上,它存在主要原因是为了在使用线程池的时候,将对Java 5的依赖抽象掉。这个接口只有一个方法execute(Runnable task)
,它根据线程池的语义和配置,来接受一个执行任务。
TaskExecutor类型:
在Spring发行包中预定义了一些TaskExecutor实现。有了它们,你甚至不需要再自行实现了。
•SimpleAsyncTaskExecutor类
这个实现不重用任何线程,或者说它每次调用都启动一个新线程。但是,它还是支持对并发总数设限,当超过线程并发总数限制时,阻塞新的调用,直到有位置被释放。如果你需要真正的池,请继续往下看。
•SyncTaskExecutor类
这个实现不会异步执行。相反,每次调用都在发起调用的线程中执行。它的主要用处是在不需要多线程的时候,比如简单的test case。
•ConcurrentTaskExecutor类
这个实现是对Java 5 java.util.concurrent.Executor类的包装。有另一个备选, ThreadPoolTaskExecutor类,它暴露了Executor的配置参数作为bean属性。很少需要使用ConcurrentTaskExecutor, 但是如果ThreadPoolTaskExecutor不敷所需,ConcurrentTaskExecutor是另外一个备选。
•SimpleThreadPoolTaskExecutor类
这个实现实际上是Quartz的SimpleThreadPool类的子类,它会监听Spring的生命周期回调。当你有线程池,需要在Quartz和非Quartz组件中共用时,这是它的典型用处。
•ThreadPoolTaskExecutor类
它不支持任何对java.util.concurrent包的替换或者下行移植。Doug Lea和Dawid Kurzyniec对java.util.concurrent的实现都采用了不同的包结构,导致它们无法正确运行。
这个实现只能在Java 5环境中使用,但是却是这个环境中最常用的。它暴露的bean properties可以用来配置一个java.util.concurrent.ThreadPoolExecutor,把它包装到一个TaskExecutor中。如果你需要更加先进的类,比如ScheduledThreadPoolExecutor,我们建议你使用ConcurrentTaskExecutor来替代。
•TimerTaskExecutor类
这个实现使用一个TimerTask作为其背后的实现。它和SyncTaskExecutor的不同在于,方法调用是在一个独立的线程中进行的,虽然在那个线程中是同步的。
•WorkManagerTaskExecutor类
CommonJ 是BEA和IBM联合开发的一套规范。这些规范并非Java EE的标准,但它是BEA和IBM的应用服务器实现的共同标准
这个实现使用了CommonJ WorkManager作为其底层实现,是在Spring context中配置CommonJ WorkManager应用的最重要的类。和SimpleThreadPoolTaskExecutor类似,这个类实现了WorkManager接口,因此可以直接作为WorkManager使用。
参考Book书中的 Spring2.5参考手册.chm里的 ——>整合——>Spring邮件抽象层