一、准备工作(本案例测试使用的为QQ邮箱)
1.前提知识
动手实践之前,你最好对以下知识有所了解:
- JSP和Servlet
- Maven
- MySQL
- c3p0
- SMTP协议和POP3协议
邮件收发过程
2.邮箱准备☆☆☆☆
在了解的上述内容之后,要实现这个案例,首先我们还得有两个邮箱账号,一个用来发送邮件,一个用来接收邮件。本案例使用QQ邮箱向163邮箱发送激活邮件,因此需要登录QQ邮箱,在设置->账户面板中开启POP3/SMTP服务,以允许我们通过第三方客户端发送邮件:
还要注意的是,登录以下服务: POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务时,需要用到授权码而不是QQ密码,授权码是用于登录第三方邮件客户端的专用密码。因此我们需要获得授权码,以在后面的程序中使用。
- 实现步骤
- 添加java包依赖☆☆☆☆
使用JavaMail发送邮件需要用到mail.jar和activation.jar两个包。
<!-- 使用mail使用添加mail和activtion两个jar包 --> <dependency> <groupId>javax.mail</groupId> <artifactId>mail</artifactId> <version>1.4.7</version> </dependency> <!-- https://mvnrepository.com/artifact/javax.activation/activation --> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> |
- 数据库表(示例)
其中要注意的地方是state字段(用来判断用户账号是否激活)和code字段(激活码)。
页面
- 主要的业务逻辑☆☆☆☆
先想一下,我们的整个流程应该是这样的:
- 用户填写相关信息,点击注册按钮
- 系统先将用户记录保存到数据库中,其中用户状态为未激活
- 系统发送一封邮件并通知用户去验证
- 用户登录邮箱并点击激活链接
- 系统将用户状态更改为已激活并通知用户注册成功
- 编辑reg.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme() + "://" +request.getServerName()+":" +request.getServerPort() +path +"/"; %> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>无标题文档</title> <script type="text/javascript" src="<%=basePath %>js/jquery-1.42.min.js"></script> <link href="<%=basePath %>css/bootstrap.min.css" rel="stylesheet" type="text/css"> <link href="<%=basePath %>css/font-awesome.min.css" rel="stylesheet" type="text/css"> <link href="<%=basePath %>css/base.css" rel="stylesheet" type="text/css"> <link href="<%=basePath %>css/reg.css" rel="stylesheet" type="text/css"> <link rel="stylesheet" href="<%=basePath %>css/headbott.css" type="text/css" /> <link rel="stylesheet" href="<%=basePath %>css/ace.min.css" type="text/css" /> </head> <body> <!-- 头部 --> <jsp:include page="frontHead.jsp"></jsp:include> <!-- 头部 --> <div class="login-container"> <div class="space-6"></div> <div class="position-relative"> <div id="signup-box" class="signup-box widget-box no-border"> <div class="widget-body"> <div class="widget-main"> <h4 class="header green lighter bigger"> <i class="ace-icon fa fa-users blue"></i> 用户注册 </h4> <div class="space-6"></div> <p>填写信息:</p> <form action="<%= basePath%>user/regist.action" method="post"> <fieldset> <label class="block clearfix"> <span class="block input-icon input-icon-left"> <input type="text" class="form-control" placeholder="邮箱或手机号码" name="usEmail"/> <i class="ace-icon fa fa-envelope"></i> </span> </label> <label class="block clearfix"> <span class="block input-icon input-icon-left"> <input type="text" class="form-control" placeholder="用户名" name="usName" /> <i class="ace-icon fa fa-user"></i> </span> </label> <label class="block clearfix"> <span class="block input-icon input-icon-left"> <input type="password" class="form-control" placeholder="密码" name="usPassword" /> <i class="ace-icon fa fa-lock"></i> </span> </label> <!-- <label class="block clearfix"> <span class="block input-icon input-icon-left"> <input type="password" class="form-control" placeholder="确认密码" /> <i class="ace-icon fa fa-retweet"></i> </span> </label> --> <!--验证码--> <!-- <label class="block clearfix"> <span> <input type="text" class="" placeholder="验证码" /> <button class="btn btn-default"> <a>点击获取验证码</a> </button> </span> </label> --> <label class="block"> <input type="checkbox" class="ace" /> <span class="lbl"> 接受 <a href="#">用户协议</a> </span> </label> <div class="space-24"></div> <p class="error-message" name="error">${errMsg}</p> <div class="clearfix"> <button type="reset" class="width-30 pull-left btn btn-sm"> <i class="ace-icon fa fa-refresh"></i> <span class="bigger-110">重置</span> </button> <button type="submit" class="width-65 pull-right btn btn-sm btn-success"> <span class="bigger-110">注册</span> <i class="ace-icon fa fa-arrow-right icon-on-right"></i> </button> </div> </fieldset> </form> <!--第三方--> <div class="social-or-login center"> <span class="bigger-110">第三方登录</span> </div> <div class="space-6"></div> <div class="social-login center"> <a href="#"> <img src="<%=basePath %>images/weixin.png"> </a> <a href="#"> <img src="<%=basePath %>images/qq.png"> </a> <a href="#"> <img src="<%=basePath %>images/sina.png"> </a> </div> </div> <div class="toolbar center"> <a href="<%=basePath %>user/login.action" data-target="#login-box" class="back-to-login-link"> <i class="ace-icon fa fa-arrow-left"></i> 返回登录 </a> </div> </div> <!-- /.widget-body --> </div> </div> </div> </div> <div id="bottom"> <div class="bottom-ggt"> <a href=""><img src="images/bottbom_68.jpg" alt="" /></a> </div> <div class="zc-yqlink"> <ul> <li><a href="">阿里巴巴集团</a></li> <li><a href="">淘宝网</a></li> <li><a href="">天猫</a></li> <li><a href="">聚划算</a></li> <li><a href="">全球速卖通</a></li> <li><a href="">阿里巴巴国际交易市场</a></li> <li><a href="">1688</a></li> <li><a href="">阿里妈妈</a></li> <li><a href="">阿里旅行</a></li> <li><a href="">阿里云计算</a></li> <li><a href="">阿里巴巴集团</a></li> <li><a href="">淘宝网</a></li> <li><a href="">天猫</a></li> <li><a href="">聚划算</a></li> <li><a href="">全球速卖通</a></li> <li><a href="">阿里巴巴国际交易市场</a></li> <li><a href="">1688</a></li> <li><a href="">阿里妈妈</a></li> <li><a href="">阿里云计算</a></li> </ul> </div> <div class="footer-bd"> <a href=" ">关于淘宝</a> <a href=" ">合作伙伴</a> <a href=" ">营销中心</a> <a href=" ">廉正举报</a> <a href=" ">联系客服</a> <a href=" ">开放平台</a> <a href=" ">诚征英才</a> <a href=" ">联系我们</a> <a href=" ">网站地图</a> <a href=" ">法律声明</a> <em>© 2003-2015 Taobao.com 版权所有</em><br> <br> <span>网络文化经营许可证:<a href=" ">浙网文[2013]0268-027号</a></span> <b>|</b> <span data-spm-protocol="i">增值电信业务经营许可证:<a href="">浙B2-20080224-1</a></span> <b>|</b> <span>信息网络传播视听节目许可证:1109364号</span> <b>|</b> <span>举报电话:0571-81683755</span> </div> </div> </body> </html> |
页面效果
- 编辑实体类
package com.zhiyou100.crowdFunding.vo; import java.util.Date; public class User { private int usId; private String usEmail; private String usName; private String usPassword; private double usMoney; private String usIdcard; private String usPhone; private String usAddress; private int usRole; private String usSex; private String usCode; private Date usCreateTime; private Date usUpdateTime; public User() { super(); } public int getUsId() { return usId; } public void setUsId(int usId) { this.usId = usId; } public String getUsEmail() { return usEmail; } public void setUsEmail(String usEmail) { this.usEmail = usEmail; } public String getUsName() { return usName; } public void setUsName(String usName) { this.usName = usName; } public String getUsPassword() { return usPassword; } public void setUsPassword(String usPassword) { this.usPassword = usPassword; } public double getUsMoney() { return usMoney; } public void setUsMoney(double usMoney) { this.usMoney = usMoney; } public String getUsIdcard() { return usIdcard; } public void setUsIdcard(String usIdcard) { this.usIdcard = usIdcard; } public String getUsPhone() { return usPhone; } public void setUsPhone(String usPhone) { this.usPhone = usPhone; } public String getUsAddress() { return usAddress; } public void setUsAddress(String usAddress) { this.usAddress = usAddress; } public int getUsRole() { return usRole; } public void setUsRole(int usRole) { this.usRole = usRole; } public String getUsSex() { return usSex; } public void setUsSex(String usSex) { this.usSex = usSex; } public String getUsCode() { return usCode; } public void setUsCode(String usCode) { this.usCode = usCode; } public Date getUsCreateTime() { return usCreateTime; } public void setUsCreateTime(Date usCreateTime) { this.usCreateTime = usCreateTime; } public Date getUsUpdateTime() { return usUpdateTime; } public void setUsUpdateTime(Date usUpdateTime) { this.usUpdateTime = usUpdateTime; } @Override public String toString() { return "【User】 usId=" + usId + ", usEmail=" + usEmail + ", usName=" + usName + ", usPassword=" + usPassword + ", usMoney=" + usMoney + ", usIdcard=" + usIdcard + ", usPhone=" + usPhone + ", usAddress=" + usAddress + ", usRole=" + usRole + ", usSex=" + usSex + ", usCode=" + usCode + ", usCreateTime=" + usCreateTime + ", usUpdateTime=" + usUpdateTime + "\n"; } } |
- 添加编辑controller☆☆☆☆
// 进入注册页面 @RequestMapping("/reg") public ModelAndView reg() throws Exception { ModelAndView mav = new ModelAndView("p2-crowdfunding/reg.jsp"); return mav; } @RequestMapping("/toregist") public String toemail() { return "regist"; } @RequestMapping("/regist") public void regist(User user, HttpSession httpSession, HttpServletResponse response, HttpServletRequest request) throws Exception { user.setUsRole(0);// 刚注册默认是没有激活状态 // user.setActivated(false); // 刚注册默认是没有激活状态 user.setUsCode(UUID.randomUUID().toString()); user.setUsPassword(MyPasswordEncrypt.encryptPassword(user.getUsPassword())); // 注册用户 if (userService.findByEmail(user.getUsEmail()) == null) { userService.add(user); // userService.saveUser(user); } else { response.setContentType("text/html;charset=utf-8"); response.getWriter().write("注册失败,该邮箱已被注册"); throw new RuntimeException("注册失败,该邮箱已被注册"); } // 查看是否注册成功,为实体类User的id赋值 User findUser = userService.findByEmail(user.getUsEmail()); if (findUser != null) { user.setUsId(findUser.getUsId()); } else { throw new RuntimeException("注册用户失败"); } // 注册成功后,发送账户激活链接 httpSession.setAttribute("user", user); EmailUtils.sendAccountActivateEmail(user); try { response.setContentType("text/html;charset=utf-8"); response.getWriter().write("激活邮件已经发送,请注意提醒查收"); } catch (IOException e) { e.printStackTrace(); } } @RequestMapping("/activate") public void activate(String id, String checkCode, HttpServletResponse response) throws Exception { int idInt = Integer.parseInt(id); // 根据用户id查找用户 User user = userService.findById(idInt); // 验证无误,状态更改为1,即激活 if (GenerateLinkUtils.verifyCheckcode(user, checkCode)) { // 修改状态 int activated = 1; userService.doUpdateRole(idInt); user.setUsRole(1); // user.setActivated(true); try { response.setContentType("text/html;charset=utf-8"); response.getWriter().write("恭喜,激活成功!"); } catch (IOException e) { e.printStackTrace(); } } } |
- EmailUtils工具类☆☆☆☆
package com.zhiyou100.crowdFunding.utils; import java.util.Date; import java.util.Properties; import javax.mail.Authenticator; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.PasswordAuthentication; import javax.mail.Session; import javax.mail.Transport; import javax.mail.internet.InternetAddress; import javax.mail.internet.MimeMessage; import com.zhiyou100.crowdFunding.vo.User; public class EmailUtils { private static final String FROM = "[email protected]"; public static void sendAccountActivateEmail(User user) { Session session = getSession(); MimeMessage message = new MimeMessage(session); try { message.setSubject("这是一封激活账号的邮件"); message.setSentDate(new Date()); //setFrom 表示用哪个邮箱发送邮件 message.setFrom(new InternetAddress(FROM)); message.setRecipient(Message.RecipientType.TO, new InternetAddress(user.getUsEmail())); message.setContent(user.getUsName()+"先生/女士您好,请点击此链接激活账号"+GenerateLinkUtils.generateActivateLink(user) ,"text/html;charset=utf-8"); Transport.send(message); } catch (MessagingException e) { e.printStackTrace(); } } public static Session getSession() { Properties props = new Properties(); props.setProperty("mail.transport.protocol", "smtp");//指定发送的邮箱的邮箱协议 props.setProperty("mail.smtp.host","smtp.qq.com");//指定SMTP服务器 props.setProperty("mail.smtp.port", "25"); //smtp是发信邮件服务器,端口是25 props.setProperty("mail.smtp.auth","true");//指定是否需要SMTP验证 Session session = Session.getInstance(props, new Authenticator() { @Override protected PasswordAuthentication getPasswordAuthentication() { return new PasswordAuthentication(FROM, "wbmnqmwoxnwxjjgi");//SMTP服务器密码 } }); return session; } } |
- 编辑GenerateLinkUtils工具类☆☆☆☆
package com.zhiyou100.crowdFunding.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import com.zhiyou100.crowdFunding.vo.User; public class GenerateLinkUtils { private static final String CHECK_CODE = "checkCode"; public static String generateActivateLink(User user) { return "http://192.168.4.201:8080/crowdFunding/user/activate.action?id="+user.getUsId()+"&"+CHECK_CODE+"="+generateCheckcode(user); } private static String generateCheckcode(User user) { String userName = user.getUsName(); String randomCode = user.getUsCode(); return md5(userName+":"+randomCode); } private static String md5(String string) { MessageDigest md = null; try { md = MessageDigest.getInstance("md5");//返回实现指定摘要算法的 MessageDigest 对象。 md.update(string.getBytes());//使用指定的 byte 数组更新摘要。 byte[] md5Bytes = md.digest();//通过执行诸如填充之类的最终操作完成哈希计算。在调用此方法之后,摘要被重置。 return bytes2Hex(md5Bytes);//本信息摘要 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); System.out.println("md5这里出错了"); } return null; } //二行制转字符串 private static String bytes2Hex(byte[] byteArray) { StringBuffer strBuf = new StringBuffer(); for (int i = 0; i < byteArray.length; i++) { if(byteArray[i] >= 0 && byteArray[i] < 16) { strBuf.append("0"); } strBuf.append(Integer.toHexString(byteArray[i] & 0xFF)); } return strBuf.toString(); } public static boolean verifyCheckcode(User user, String checkCode) { boolean flag = generateCheckcode(user).equals(checkCode); return flag; } } GitHub地址:https://github.com/16638240445/crowdFunding |