黑马旅游网(2):用户注册

  • 1 业务描述
  • 2 业务分析
    • 2.1 业务流程抽象
    • 2.2 可能的技术难点与解决策略
  • 3 代码实现
    • 3.1 信息验证与提交
      • 3.1.1 前端
      • 3.1.2 Servlet
      • 3.1.3 Service
      • 3.1.4 Dao
    • 3.2 邮件激活
      • 3.2.1 Servlet
      • 3.2.2 Service
      • 3.2.3 Dao

项目课程链接:https://www.bilibili.com/video/BV1CE411E7h4
完整课程连接:https://www.bilibili.com/video/BV1uJ411k7wy

1 业务描述

注册业务旨在收集和管理用户的个人信息,是未来提供个性化服务的基础。相应的前端页面如下方静态H5页面图所示:


网页中提供多个输入框,并给出对应的提示信息,逐步引导用户根据提示向输入框中填写信息。最终点击下方的 注册 按钮完成用户注册。


进一步地,为了验证联系方式的有效性,在完成注册功能后,前端还会提示用户执行 激活 操作:通过向用户注册时填写的邮箱发送验证邮件。在邮件正文中引导用户点击相应的超链接完成账户激活,并在激活页面提供登录链接,引导用户登录网站。整个注册业务流程完毕。


2 业务分析

2.1 业务流程抽象

在本案例中,注册业务分为两阶段:

  1. 注册阶段:用户根据前端页面的提示信息填写相应内容,进而提交至后台处理,最终将信息保存至数据库。
  2. 激活阶段:系统后台自动向用户填写的邮件地址发送一封 激活邮件,邮件中包含一个激活链接。用户通过点击激活链接向服务器发送一个请求,服务器在接收到该请求后,再向用户浏览器回写激活成功信息。

2.2 可能的技术难点与解决策略

  1. 避免机器人批量注册
    添加验证码,优先核对,不满足直接跳出方法。(后续单独写一篇博客分析此功能)

  2. 如何保证激活用户的唯一性?
    tab_user 表中添加字段:active_code 。它是一种保证唯一性的序列码,本案例中调用 Java 中的工具类 UUID 生成序列并作为用户的激活码。在用户注册时生成并与用户信息一并写入数据库,同时向用户提交的邮件地址发送一封带有激活码链接的邮件。只有用户在邮件中点击了这个链接,使用带有激活码的URL向服务器发出请求,服务器才能收到用户“发来的”激活码,并在后端完成校验并向用户端浏览器回写响应信息。

  3. 如何定义和处理激活状态?
    tab_user 表中添加两个字段:statusstatus 用于标注用户是否激活,它只有两种可能的取值:Y(已激活)和 N(未激活)。在用户刚刚提交注册表单时,后端在数据库中添加用户信息时对该字段设为 N,当用户在激活邮件中点击激活链接向服务器发送激活请求时,服务器在核对通过的前提下将该字段修改为 Y

  4. 前端校验用户填写的表单信息:正则表达式校验,这里参考了暮光乐鱼的博客,他的正则表达式写的要比我的好。

    1. 非空 :.+
    2. 字符集 :^\w{6,20}$
    3. 手机号 :1(3|4|5|7|8)\d{9}
    4. 邮箱 :^\w+(.\w+)*@\w+(.\w+)+$

3 代码实现

3.1 信息验证与提交

3.1.1 前端

  1. 表单数据验证与提交主函数

    /*如果此方法:无返回或返回true,则表单提交返回false,则表单不提交*/
    $(function () {// 当表单提交时调用所有的校验方法$("#registerForm").submit(function () {// 1.发送数据到服务器if (checkUsername() &&           // 用户名校验checkPassword() &&          // 密码校验checkEmail() &&              // 邮箱校验checkName() &&               // 姓名校验checkTelephone() &&          // 手机号校验checkSex() &&               // 性别校验checkBirthday() &&           // 生日校验checkCode()                  // 验证码校验) {         // 校验成功// 发送AJAX请求,提交表单数据    username=Alex&password=123 ...$.post("user/register", $(this).serialize(), function (data) {// 处理响应数据 data {flag:true/false, errorMsg:"..."}if (data["flag"]) { // 注册成功// 跳转成功页面location.href = "register_ok.html";} else {          // 注册失败// 在注册页面添加提示信息$("#errorMsg").html(data["errorMsg"]);}});} else { // 校验失败}// 2.跳转页面return false;});// 当某一个组件失去焦点时,调用对应的校验方法$("#username").blur(checkUsername);$("#password").blur(checkPassword);$("#email").blur(checkEmail);$("#name").blur(checkName);$("#telephone").blur(checkTelephone);$("#sex").blur(checkSex);$("#birthday").blur(checkBirthday);$("#check").blur(checkCode);
    })
    
  2. 用户名校验

    // 校验用户名
    function checkUsername() {// 1.获取用户名let username = $("#username").val();// 2.定义正则let reg_username = /^\w{8,20}$/;// 正则:单词字符,以单词开头,以单词结尾,长度8~20位,包含8和20// 3.判断并给出提示信息let flag = reg_username.test(username);if (flag) {      // 校验合法$("#username").css("border", "");} else {      // 校验非法// 输入栏边框变红$("#username").css("border", "2px solid red");}return flag;
    }
    
  3. 密码校验

    // 校验密码
    function checkPassword() {// 1.获取密码let password = $("#password").val();// 2.定义正则let reg_username = /^\w{8,20}$/;// 正则:单词字符,以单词开头,以单词结尾,长度8~20位,包含8和20// 3.判断并给出提示信息let flag = reg_username.test(password);if (flag) {       // 校验合法$("#password").css("border", "");} else {      // 校验非法// 输入栏边框变红$("#password").css("border", "2px solid red");}return flag;
    }
    

校验工作重复性较高,其它校验就不再博客里写了。可以参考我的项目仓库,或者暮光乐鱼的博客。

3.1.2 Servlet

/*** 用户注册方法*/
public void register(HttpServletRequest request, HttpServletResponse response) throws IOException {// 0.验证码校验HttpSession session = request.getSession();// 获取客户端浏览器提交的验证码String checkCode_browser = request.getParameter("check");session.removeAttribute("check");   // 客户端验证码获取即从Session中移除,保证验证码的一次性// 获取服务器程序 CheckCodeServlet 生成的验证码String checkCode_server = (String) session.getAttribute("CheckCode_Server");// 验证码比对if (!checkCode_server.equalsIgnoreCase(checkCode_browser)) {                             /*比对失败,向浏览器回写信息并退出方法*/return;}// 1.获取用户提交数据Map<String, String[]> parameterMap = request.getParameterMap();// 2.封装对象User user = new User();/*利用BeanUtils.populate将表单封装至user对象中*/// 3.调用service完成注册boolean flag = service.register(user);ResultInfo resultInfo = new ResultInfo();// 4.响应结果ResultInfo resultInfo = new ResultInfo();/*向resultInfo填充信息,序列化为json,回写给客户端浏览器*/
}

3.1.3 Service

/*** 注册用户* @param user User Bean 对象* @return boolean*      true:注册成功*      false:注册失败*/
@Override
public boolean register(User user) {// 1.根据用户名查询用户对象(存在false,不存在true)User loginUser = userDao.findByUsername(user.getUsername());// 判断loginUser是否为nullif (loginUser != null) {    // 用户名存在,注册失败return false;}   // 用户名不存在,注册成功// 2.保存用户信息// 2.1 设置唯一的激活码user.setCode(UuidUtil.getUuid());// 2.2 设置激活状态user.setStatus("N");    // 初始状态:未激活// 2.3 向数据库中写入用户信息userDao.save(user);// 3.发送激活邮件// 3.1 定义邮件内容String content = "<a href='http://localhost:80/travel/user/active?code=" +user.getCode() + "'>点击激活【黑马旅游网】</a>";// 3.2 发送邮件MailUtils.sendMail(user.getEmail(), content, "激活邮件");return true;
}

3.1.4 Dao

/*** 根据用户名查询用户信息* @param username String 用户名* @return*      查询成功:User Bean 对象*      查询失败:null*/
@Override
public User findByUsername(String username) {User user = null;try {// 1.定义sqlString sql = "SELECT * FROM tab_user WHERE username = ?";// 2.执行sqluser = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), username);} catch (Exception e) {e.printStackTrace();}return user;
}
/*** 用户信息保存* @param user User Bean 对象*/
@Override
public void save(User user) {// 1.定义sqlString sql = "INSERT INTO tab_user(" +"username, password, name, birthday, sex, telephone, email, status, code) " +"VALUES(?,?,?,?,?,?,?,?,?)";// 2.执行sqltemplate.update(sql, user.getUsername(), user.getPassword(),/*一系列getter方法获取fields*/);
}

3.2 邮件激活

3.2.1 Servlet

/*** 用户激活方法*/
public void active(HttpServletRequest request, HttpServletResponse response) throws IOException {// 1.获取激活码String code = request.getParameter("code");if (code != null) {     // 获取激活码// 2.调用service完成激活操作// UserService service = new UserServiceImpl();boolean flag = service.active(code);// 3.判断标记String msg;if (flag) {     // 激活成功msg = "激活成功,请<a href='../login.html'>登录</a>";} else {        // 激活失败msg = "激活失败,请联系管理员";}// 4.回写响应内容response.setContentType("text/html;charset=utf-8");response.getWriter().write(msg);}
}

3.2.2 Service

/*** 激活用户* @param code String 激活码* @return*      true:激活成功*      false:激活失败*/
@Override
public boolean active(String code) {// 1.根据激活码查询用户对象User user = userDao.findByCode(code);if (user != null) {// 2.调用userDao中的修改激活状态方法userDao.updateStatus(user);return true;} else {return false;}
}

3.2.3 Dao

/*** 根据激活码查询用户信息* @param code String 激活码* @return*      查询成功:User Bean 对象*      查询失败:null*/
@Override
public User findByCode(String code) {User user = null;try {String sql = "SELECT * FROM tab_user WHERE code = ?";user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), code);} catch (DataAccessException e) {e.printStackTrace();}return user;
}
/*** 更新激活状态* @param user User Bean 对象*/
@Override
public void updateStatus(User user) {String sql = "UPDATE tab_user SET status = 'Y' WHERE uid = ?";template.update(sql, user.getUid());
}

部分代码并未完全展示,完整代码可以参考我的 GitHub 仓库

JavaWeb - 黑马旅游网(2):用户注册相关推荐

  1. JavaWeb黑马旅游网-学习笔记10【项目代码】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  2. JavaWeb黑马旅游网-学习笔记09【旅游线路收藏】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  3. JavaWeb黑马旅游网-学习笔记08【旅游线路详情】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  4. JavaWeb黑马旅游网-学习笔记06【旅游线路分页展示分页展示】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  5. JavaWeb黑马旅游网-学习笔记05【分类数据展示功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  6. JavaWeb黑马旅游网-学习笔记04【BaseServlet抽取】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  7. JavaWeb黑马旅游网-学习笔记03【登陆和退出功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  8. JavaWeb黑马旅游网-学习笔记02【注册功能】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  9. JavaWeb黑马旅游网-学习笔记01【准备工作】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

  10. JavaWeb黑马旅游网-学习笔记07【旅游线路查询】

    Java后端 学习路线 笔记汇总表[黑马程序员] JavaWeb黑马旅游网-学习笔记01[准备工作] JavaWeb黑马旅游网-学习笔记02[注册功能] JavaWeb黑马旅游网-学习笔记03[登陆和 ...

最新文章

  1. hp laser103 属性没有配置项_冰雪传奇:起源之上还有装备吗?详解鸿蒙装备合成与属性...
  2. 减免租金?也要体谅业主难处哟
  3. C#设计模式——适配器模式(Adapter Pattern)
  4. Sublime Text(2/3)编译lua
  5. Programming WCF Services 学习笔记四、Instance Management
  6. 018_switch语句
  7. mysql数据库truncate 夯住_MySQL如何优雅的删除大表实例详解
  8. 天线3db波束宽度_天线波束宽度计算公式
  9. PyCharm安装和配置教程
  10. GCC 放弃将代码贡献版权强制转让给 FSF!
  11. Linux系统管理第七周作业【Linux微职位】
  12. Linux命令:wget、unzip、cmake、make、vim
  13. android studio for android learning (六)在布局中常使用的单位
  14. PAYPAL支付开发简介
  15. Python 与金融科技2|数据的滑动平均值及多图可视化
  16. 用户画像基础之应用落地和案例展示
  17. MATLAB寻找高斯光束光斑中心
  18. 计算机报名503,503错误,教您网页出现503错误怎么解决
  19. 用asp怎样编写文档搜索页面
  20. 麻将牌识别算法AI也能打麻将了只赢钱

热门文章

  1. 金山毒霸6 最新版(全功能版) 注册版
  2. JAVA计算机毕业设计智能导诊系统Mybatis+源码+数据库+lw文档+系统+调试部署
  3. 猜数字游戏——Java图形界面
  4. IDEA里面快速生成函数注释
  5. things 3 mac 破解版永久激活方法
  6. 诺基亚 N78 手机 “连城诀”活动 传遍中国 悬赏78000元大奖
  7. 物联网串口在线更新语音的mp3语音芯片ic方案说明
  8. ion框架 android,模块化 GKI 的 ION 堆
  9. android ion内存统计,android ion 内存泄漏排查
  10. 北斗三代的RNSS+RDSS组合技术