一、JavaMail的一个综合案例
项目要求:
用户在网站上注册完成后给用户发一封邮件。
且需要用户通过邮件激活后才可以使用。
二、关于此项目的一个整体框架设计
1、分别有以下模块:
(1)注册模块(reg)、登录模块(login)、激活模块(active)、值对象(domain)、过滤器(filter)、工具类(pubs)
(2)其中每一个模块都是采用“铁三角”模式
(3)需要用到的Jar包:
三、主页面index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>邮箱激活用户注册账号的例子</title>
<script type="text/javascript">
function reg(){
document.forms[0].action="<c:url value='/RegServlet'/>"; /* 【注意】object.action [ = sURL ] */
document.forms[0].submit(); /*【注意】 FORM.submit() */
}
function login(){
document.forms[0].action="<c:url value='/LoginServlet'/>";
document.forms[0].submit();
}
</script>
</head>
<body>
<h2>用户注册</h2>
<c:if test="${!empty error}">
用户名或密码错误
<c:remove var="error" scope="session"/>
</c:if>
<c:if test="${sessionScope.user==null}" var="boo">
<form action="" method="post">
Name:<input type="text" name="name"/><br/>
Pwd:<input type="password" name="pwd"/><br/>
Email:<input type="text" name="email"/><br/>
<input type="button" value="登录" onclick="login();"/>
<input type="button" value="注册" onclick="reg();">
</form>
</c:if>
<c:if test="${!boo}">
您已经登录,用户名:${user.name}<br/>
</c:if>
</body>
</html>
result.jsp页面:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<script type="text/javascript">
/* 开始数倒计时数字 */
var i = 4;
function aa(){
i--;
div1.innerHTML=i+" 秒钟后,自动去去登录";
if(i<1){
/* 清除定时器 */
window.clearInterval(tm);
window.location.href="<c:url value='/index.jsp'/>";
}
}
</script>
</head>
<body>
<h2>激活结果</h2>
<c:if test="${boo}">
恭喜,你已经成功激活账号,请前去登录<br/>
<a href="<c:url value='/index.jsp'/>">登录</a>
<!-- 写一个自动登录的功能 -->
<div id="div1">
</div>
</c:if>
<script type="text/javascript">
/* 做一个定时器 */
tm = window.setInterval(aa, 1000);
</script>
<c:if test="${!boo}">
激活不成功,请检查激活码,或另择时间再尝试!
</c:if>
</body>
</html>
四、注册模块(reg)
1、servlet层:RegServlet.java
package cn.hncu.reg.servlet;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hncu.domain.User;
import cn.hncu.pubs.SendMailThread;
import cn.hncu.reg.service.RegService;
import cn.hncu.reg.service.RegServiceImpl;
public class RegServlet extends HttpServlet {
private RegService service = new RegServiceImpl();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
//1.收集参数
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
String email = request.getParameter("email");
//2.组织参数
User user = new User();
user.setName(name);
user.setPwd(pwd);
user.setEmail(email);
//3.调用service层
try {
user = service.reg(user);
if(user!=null){
System.out.println("注册了一个用户:"+user);
//【注意】如果注册成功,则给用户的邮箱 发邮件,让他到他的邮件中去激活
new SendMailThread(user).start();
//4.返回调用结果
out.println("您已经成功注册了,请到邮箱中收取激活邮件,如果没有收到邮件,请再等一会儿再收!!!");
}
} catch (SQLException e) {
out.println("注册失败!");
}
}
}
2、service层:RegService.java
package cn.hncu.reg.service;
import java.sql.SQLException;
import cn.hncu.domain.User;
public interface RegService {
public User reg(User user) throws SQLException;
}
2、service层:RegServiceImpl.java
package cn.hncu.reg.service;
import java.sql.SQLException;
import cn.hncu.domain.User;
import cn.hncu.reg.dao.RegDAO;
import cn.hncu.reg.dao.RegDaoJdbc;
public class RegServiceImpl implements RegService{
private RegDAO dao = new RegDaoJdbc();
@Override
public User reg(User user) throws SQLException {
return dao.reg(user);
}
}
3、dao层:RegDAO.java
package cn.hncu.reg.dao;
import java.sql.SQLException;
import cn.hncu.domain.User;
public interface RegDAO {
public User reg(User user) throws SQLException ;
}
3、dao层:RegDaoJdbc.java
package cn.hncu.reg.dao;
import java.sql.SQLException;
import java.util.UUID;
import org.apache.commons.dbutils.QueryRunner;
import cn.hncu.domain.User;
import cn.hncu.pubs.C3p0Pool;
public class RegDaoJdbc implements RegDAO{
@Override
public User reg(User user) throws SQLException {
String id = UUID.randomUUID().toString().replaceAll("-", "");
String acode = UUID.randomUUID().toString().replaceAll("-", "");
String sql = "insert into users(id,name,pwd,email,active,acode) values(?,?,?,?,?,?)";
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
int n = run.update(sql,id,user.getName(),user.getPwd(),user.getEmail(),"0",acode);
if(n>0){
user.setId(id);
user.setActive("0");
user.setAcode(acode);
return user;
}
return null;
}
}
五、激活模块(active)
1、servlet层:ActiveServlet.java
package cn.hncu.active.servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hncu.active.service.ActiveService;
import cn.hncu.active.service.ActiveServiceImpl;
public class ActiveServlet extends HttpServlet {
private ActiveService service = new ActiveServiceImpl();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String code = request.getParameter("acode");
boolean boo ;
try{
boo = service.active(code);
//【注意】如果激活成功则将结果转发出去
request.setAttribute("boo", boo);
} catch (SQLException e) {
request.setAttribute("boo", false);
}
request.getRequestDispatcher("jsps/result.jsp").forward(request, response);
}
}
2、service层:ActiveService.java
package cn.hncu.active.service;
import java.sql.SQLException;
public interface ActiveService {
public boolean active(String code)throws SQLException ;
}
2、service层:ActiveServiceImpl.java
package cn.hncu.active.service;
import java.sql.SQLException;
import cn.hncu.active.dao.ActiveDAO;
import cn.hncu.active.dao.ActiveDaoJdbc;
public class ActiveServiceImpl implements ActiveService{
private ActiveDAO dao = new ActiveDaoJdbc();
@Override
public boolean active(String code) throws SQLException {
return dao.active(code);
}
}
3、dao层:ActiveDAO.java
package cn.hncu.active.dao;
import java.sql.SQLException;
public interface ActiveDAO {
public boolean active(String code) throws SQLException;
}
3、dao层:ActiveDaoJdbc.java
package cn.hncu.active.dao;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import cn.hncu.pubs.C3p0Pool;
public class ActiveDaoJdbc implements ActiveDAO{
@Override
public boolean active(String code) throws SQLException {
//【注意】首先查询出是不是有激活码,传过来的激活码在数据库中是不是存在
String sql = "select count(1) from users where acode=?";
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
int count = Integer.parseInt(run.query(sql, new ScalarHandler(), code)+"");
if(count==0){
return false;//【注意】此时激活码错误
}else{
//【注意】否则激活码存在的话,将激活码销毁,激活状态以激活
//【注意】单词写对,坑了一把
sql = "update users set active='1',acode='' where acode=?";
run.update(sql, code);
return true;
}
}
}
六、登录模块(login)
1、servlet层:LoginServlet.java
package cn.hncu.login.servlet;
import java.io.IOException;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.hncu.domain.User;
import cn.hncu.login.service.LoginService;
import cn.hncu.login.service.LoginServiceImpl;
public class LoginServlet extends HttpServlet {
private LoginService service = new LoginServiceImpl();
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//1.收集参数
String name = request.getParameter("name");
String pwd = request.getParameter("pwd");
//2.组织参数
User user = new User();
user.setName(name);
user.setPwd(pwd);
//3.调用service层
try {
user= service.login(user);
if(user==null){
request.setAttribute("error", "1");//【注意】如果返回user为空则表示登录的用户未激活
}else{
request.getSession().setAttribute("user", user);
}
} catch (SQLException e) {
request.setAttribute("error", "1");//【注意】如果返回user为空则表示登录的用户未激活
}
//4.返回结果页面
response.sendRedirect(request.getContextPath()+"/index.jsp");
}
}
2、service层:LoginService.java
package cn.hncu.login.service;
import java.sql.SQLException;
import cn.hncu.domain.User;
public interface LoginService {
public User login(User user)throws SQLException ;
}
2、service层:LoginServiceImpl.java
package cn.hncu.login.service;
import java.sql.SQLException;
import cn.hncu.domain.User;
import cn.hncu.login.dao.LoginDAO;
import cn.hncu.login.dao.LoginDaoJdbc;
public class LoginServiceImpl implements LoginService{
private LoginDAO dao = new LoginDaoJdbc();
@Override
public User login(User user) throws SQLException {
return dao.login(user);
}
}
3、dao层:LoginDAO.java
package cn.hncu.login.dao;
import java.sql.SQLException;
import cn.hncu.domain.User;
public interface LoginDAO {
public User login(User user)throws SQLException;
}
3、dao层:LoginDaoJdbc.java
package cn.hncu.login.dao;
import java.sql.SQLException;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import cn.hncu.domain.User;
import cn.hncu.pubs.C3p0Pool;
public class LoginDaoJdbc implements LoginDAO{
@Override
public User login(User user) throws SQLException {
String sql = "select * from users where name=? and pwd=? and active='1'";
QueryRunner run = new QueryRunner(C3p0Pool.getDataSource());
user = run.query(sql, new BeanHandler<User>(User.class), user.getName(),user.getPwd());
return user;
}
}
七、工具包(pubs)
1、C3p0Pool.java工具类:
package cn.hncu.pubs;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
/※※※以后我们开发可以做一个这样的池来使用
public class C3p0Pool {
private static DataSource ds; //单例的池
private static ThreadLocal<Connection> t = new ThreadLocal<Connection>();
static{
try {
ds = new ComboPooledDataSource();
} catch (Exception e) {
throw new RuntimeException("数据库连接池创建失败!", e);
}
}
//以后会用到这个功能
public static DataSource getDataSource(){
return ds;
}
public static Connection getConn() throws SQLException{
Connection con = t.get();
if(con==null){
con = ds.getConnection();
t.set(con);
}
return con;
}
public static void clearConFromThreadLocal(){
t.set(null);
}
}
2、c3p0-config.xml:
<c3p0-config>
<default-config>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="jdbcUrl">
<![CDATA[jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=UTF-8]]>
</property>
<property name="user">root</property>
<property name="password">1234</property>
<!-- 初始化池大小 -->
<property name="initialPoolSize">2</property>
<!-- 最大空闲时间 -->
<property name="maxIdleTime">30</property>
<!-- 最多有多少个连接 -->
<property name="maxPoolSize">10</property>
<!-- 最少几个连接 -->
<property name="minPoolSize">2</property>
<!-- 每次最多可以执行多少个批处理语句 -->
<property name="maxStatements">50</property>
</default-config>
</c3p0-config>
3、发送邮件工具类:SendMailThread.java:
package cn.hncu.pubs;
import java.util.Date;
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMessage.RecipientType;
import cn.hncu.domain.User;
public class SendMailThread extends Thread{
private User user;
public SendMailThread(User user) {
this.user = user;
}
@Override
public void run() {
try {
//【注意】开始发邮件
Properties p = new Properties();
p.setProperty("mail.host", "smtp.sina.com");
p.setProperty("mail.smtp.auth", "true");//认证登录
Session session = Session.getDefaultInstance(p, new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("hncujava", "hncu1234567");
}
});
session.setDebug(true);//【注意】以debug方式 应答,进行通讯
//【注意】准备邮件
MimeMessage msg = new MimeMessage(session);//从session中创建邮件
msg.setFrom(new InternetAddress("hncujava@sina.com"));
msg.setRecipient(RecipientType.TO, new InternetAddress(user.getEmail()));
msg.setSubject("账号激活邮件,城院公司欢迎你");
String info="激活:<a href='http://127.0.0.1:8080/mailWeb1602Test/ActiveServlet?acode="+user.getAcode()+"'>激活</a>";
info = info + "<br/>如果激活未成功,请把地址复制到浏览器进行手动请求以激活:http://127.0.0.1:8080/mailWeb1602Test/ActiveServlet?acode="+user.getAcode();
msg.setContent(info,"text/html;charset=utf-8");
msg.setSentDate(new Date());
//【注意】发送邮件
Transport.send(msg);
} catch (Exception e) {
e.printStackTrace();
}
}
}
八、值对象层(domain)
1、user.java
package cn.hncu.domain;
/**
* private String id;//ID
private String name;//用户名
private String pwd;//密码
private String email;//Email
private String active;//激活状态
private String acode;//激活码
* @author user
*
*/
public class User {
private String id;//ID
private String name;//用户名
private String pwd;//密码
private String email;//Email
private String active;//激活状态
private String acode;//激活码
public User() {
super();
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getActive() {
return active;
}
public void setActive(String active) {
this.active = active;
}
public String getAcode() {
return acode;
}
public void setAcode(String acode) {
this.acode = acode;
}
@Override
public String toString() {
return "User [id=" + id + ", name=" + name + ", pwd=" + pwd
+ ", email=" + email + ", active=" + active + ", acode="
+ acode + "]";
}
}
九、预处理过滤器(PreFilter)
package cn.hncu.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class PreFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
十、web.xml配置文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
<display-name></display-name>
<servlet>
<servlet-name>RegServlet</servlet-name>
<servlet-class>cn.hncu.reg.servlet.RegServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>ActiveServlet</servlet-name>
<servlet-class>cn.hncu.active.servlet.ActiveServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>cn.hncu.login.servlet.LoginServlet</servlet-class>
</servlet>
<filter>
<filter-name>PreFilter</filter-name>
<filter-class>cn.hncu.filter.PreFilter</filter-class>
</filter>
<servlet-mapping>
<servlet-name>RegServlet</servlet-name>
<url-pattern>/RegServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>ActiveServlet</servlet-name>
<url-pattern>/ActiveServlet</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/LoginServlet</url-pattern>
</servlet-mapping>
<filter-mapping>
<filter-name>PreFilter</filter-name>
<url-pattern>/RegServlet</url-pattern>
<url-pattern>/LoginServlet</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
十一、项目执行效果:
1、首页:
2、填写注册信息:
3、跳转到注册成功页面:
4、数据库收到注册信息:
acode码末尾四位为:f32e
5、注册邮箱收到邮件:
收到的邮件中连接的acode码末尾四位为:f32e
6、点击激活:
激活成功的超链接中的acode码末尾四位为:f32e
7、此时刷新数据库,发现acode码被清空,激活状态变为1:
8、用注册的用户名和密码登录: