261 lines
7.2 KiB
Markdown
261 lines
7.2 KiB
Markdown
# 🛒 开发注册功能
|
|
|
|
---
|
|
|
|
## 1. 开发步骤
|
|
|
|
访问注册页面
|
|
|
|
提交注册数据:
|
|
|
|
- 通过表单提交数据
|
|
- 服务端验证账号是否已存在、邮箱是否已注册
|
|
- 服务端发送激活邮件
|
|
|
|
激活注册账号:
|
|
|
|
- 点击邮件中的链接,访问服务端的激活服务
|
|
|
|
## 2. 代码编写
|
|
|
|
### ① 提交注册数据
|
|
|
|
#### UserService
|
|
|
|
```java
|
|
package com.greate.community.service;
|
|
|
|
import com.greate.community.dao.UserMapper;
|
|
import com.greate.community.entity.User;
|
|
import com.greate.community.util.CommunityUtil;
|
|
import com.greate.community.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 {
|
|
|
|
@Autowired
|
|
private UserMapper userMapper;
|
|
|
|
@Autowired
|
|
private MailClient mailClient;
|
|
|
|
@Autowired
|
|
private TemplateEngine templateEngine;
|
|
|
|
// 网站域名
|
|
@Value("${community.path.domain}")
|
|
private String domain;
|
|
|
|
// 项目名 http://localhost:8080/greatecommunity/......
|
|
@Value("${server.servlet.context-path}")
|
|
private String contextPath;
|
|
|
|
/**
|
|
* 根据 Id 查询用户
|
|
* @param id
|
|
* @return
|
|
*/
|
|
public User findUserById (int id) {
|
|
return userMapper.selectById(id);
|
|
}
|
|
|
|
/**
|
|
* 用户注册
|
|
* @param user
|
|
* @return Map<String, Object> 返回错误提示消息,如果返回的 map 为空,则说明注册成功
|
|
*/
|
|
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)); // salt
|
|
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/greatecommunity/activation/用户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(),"激活 Greate Community 账号", content);
|
|
|
|
return map;
|
|
}
|
|
|
|
}
|
|
```
|
|
|
|
#### LoginController
|
|
|
|
```java
|
|
/**
|
|
* 登录注册
|
|
*/
|
|
@Controller
|
|
public class LoginController {
|
|
|
|
@Autowired
|
|
UserService userService;
|
|
|
|
/**
|
|
* 进入注册界面
|
|
* @return
|
|
*/
|
|
@GetMapping("/register")
|
|
public String getRegisterPage() {
|
|
return "site/register";
|
|
}
|
|
|
|
/**
|
|
* 注册用户
|
|
* @param model
|
|
* @param user
|
|
* @return
|
|
*/
|
|
@PostMapping("/register")
|
|
public String register(Model model, User user) {
|
|
Map<String, Object> map = userService.register(user);
|
|
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";
|
|
}
|
|
}
|
|
|
|
}
|
|
```
|
|
|
|
注册成功会跳转到一个中间界面:`operate-result`,提示用户注册成功,并前往邮箱进行激活
|
|
|
|
```html
|
|
<p>
|
|
系统会在 <span id="seconds" class="text-danger">8</span> 秒后自动跳转,
|
|
您也可以点击 <a id="target" th:href="@{${target}}" class="text-primary">此链接</a>, 手动跳转!
|
|
</p>
|
|
```
|
|
|
|
#### 前端通过表单提交数据
|
|
|
|
```html
|
|
<form class="mt-5" method="post" th:action="@{/register}">
|
|
<input name = "username" />
|
|
```
|
|
|
|
SpringMVC 基于同名原则,把前端的 username 传给 user.username
|
|
|
|
```java
|
|
@PostMapping("/register")
|
|
public String register(Model model, User user)
|
|
```
|
|
|
|
### ② 激活注册账号
|
|
|
|
#### UserService
|
|
|
|
```java
|
|
/**
|
|
* 激活用户
|
|
* @param userId 用户 id
|
|
* @param code 激活码
|
|
* @return
|
|
*/
|
|
public int activation(int userId, String code) {
|
|
User user = userMapper.selectById(userId);
|
|
if (user.getStatus() == 1) {
|
|
// 用户已激活
|
|
return ACTIVATION_REPEAT;
|
|
}
|
|
else if (user.getActivationCode().equals(code)) {
|
|
// 修改用户状态为已激活
|
|
userMapper.updateStatus(userId, 1);
|
|
return ACTIVATION_SUCCESS;
|
|
}
|
|
else {
|
|
return ACTIVATION_FAILURE;
|
|
}
|
|
}
|
|
```
|
|
|
|
#### LoginController
|
|
|
|
用户收到激活邮件后,点击邮件中的链接,则激活该用户
|
|
|
|
```java
|
|
// 用户激活
|
|
// http://localhost:8080/greatecommunity/activation/用户id/激活码
|
|
@GetMapping("/activation/{userId}/{code}")
|
|
public String activation(Model model, @PathVariable("userId") int userId, @PathVariable("code") String code) {
|
|
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";
|
|
}
|
|
```
|
|
|