牛客网项目3:注册、激活功能
思路汇总
①注册功能:
首先在主页index,点击注册:<a class="nav-link" th:href="@{/register}">注册</a>
通过控制器方法getRegisterPage(),跳转到register.html界面。
输入账号密码邮箱后,点击立即注册。form表单跳转到th:action="@{/register}"。由于此次发送的是POST请求,执行register()控制器方法。该方法调用了userService.register(user),将user进行注册。
userService.register(user)会进行注册参数的判断:包括参数非空、账号邮箱已存在,并将错误信息存储到Map中。如果都没问题,则对user的其他属性进行复制,例如设置类型、状态、默认头像、自动生成激活码等,从而得到一个完整的user。然后发送激活邮件,context包含了用户邮件地址、激活路径(包含用户ID、激活码):
激活路径格式:http://localhost:8080/community/activation/101/code
并将html文件与context封装到content中,之后调用mailClient.sendMail(邮箱、主题、content),发送html邮件:
String content = templateEngine.process("/mail/activation",context);
到此为止,用户已经注册成功,控制器方法register()还没执行完。继续对userService.register(user)返回的Map进行判断,跳转到设定的界面,并展示相应的信息。
②激活功能:
用户邮箱中会展现activation.html中的内容,里面有个点击此链接激活账号的功能。这个链接就是上一段中【包含用户ID、激活码的激活路径】,我们点击后,会通过控制器方法@RequestMapping(path = "/activation/{userId}/{code}", method = RequestMethod.GET)
activation(){...} 来判断链接中的激活码和user设定的激活码是否相同,并进行各种判断,封装信息、下一步的访问路径。最后返回"/site/operate-result"页面,这是个中转页面,上面会显示上一步判断的信息,并在8秒后跳回上一步设定的路径。
1. 注册页面
首先搞个注册页面:
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous"><link rel="stylesheet" th:href="@{/css/global.css}" /><link rel="stylesheet" th:href="@{/css/login.css}" /><title>牛客网-注册</title>
</head>
<body><div class="nk-container"><!-- 头部 --><!--用index中的header替换掉此内容--><header class="bg-dark sticky-top" th:replace="index::header"><div class="container"><!-- 导航 --><nav class="navbar navbar-expand-lg navbar-dark"><!-- logo --><a class="navbar-brand" href="#"></a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><!-- 功能 --><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav mr-auto"><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link" th:href="@{/index}">首页</a></li><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link position-relative" href="letter.html">消息<span class="badge badge-danger">12</span></a></li><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link" href="@{/register}">注册</a></li><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link" href="login.html">登录</a></li><li class="nav-item ml-3 btn-group-vertical dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><img src="http://images.nowcoder.com/head/1t.png" class="rounded-circle" style="width:30px;"/></a><div class="dropdown-menu" aria-labelledby="navbarDropdown"><a class="dropdown-item text-center" href="profile.html">个人主页</a><a class="dropdown-item text-center" href="setting.html">账号设置</a><a class="dropdown-item text-center" href="login.html">退出登录</a><div class="dropdown-divider"></div><span class="dropdown-item text-center text-secondary">nowcoder</span></div></li></ul><!-- 搜索 --><form class="form-inline my-2 my-lg-0" action="search.html"><input class="form-control mr-sm-2" type="search" aria-label="Search" /><button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button></form></div></nav></div></header><!-- 内容 --><div class="main"><div class="container pl-5 pr-5 pt-3 pb-3 mt-3 mb-3"><h3 class="text-center text-info border-bottom pb-3">注 册</h3><form class="mt-5" method="post" th:action="@{/register}"><div class="form-group row"><label for="username" class="col-sm-2 col-form-label text-right">账号:</label><div class="col-sm-10"><!--如果usernameMsg不为空,就在input标签中添加 th:class='is-invalid' --><!--设定默认值,在报错返回来以后,model仍存有刚才的user对象,这样用户就不要再输一遍了--><!--标签的name属性,需要与user的属性名相同--><input type="text"th:class="|form-control ${usernameMsg!=null?'is-invalid':''}|"th:value="${user!=null?user.username:''}"id="username" name="username" placeholder="请输入您的账号!" required><!--账号的错误就取出map中存的账号错误信息--><div class="invalid-feedback" th:text="${usernameMsg}">该账号已存在!</div></div></div><div class="form-group row mt-4"><label for="password" class="col-sm-2 col-form-label text-right">密码:</label><div class="col-sm-10"><input type="password"th:class="|form-control ${passwordMsg!=null?'is-invalid':''}|"th:value="${user!=null?user.password:''}"id="password" name="password" placeholder="请输入您的密码!" required><div class="invalid-feedback" th:text="${passwordMsg}">密码长度不能小于8位!</div> </div></div><div class="form-group row mt-4"><label for="confirm-password" class="col-sm-2 col-form-label text-right">确认密码:</label><div class="col-sm-10"><input type="password" class="form-control"th:value="${user!=null?user.password:''}"id="confirm-password" placeholder="请再次输入密码!" required><div class="invalid-feedback">两次输入的密码不一致!</div></div></div><div class="form-group row"><label for="email" class="col-sm-2 col-form-label text-right">邮箱:</label><div class="col-sm-10"><input type="email"th:class="|form-control ${emailMsg!=null?'is-invalid':''}|"th:value="${user!=null?user.email:''}"id="email" name="email" placeholder="请输入您的邮箱!" required>
<!-- <div class="invalid-feedback" th:text="${emailMsg}">-->
<!-- 该邮箱已注册!-->
<!-- </div>--></div></div><div class="form-group row mt-4"><div class="col-sm-2"></div><div class="col-sm-10 text-center"><button type="submit" class="btn btn-info text-white form-control">立即注册</button></div></div></form> </div></div><!-- 尾部 --><!-- 代码太长,我先删掉 --></div><script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script><script th:src="@{/js/global.js}"></script><script th:src="@{/js/register.js}"></script>
</body>
</html>
注:这里的<header class="bg-dark sticky-top" th:replace="index::header">
利用了主页面index中的header替换掉此内容,为复用。需要在index的header上添加:
<header class="bg-dark sticky-top" th:fragment="header">
2. 创建工具类
mycommunity/util下新建工具类:CommunityUtil
目前主要包含两个方法:
- 为密码随机生成一个字符串后缀,用来加强密码;
- 将密码进行MD5加密。
public class CommunityUtil {//生成随机字符串public static String generateUUID(){return UUID.randomUUID().toString().replace("-","");}//MD5加密//hello + 3e4r8 --> abc13huoad34public static String md5(String key){if(StringUtils.isBlank(key)){return null;}return DigestUtils.md5DigestAsHex(key.getBytes());}
}
3. 提交注册数据
由于注册是针对用户表的数据,因此注册逻辑写在UserService中。
自动注入了MailClient、TemplateEngine、domain、contextPath(后两个为配置文件中的数据)。
package com.nowcoder.mycommunity.service;import com.nowcoder.mycommunity.dao.UserMapper;
import com.nowcoder.mycommunity.entity.User;
import com.nowcoder.mycommunity.util.CommunityConstant;
import com.nowcoder.mycommunity.util.CommunityUtil;
import com.nowcoder.mycommunity.util.MailClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;@Service
public class UserService implements CommunityConstant {@Autowiredprivate UserMapper userMapper;@Autowiredprivate MailClient mailClient;@Autowiredprivate TemplateEngine templateEngine;//以下值从配置文件中读取@Value("${mycommunity.path.domin}")private String domain;@Value("${server.servlet.context-path}")private String contextPath;public User findUserById(int id){return userMapper.selectById(id);}// 由于注册是针对用户表的数据,因此注册逻辑写在UserService中public Map<String,Object> register(User user){Map<String,Object> map = new HashMap<>();//空值处理if (user == null){throw new IllegalArgumentException("参数不能为空!");}if (StringUtils.isBlank(user.getUsername())){map.put("usernameMsg","账号不能为空!");return map;}if (StringUtils.isBlank(user.getPassword())){map.put("passwordMsg","密码不能为空!");return map;}if (StringUtils.isBlank(user.getEmail())){map.put("emailMsg","邮箱不能为空!");return map;}//验证账号:看是否已存在User u = userMapper.selectByName(user.getUsername());if(u != null){map.put("usernameMsg", "该账号已存在!");return map;}//验证邮箱//u = userMapper.selectByEmail(user.getEmail());//if(u != null){// map.put("emailMsg", "该邮箱已被注册!");// return map;//}//注册//生成随机字符串,添加到密码上user.setSalt(CommunityUtil.generateUUID().substring(0,5));user.setPassword(CommunityUtil.md5(user.getPassword() + user.getSalt()));user.setType(0);user.setStatus(0);user.setActivationCode(CommunityUtil.generateUUID());//设置头像user.setHeaderUrl(String.format("http://images.nowcoder.com/head/%dt.png",new Random().nextInt(1000)));user.setCreateTime(new Date());userMapper.insertUser(user);//发送激活邮件Context context = new Context();context.setVariable("email", user.getEmail());//激活路径格式:http://localhost:8080/community/activation/101/code//注:用户ID为主键自动生成String url = domain + contextPath + "/activation/" + user.getId() + "/" + user.getActivationCode();context.setVariable("url",url);String content = templateEngine.process("/mail/activation",context);mailClient.sendMail(user.getEmail(), "激活账号", content);//最后返回的map为空,则说明没有问题return map;}//激活//需要传进用户ID,得到该用户的激活码,与传进来的激活码进行对比public int activation(int userId, String code){User user = userMapper.selectById(userId);//如果可以查询到该用户ID,说明已经有了,重复注册if(user.getStatus() == 1){return ACTIVATION_REPEAT;} else if(user.getActivationCode().equals(code)){//激活码正确,则将用户的状态设为1userMapper.updateStatus(userId,1);return ACTIVATION_SUCCESS;} else {return ACTIVATION_FAILURE;}}
}
4. 创建控制器
在LoginController中编写注册相应的控制器方法。
package com.nowcoder.mycommunity.controller;import com.nowcoder.mycommunity.dao.UserMapper;
import com.nowcoder.mycommunity.entity.User;
import com.nowcoder.mycommunity.service.UserService;
import com.nowcoder.mycommunity.util.CommunityConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;import java.util.Map;@Controller
public class LoginController implements CommunityConstant {@Autowiredprivate UserService userService;//登录页面@RequestMapping(path = "/login", method = RequestMethod.GET)public String getLoginPage(){System.out.println("lalala");return "/site/login";}//注册页面@RequestMapping(path = "/register", method = RequestMethod.GET)public String getRegisterPage(){return "/site/register";}@RequestMapping(path="/register",method = RequestMethod.POST)public String register(Model model, User user){Map<String, Object> map = userService.register(user);//map为空,说明注册成功了if(map == null || map.isEmpty()){model.addAttribute("msg","注册成功,我们已经向您的邮箱发送了一封激活邮件,请尽快激活!");model.addAttribute("target","/index");//这里并未通过控制器,而是直接访问了静态资源return "/site/operate-result";} else{model.addAttribute("usernameMsg",map.get("usernameMsg"));model.addAttribute("passwordMsg",map.get("passwordMsg"));//model.addAttribute("emailMsg",map.get("emailMsg"));return "/site/register";}}@RequestMapping(path = "/activation/{userId}/{code}", method = RequestMethod.GET)public String activation(Model model,@PathVariable("userId") int userId,@PathVariable("code") String code){System.out.println("我进来了!");int result = userService.activation(userId, code);if(result == ACTIVATION_SUCCESS){model.addAttribute("msg","激活成功!您的账号可以正常使用了!");model.addAttribute("target","/login");} else if (result == ACTIVATION_REPEAT){model.addAttribute("msg","无效操作,该账号已经激活过了!");model.addAttribute("target","/index");} else {model.addAttribute("msg","激活失败,请提供正确的激活码!");model.addAttribute("target","/index");}return "/site/operate-result";}
}
这里还创建了一个常量接口,用于存放常量:
util目录下,新建接口:CommunityConstant
//常量接口
public interface CommunityConstant {//激活成功int ACTIVATION_SUCCESS = 0;//重复激活int ACTIVATION_REPEAT = 1;//激活失败int ACTIVATION_FAILURE = 2;
}
5. 其他html
activation.html:
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"><link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/><title>牛客网-激活账号</title>
</head>
<body><div><p><b th:text="${email}">xxx@xxx.com</b>, 您好!</p><p>您正在注册牛客网, 这是一封激活邮件, 请点击 <a th:href="${url}">此链接</a>,激活您的牛客账号!</p></div>
</body>
</html>
operate-result.html
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"><link rel="icon" href="https://static.nowcoder.com/images/logo_87_87.png"/><link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous"><link rel="stylesheet" th:href="@{/css/global.css}" /><title>牛客网-操作结果</title>
</head>
<body class="bg-white"><div class="nk-container"><!-- 头部 --><header class="bg-dark sticky-top" th:replace="index::header"><div class="container"><!-- 导航 --><nav class="navbar navbar-expand-lg navbar-dark"><!-- logo --><a class="navbar-brand" href="#"></a><button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button><!-- 功能 --><div class="collapse navbar-collapse" id="navbarSupportedContent"><ul class="navbar-nav mr-auto"><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link" href="../index.html">首页</a></li><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link position-relative" href="letter.html">消息<span class="badge badge-danger">12</span></a></li><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link" href="register.html">注册</a></li><li class="nav-item ml-3 btn-group-vertical"><a class="nav-link" href="login.html">登录</a></li><li class="nav-item ml-3 btn-group-vertical dropdown"><a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><img src="http://images.nowcoder.com/head/1t.png" class="rounded-circle" style="width:30px;"/></a><div class="dropdown-menu" aria-labelledby="navbarDropdown"><a class="dropdown-item text-center" href="profile.html">个人主页</a><a class="dropdown-item text-center" href="setting.html">账号设置</a><a class="dropdown-item text-center" href="login.html">退出登录</a><div class="dropdown-divider"></div><span class="dropdown-item text-center text-secondary">nowcoder</span></div></li></ul><!-- 搜索 --><form class="form-inline my-2 my-lg-0" action="search.html"><input class="form-control mr-sm-2" type="search" aria-label="Search" /><button class="btn btn-outline-light my-2 my-sm-0" type="submit">搜索</button></form></div></nav></div></header><!-- 内容 --><div class="main"><div class="container mt-5"><div class="jumbotron"><p class="lead" th:text="${msg}">您的账号已经激活成功,可以正常使用了!</p><hr class="my-4"><p>系统会在 <span id="seconds" class="text-danger">8</span> 秒后自动跳转,您也可以点此 <a id="target" th:href="@{${target}}" class="text-primary">链接</a>, 手动跳转!</p></div></div></div><!-- 尾部 --><footer class="bg-dark"><div class="container"><div class="row"><!-- 二维码 --><div class="col-4 qrcode"><img src="https://uploadfiles.nowcoder.com/app/app_download.png" class="img-thumbnail" style="width:136px;" /></div><!-- 公司信息 --><div class="col-8 detail-info"><div class="row"><div class="col"><ul class="nav"><li class="nav-item"><a class="nav-link text-light" href="#">关于我们</a></li><li class="nav-item"><a class="nav-link text-light" href="#">加入我们</a></li><li class="nav-item"><a class="nav-link text-light" href="#">意见反馈</a></li><li class="nav-item"><a class="nav-link text-light" href="#">企业服务</a></li><li class="nav-item"><a class="nav-link text-light" href="#">联系我们</a></li><li class="nav-item"><a class="nav-link text-light" href="#">免责声明</a></li><li class="nav-item"><a class="nav-link text-light" href="#">友情链接</a></li></ul></div></div><div class="row"><div class="col"><ul class="nav btn-group-vertical company-info"><li class="nav-item text-white-50">公司地址:北京市朝阳区大屯路东金泉时代3-2708北京牛客科技有限公司</li><li class="nav-item text-white-50">联系方式:010-60728802(电话) admin@nowcoder.com</li><li class="nav-item text-white-50">牛客科技©2018 All rights reserved</li><li class="nav-item text-white-50">京ICP备14055008号-4 <img src="http://static.nowcoder.com/company/images/res/ghs.png" style="width:18px;" />京公网安备 11010502036488号</li></ul></div></div></div></div></div></footer></div><script src="https://code.jquery.com/jquery-3.3.1.min.js" crossorigin="anonymous"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" crossorigin="anonymous"></script><script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" crossorigin="anonymous"></script><script>$(function(){setInterval(function(){var seconds = $("#seconds").text();$("#seconds").text(--seconds);if(seconds == 0) {location.href = $("#target").attr("href");}}, 1000);});</script>
</body>
</html>
牛客网项目3:注册、激活功能相关推荐
- 云服务器上部署仿牛客网项目
云服务器上部署仿牛客网项目 安装JRE 安装Maven 安装MySQL 给mysql导入数据 安装Redis 安装kafka 安装ElasticSearch Wkhtmltopdf 安装tomcat ...
- 仿牛客网项目第二章:开发社区登录模块(详细步骤和思路)
目录 1. 发送邮件 1.0 三步走 1.1 邮箱设置 1.2 Spring Email 1.3 模板引擎 1.4 发送邮件的过程 1.5 检验发送邮件的过程 2. 开发注册功能 2.0 注册功能的步 ...
- 牛客网项目1:开发社区首页
总结在先: ①首先根据每张表创建相对应的实体类,该实体类中的属性与表中的字段名相同: ②由于每张表都需要一些增删改查的方法,因此需要创建Mapper接口(每张表各一个),接口中放有对应表的增删改查方法 ...
- 仿牛客网项目第五,六章:异步消息系统和分布式搜索引擎(详细步骤和思路)
目录 1. Kafka:构建TB级异步消息系统 1.0 同步/异步消息的区别 1.1 项目的目的 1. 2 阻塞队列实现异步消息系统 1.4 Kafka入门 1.5 Spring整合Kafka 1.6 ...
- ATeam社区(牛客网项目第三章)
这里写目录标题 1. 过滤敏感词 1.1 定义敏感词 1.2 定义前缀树 1.3 根据敏感词初始化前缀树 1.4 过滤敏感词的方法 1.5 前缀树过滤敏感词简述 2. 发布帖子 2.1 AJA使用示例 ...
- 牛客网项目5:登录、退出功能
1. 访问登录页面 点击顶部区域内的连接,打开登陆页面. index.html中: <li class="nav-item ml-3 btn-group-vertical"& ...
- 牛客网项目——项目开发(八):开发社区搜索功能
文章目录 1. ElasticsearchService 1.1 注入bean 1.2 保存(修改)和删除 1.3 搜索 searchDiscussPost 2. DiscussPostControl ...
- 牛客网项目(社区项目)知识整理
什么是Spring框架? 有很多模块组成,利用这些模块可以方便开发工作.这些模块是:核心容器(spring core)/数据访问和集成(Spring JDBC)/Web(Spring Web/MVC) ...
- 牛客网项目--MyBatis
1. 安装软件: MySQL 官网下载–>在根目录下,新建文件夹my.ini–> 对mysql进行初始化 配置环境变量,将mysql的bin目录配置到path中: 对mysql进行初始化, ...
最新文章
- 学习.NET的两个网站:MSDN和Asp .NET
- 2020华为推迟发布鸿蒙战略,早新闻:华为5nm麒麟芯片延期,确认新版鸿蒙将发...
- java调试案例_Spring-boot的debug调试代码实例
- Linux 修改用户名的主目录 家目录
- linux diff详解
- java开源项目-SpringBoot在线教育平台
- iso硬盘安装 凤凰os_在Linux中安装凤凰系统(Phoenix OS)的方法
- css背景图片高斯模糊_CSS3 filter(滤镜) 制作图片高斯模糊无需JS
- 莫名其妙把电脑机箱左边耳机孔弄出来声音
- 怎么把图片转换成PDF文件?
- 竞价推广方案怎么写,这些点你get到了吗?
- idea中设置jdk
- 如何建设前端物料平台?
- 【Caffe学习三】基于ROC-RK3399-PC/Ubuntu18.04的Caffe-SSD-CPU 安装编译___BUG
- Spring学习——自动装配
- 绘制Excel字符画
- 阿里云产品专家陶炳哲:Java应用最佳实验
- 【基础篇】详解Zookeeper客户端Curator
- 设置adobe reader pro的文本框字体属性
- win7家庭版升级到旗舰版
热门文章
- SDCMS1.31调用指定栏目信息的代码大全及调用方法
- ROS全覆盖规划算法 Coverage Path Planning 采坑
- arcgis engine10.2版本 ,狭长面分析,可自定义长宽比例
- VC 获取屏幕及打印机的像素,DPI,英寸数,毫米数,缇数(twips)
- 手把手教你生成你的独家微信聊天年度报告
- 这本694页的程序员砖头书让你精通ASP.NET Core MVC
- MySQL——深入理解
- u盘修复计算机w7,怎么用u盘修复系统开启,win7旗舰版!
- 语谱图(二) Spectrogram 的产生
- 超融合架构hci之路坦力nutanix之硬件规格及软件配置之一