用户注册的邮箱激活模块的设计与实现
----------------------------------------------------------------------------------------------
[版权申明:本文系作者原创,转载请注明出处]
文章出处:http://blog.csdn.net/sdksdk0/article/details/52144698
作者:朱培 ID:sdksdk0 邮箱: zhupei@tianfang1314.cn
--------------------------------------------------------------------------------------------
本文主要内容是分享用户注册时需要进行的邮箱激活功能的实现。在我们都知道在一个网站中,用户注册后需要来一个邮箱进行激活是很常见的功能,那么我们今天就来学习一下这个邮箱验证功能.这里以我的一个小项目“网上书店”的这个模块来说明这个邮箱激活的功能!采用的是mvc模式开发!
一、数据库设计
首先我们需要对用户注册的表进行设计,里面要添加激活码的字段和激活的状态的字段。我们可以看到页面是这样的,有5个需要填写的字段,然后加上我们这个激活码的就有7个了。
这里我采用的是mysql数据库。actived表示激活码的状态位,0表示未激活,1表示激活了.
CREATE TABLE customers( id VARCHAR(100) PRIMARY KEY, username VARCHAR(100) NOT NULL UNIQUE, PASSWORD VARCHAR(100) NOT NULL, phone VARCHAR(20) NOT NULL UNIQUE, address VARCHAR(255) NOT NULL , email VARCHAR(50) NOT NULL UNIQUE, CODE VARCHAR(200) UNIQUE, --激活码 actived BIT(1) --激活码的状态位,0表示未激活,1表示激活 )
二、bean设计
新建一个Customer.java
生成其get\set方法即可。
private String id; private String username; private String password; private String phone; private String address; private String email; private String code; //激活码 private boolean actived; //账户是否激活
三、接口设计
新建一个CustomerDao.java
有保存密码、更新激活状态、登录等。
public interface CustomerDao { void save(Customer customer); void update(Customer customer); Customer findByCode(String code); Customer find(String username, String password); }
接口的实现类
CustomerDaoImpl.java
我们主要就是在这个里面进行与数据库的交互
public class CustomerDaoImpl implements CustomerDao { private QueryRunner qr=new QueryRunner(C3P0Util.getDataSource()); public void save(Customer customer) { try { qr.update("insert into customers (id,username,password,phone,address,email,code,actived) values (?,?,?,?,?,?,?,?)", customer.getId(),customer.getUsername(),customer.getPassword(),customer.getPhone(),customer.getAddress(), customer.getEmail(),customer.getCode(),customer.isActived()); } catch (SQLException e) { throw new RuntimeException(e); } } public void update(Customer customer) { try { qr.update("update customers set username=?,password=?,phone=?,address=?,email=?,code=?,actived=? where id=?", customer.getUsername(),customer.getPassword(),customer.getPhone(),customer.getAddress(), customer.getEmail(),customer.getCode(),customer.isActived(),customer.getId()); } catch (SQLException e) { throw new RuntimeException(e); } } public Customer findByCode(String code) { try { return qr.query("select * from customers where code=?", new BeanHandler<Customer>(Customer.class),code); } catch (SQLException e) { throw new RuntimeException(e); } } public Customer find(String username, String password) { try { return qr.query("select * from customers where username=? and password=?", new BeanHandler<Customer>(Customer.class),username,password); } catch (SQLException e) { throw new RuntimeException(e); } } }
四、Service的实现
新建一个service类:接口BusinessService.java
//用户注册 void registCustomer(Customer customer); //根据激活码获取用户信息 Customer findByCode(String code); //激活客户的账户 void activeCustomer(Customer customer); //根据用户名或密码登录,如果账户没有激活就返回null Customer login(String username,String password);
接口的实现
@Override public void registCustomer(Customer customer) { customer.setId(UUID.randomUUID().toString()); customerDao.save(customer); } @Override public Customer findByCode(String code) { return customerDao.findByCode(code); } @Override public void activeCustomer(Customer customer) { if(customer==null) throw new RuntimeException("数据不能为空"); if(customer.getId()==null) throw new RuntimeException("更新数据的主键不能为空"); customerDao.update(customer); } @Override public Customer login(String username, String password) { Customer customer = customerDao.find(username,password); if(customer==null) return null; if(!customer.isActived()) return null; return customer; }
五、Servlet的实现
这里是控制层:激活邮箱我使用的是在另外的一个线程中实现的。SendMailThread.java中实现。
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String op=request.getParameter("op"); if("customerRegist".equals(op)){ customerRegist(request,response); }else if("activeCustomer".equals(op)){ activeCustomer(request,response); }else if("login".equals(op)){ login(request,response); }else if("logout".equals(op)){ logout(request,response); } } //注销登录 private void logout(HttpServletRequest request, HttpServletResponse response) throws IOException { request.getSession().removeAttribute("customer"); response.getWriter().write("注销成功!2秒后转向主页"); response.setHeader("Refresh", "2;URL="+request.getContextPath()); } //用户登录 private void login(HttpServletRequest request, HttpServletResponse response) throws IOException { String username=request.getParameter("username"); String password=request.getParameter("password"); Customer customer=s.login(username, password); if(customer==null){ response.getWriter().write("错误的用户名或密码,或者您的账户还没有激活!5秒后转向登陆页"); response.setHeader("Refresh", "5;URL="+request.getContextPath()+"/login.jsp"); return; } request.getSession().setAttribute("customer", customer); response.getWriter().write("登陆成功!2秒后转向主页"); response.setHeader("Refresh", "2;URL="+request.getContextPath()); } //激活邮箱 private void activeCustomer(HttpServletRequest request, HttpServletResponse response) throws IOException { String code=request.getParameter("code"); Customer customer=s.findByCode(code); if(customer==null){ response.getWriter().write("发生未知错误,请重新输入"); return ; } customer.setActived(true); s.activeCustomer(customer); response.getWriter().write("激活成功!2秒后转向主页"); response.setHeader("Refresh", "2;URL="+request.getContextPath()); } //新用户注册,发送激活邮件 private void customerRegist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //封装数据 Customer customer=WebUtil.fillBean(request,Customer.class); customer.setCode(UUID.randomUUID().toString()); //发送邮件,单独启动一个线程 SendMailThread smt=new SendMailThread(customer); smt.start(); s.registCustomer(customer); request.setAttribute("message", "注册成功,我们已经发送了一封激活邮件到您的"+customer.getEmail()+"中,请及时激活您的账户"); request.getRequestDispatcher("/message.jsp").forward(request, response); }
六、邮件的发送
我们刚才将其抽取到一个线程中来实现.我这里使用的是万网的mail.host,所以其属性值为smtp.mxhichina.com,如果你用的是163邮箱的话,就替换为smtp.163.com即可。
对于下面点击激活后跳转的网址为你的工程的名字,这个可以根据实际情况配置,也可以直接引入公网域名来使用。
<a href='http://localhost:8080/BookStore/servlet/ClientServlet?op=activeCustomer&code="+customer.getCode()+"'>激活</a>
public class SendMailThread extends Thread{ private Customer customer; public SendMailThread(Customer customer){ this.customer=customer; } public void run(){ Properties props=new Properties(); props.setProperty("mail.transport.protocol", "smtp");//规范规定的参数 props.setProperty("mail.host", "smtp.mxhichina.com");//这里使用万网的邮箱主机 props.setProperty("mail.smtp.auth", "true");//请求认证,不认证有可能发不出去邮件。 Session session=Session.getInstance(props); MimeMessage message=new MimeMessage(session); try { message.setFrom(new InternetAddress("xingtian@tianfang1314.cn")); //这里可以根据你的实际情况更改邮箱号 message.setRecipients(Message.RecipientType.TO, customer.getEmail()); message.setSubject("来自指令汇科技书店的注册邮件"); message.setContent("","text/html;charset=UTF-8"); message.setContent("亲爱的"+customer.getUsername()+":<br/>请猛戳下面激活您的账户<a href='http://localhost:8080/BookStore/servlet/ClientServlet?op=activeCustomer&code="+customer.getCode()+"'>激活</a><br/>", "text/html;charset=UTF-8"); message.saveChanges(); Transport ts = session.getTransport(); ts.connect("你的邮箱账号", "邮箱密码"); ts.sendMessage(message, message.getAllRecipients()); ts.close(); } catch (AddressException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchProviderException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (MessagingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
七、界面
关于注册的这个界面我是真的不写了,其实就是一个表单而已,里面通过一个servlet转向那个servlet就可以了。记得去web.xml中配置一个servlet,或者你直接用注解也是可以的。
<form action="${pageContext.request.contextPath}/servlet/ClientServlet?op=customerRegist" method="post">
效果如下:
源码地址:https://github.com/sdksdk0/BookStore