美文网首页项目设计
三层架构,用户注册邮箱激活代码流程

三层架构,用户注册邮箱激活代码流程

作者: 云承寒 | 来源:发表于2018-08-12 11:21 被阅读73次

模式的发展

最开始,在使用Servlet实现动态页面时,都要在Servlet中嵌入HTML代码输出显示,使得维护成本极大,为了解决这种问题就有了Jsp做页面输出,然而Jsp本质也是Servlet,所以不可避免的要写一些Java代码做脚本,为了不让Jsp内容混乱,就增加了标签,EL表达式来尽量代替Jsp中的Java代码。

MVC模式
  • 模型(Model)
    代表业务逻辑代码与数据库代码,通过JavaBean,传递存储数据。

  • 视图(View)
    代表对数据的展示代码,用于显示模型中的数据,向控制器提交数据,如Jsp。

  • 控制器(Controller)
    通常由Servlet充当控制器,连接着View和Model。

1.  从页面View中获得请求参数
2.  再从Model中通过业务逻辑代码获取需要的数据,通过Bean传递
3.  然后再交给View去显示,更新页面
下面通过一个简单的在A界面输入用户信息,传递给B界面显示,看一下MVC的工作流程。

Model
public class UserBean {

    private String name;

    public UserBean() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


View:界面A.jsp,用于输入用户名,发起请求
<html>
  <head>
    <title>A</title>
  </head>
  <body>
    <form action="/a" method="get">
      <input type="text" name="name" placeholder="用户名">
      <input type="submit" value="提交">
    </form>
  </body>
</html>


Controller:用于获取界面A中用户输入的用户名,将数据封装到JavaBean中,转发给显示界面。
@WebServlet(value = "/a")
public class AServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        UserBean userBean = new UserBean();
        userBean.setName(req.getParameter("name"));
        req.getSession().setAttribute("user",userBean);
        resp.sendRedirect("show_user_info.jsp");
    }
}

View:显示界面B.jsp,用于显示界面A传递过来的用户输入的名称
<jsp:useBean id="user" type="com.bean.UserBean" scope="session"/>
<html>
<head>
    <title>JSPDemo</title>
</head>
<body>
    <p>
        提交的用户名为:<jsp:getProperty name="user" property="name" />
    </p>
</body>
</html>
三层架构
  • Web层(表示层)
    用于获取用户输入的参数,通知Service层处理数据,根据Service的返回结果,控制跳转页面展示数据。

  • service层(业务逻辑层)
    连接Web层与Dao层,根据Dao返回的数据库结果,设置数据返回给Web层的请求结果。

  • dao层(数据访问层)
    操作数据库的CRUD,将结果返回给Service。

用户注册邮箱激活代码流程

注册激活流程图
前置工作
用户数据表的设计
domain用来传递用户数据
public class UserBean {
    private String uid; //用户ID
    private String username;
    private String password;
    private String name;
    private String email;
    private String telephone;
    private Date birthday;
    private String sex;
    private int state; //账号激活状态
    private String code; /
}
分包 注册页面
前台表单提交及校验
<form id="register_form" action="/register" method="post">
      <div class="form-group input-group">
         <span class="input-group-addon">昵称</span>
         <input type="text" name="username" class="form-control" placeholder="用户名">
       </div>
</form>

注意
控件的name最好和domain里面bean的名称一致
bean的属性名称和数据库的字段名称一致
使用jquery.validate.min.js进行前台校验

1.  通过表单id找到表单进行校验
2.  用ajax向后台请求查询数据库,用户数量,通过Json将数据返回给前台

<script type="text/javascript">

        //自定义校验
        $.validator.addMethod(
            "checkUserName", //自定义校验rules
            function (value, element, params) {

                var flag = false;
                $.ajax({
                    "async": false,
                    "url": "/checkUserName",
                    "data": {"username": value},
                    "type": "POST",
                    "dataType": "json",
                    "success": function (data) {
                        flag = data.isExists;
                    }
                })
                //如果返回false代表该校验器不通过
                return !flag;
        });

        
    $(function () {
    $("#register_form").validate({
            rules:{
                "username":{
                    "required": true,
                    "checkUserName": true
                },
                "password": {
                    "required": true,
                    "rangelength": [6, 12]
                },
                "repassword": {
                    "required": true,
                    "rangelength": [6, 12],
                    "equalTo": "#password_id"
                },
                "email": {
                    "required": true,
                    "email": true
                },
                "sex": {
                    "required": true
                }
            },
            messages:{
                "username": {
                    "required": "用户名不能为空",
                    "checkUserName": "该昵称已存在"
                },
                "password": {
                    "required": "密码不能为空",
                    "rangelength": "密码长度6-12位"
                },
               "repassword": {
                    "required": "密码不能为空",
                    "rangelength": "密码长度6-12位",
                    "equalTo": "两次密码不一致"
               },
               "email": {
                    "required": "邮箱不能为空",
                    "email": "邮箱格式不正确"
                },
                "sex": {
                    "required": "没有第三种选择"
                }
            }
        });
    });
</script>
1.  获取到用户输入的用户名
2.  调用UserService去查询数据库,Service会返回Boolean告知成功失败
3.  根据Service返回的Boolean将数据传递给前提
public class CheckUserServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        String userName = req.getParameter("username");
        UserService userService = new UserService();
        boolean isExists = userService.checkUserExists(userName);
        resp.getWriter().println("{\"isExists\":" + isExists + "}");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
}


调用UserDao去查询数据库,根据UserDao的返回值判断返回Boolean
public class UserService {

    private UserDao userDao = new UserDao();
    public boolean checkUserExists(String userName) {

        Long aLong = 0L;
        try {
            aLong = userDao.checkUserExists(userName);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        return aLong > 0 ? true : false;
    }
}


查询数据库中的此用户数量,将结果返回给Service
public class UserDao {
    public Long checkUserExists(String userName) throws SQLException {
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        String sql = "select count(*) from t_user where username = ?";
        Long aLong = (Long) runner.query(sql,new ScalarHandler(),userName);
        return aLong;
    }
}

用户注册
Web层

注意
1.  封装Bean时birthday用的是Date数据,BeanUtils框架需要转换parse

public class RegisterServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html;charset=UTF-8");

        Map<String, String[]> parameters = req.getParameterMap();
        UserBean userBean = new UserBean();
        try {

            //前面封装的Bean,日期是Date类型
            //BeanUtils需要转换一下类型
            ConvertUtils.register(new Converter() {
                @Override
                public Object convert(Class aClass, Object o) {
                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
                    Date date = null;
                    try {
                        //额外注意
                        date = format.parse(o.toString());
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                    return date;
                }
            }, Date.class);

            BeanUtils.populate(userBean, parameters);
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        //将用户没传递的数据补全
        userBean.setUid(CommonsUtils.getUUID());
        userBean.setState(0);
        String activeCode = CommonsUtils.getUUID();
        userBean.setCode(activeCode);

        //调用Service注册
        UserService userService = new UserService();
        boolean isRegisterSuccess = userService.registerUser(userBean);
        if (isRegisterSuccess) {

            try {
                String emailMsg = "恭喜您注册成功,请点击激活账户" +
                        "<a href='http://localhost:8080/active?activeCode=" + activeCode + "'>" +
                        "http://localhost:8080/active?activeCode=" + activeCode +
                        "</a>";

                MailUtils.sendMail(userBean.getEmail(),emailMsg);
            } catch (MessagingException e) {
                e.printStackTrace();
            }
            resp.sendRedirect("/login.jsp");
        } else {
            resp.getWriter().println("注册失败");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req, resp);
    }
}
Service层
public class UserService {

    private UserDao userDao = new UserDao();
    public boolean registerUser(UserBean userBean) {

        int row = 0;
        try {
            row = userDao.registerUser(userBean);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return row > 0 ? true : false;
    }
}


Dao层
public class UserDao {

    public int registerUser(UserBean userBean) throws SQLException {
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        String sql = "insert into t_user values(?,?,?,?,?,?,?,?,?,?)";
        int row = runner.update(sql,
                userBean.getUid(),
                userBean.getUsername(),
                userBean.getPassword(),
                userBean.getName(),
                userBean.getEmail(),
                userBean.getTelephone(),
                userBean.getBirthday(),
                userBean.getSex(),
                userBean.getState(),
                userBean.getCode());
        return row;
    }
}
邮箱激活注册账号
注册成功后用Mail发送邮件,附带着请求激活地址,和UUID来做激活码。
所谓的邮箱账号激活,其实就是修改用户表中用户的state

public class MailUtils {

    public static void sendMail(String email, String emailMsg)
            throws AddressException, MessagingException {

        // 1.创建一个程序与邮件服务器会话对象 Session
        Properties props = new Properties();
        props.setProperty("mail.transport.protocol", "SMTP");
        props.setProperty("mail.host", "smtp.163.com"); //发邮件的服务器地址
        props.setProperty("mail.smtp.auth", "true");//需要验证,不验证会提示没有权限发送
        //指定验证为true

        // 创建验证器
        Authenticator auth = new Authenticator() {
            public PasswordAuthentication getPasswordAuthentication() {
                //发送邮件的邮箱账户 + 授权码 
                return new PasswordAuthentication("133******53", "******");
            }
        };

        Session session = Session.getInstance(props, auth);

        // 2.创建一个Message,它相当于是邮件内容
        Message message = new MimeMessage(session);

        message.setFrom(new InternetAddress("133******53@163.com")); // 设置发送者

        message.setRecipient(RecipientType.TO, new InternetAddress(email)); // 设置发送方式与接收者

        message.setSubject("用户激活");
        // message.setText("这是一封激活邮件,请<a href='#'>点击</a>");

        message.setContent(emailMsg, "text/html;charset=utf-8");

        // 3.创建 Transport用于将邮件发送
        Transport.send(message);
    }
}
@WebServlet(value = "/active")
public class ActiveServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        resp.setContentType("text/html; charset=UTF-8");

        String activeCode = req.getParameter("activeCode");
        UserService userService = new UserService();
        boolean isActiveUser = userService.activeUser(activeCode);
        if (isActiveUser){
            resp.sendRedirect("/login.jsp");
        }else{
            resp.getWriter().println("用户未激活");
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        doGet(req,resp);
    }
}
Service层
public class UserService {

    private UserDao userDao = new UserDao();
    public boolean activeUser(String activeCode) {
        int row = 0;
        try {
            row = userDao.activeUser(activeCode);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return row > 0 ? true : false;
    }
}


Dao层
public class UserDao {
    public int activeUser(String activeCode) throws SQLException {
        QueryRunner runner = new QueryRunner(DataSourceUtils.getDataSource());
        String sql = "update t_user set state = ? where code = ?";
        int update = runner.update(sql, 1, activeCode);
        return update;
    }
}

相关文章

  • 三层架构,用户注册邮箱激活代码流程

    模式的发展 最开始,在使用Servlet实现动态页面时,都要在Servlet中嵌入HTML代码输出显示,使得维护成...

  • 整理一下在 npmjs.com 上面发布资源包踩过的坑

    正常流程就不说了,网上有很多,比如写代码、打包、注册、登录、发布等。 邮箱要激活 在 npmjs.com 上面注册...

  • java web 邮箱找回密码

    邮箱激活 背景:几乎每个网站或论坛之类的用户注册后都需要通过发送邮件到邮箱激活用户。 设计: 激活步骤: 发送激活...

  • 用户注册邮箱激活

    itsdangerous用法 1. 安装 2. 用法 加密 解密 使用itsdangerous对用户注册发送的激活...

  • javamail用户注册邮箱激活

    创建一封简单的电子邮件 首先创建一个 Java 工程,把下载好的 javax.mail.jar 作为类库加入工程,...

  • git使用

    1、注册账号登录github.com进行账号注册,邮箱激活2、git流程图https://www.runoob.c...

  • 常见问题汇总

    新注册的用户在使用所有服务前需要首先激活账户。请前往注册时使用的邮箱服务器查阅激活邮件根据邮件提示激活账户。 如果...

  • 用户通过邮箱注册后的激活处理方案

    进入注册页 验证邮箱正确性 生成邮箱账号激活码code(自加密) 发送至注册邮箱的激活邮件,包含激活URL 点击激...

  • 激活邮件发送工具

    用户注册账号之后需要给注册邮箱发送邮件激活验证,使用工具javax.mail-1.5.1.jar service层...

  • laravel邮箱认证

    继上文laravel用户认证,本篇将实现新用户需要邮箱验证才能注册成功 邮箱认证流程 分为两步: 发送认证邮件 —...

网友评论

    本文标题:三层架构,用户注册邮箱激活代码流程

    本文链接:https://www.haomeiwen.com/subject/gpajbftx.html