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

模式的发展

最开始,在使用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,用于输入用户名,发起请求

  
    A
  
  
    
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传递过来的用户输入的名称 JSPDemo

提交的用户名为:

三层架构,用户注册邮箱激活代码流程_第1张图片
三层架构
  • Web层(表示层)
    用于获取用户输入的参数,通知Service层处理数据,根据Service的返回结果,控制跳转页面展示数据。

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

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

三层架构,用户注册邮箱激活代码流程_第2张图片

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

三层架构,用户注册邮箱激活代码流程_第3张图片
注册激活流程图
前置工作
三层架构,用户注册邮箱激活代码流程_第4张图片
用户数据表的设计
三层架构,用户注册邮箱激活代码流程_第5张图片
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; /
}
三层架构,用户注册邮箱激活代码流程_第6张图片
分包
三层架构,用户注册邮箱激活代码流程_第7张图片
注册页面
前台表单提交及校验
昵称
注意 控件的name最好和domain里面bean的名称一致 bean的属性名称和数据库的字段名称一致
使用jquery.validate.min.js进行前台校验

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


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 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 = "恭喜您注册成功,请点击激活账户" +
                        "" +
                        "http://localhost:8080/active?activeCode=" + activeCode +
                        "";

                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******[email protected]")); // 设置发送者

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

        message.setSubject("用户激活");
        // message.setText("这是一封激活邮件,请点击");

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

        // 3.创建 Transport用于将邮件发送
        Transport.send(message);
    }
}
三层架构,用户注册邮箱激活代码流程_第8张图片
三层架构,用户注册邮箱激活代码流程_第9张图片
@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;
    }
}

你可能感兴趣的:(三层架构,用户注册邮箱激活代码流程)