1. 流程
- 我們注冊賬號的時候會收到一封郵件,點擊郵件里的鏈接就激活賬號,這個功能很常見。其實就是在用戶表里面加
state
和code
字段,state表示激活狀態,code是激活碼 - 用戶填寫賬號點擊注冊,接着后台就往數據庫插入數據,數據中
state
字段為0(表示未激活),還有個隨機的code - 之后就向該用戶發送郵件,郵件里有一個激活賬號的URL(URL有用戶id和對應的隨機激活碼)
- 用戶點擊郵件的鏈接,就會帶上用戶id和激活碼來到激活頁面激活賬號,若郵件的參數和數據庫參數一致則激活賬號,更新字段
state
未為1,否則不激活 - 這里只介紹最基本的功能,還有激活碼的過期時間,激活不成功刪除賬號,密碼加鹽等細節沒有實現,還有這里的項目沒有前端頁面,一切功能從地址欄實現,請各位酌情考慮
2. 環境與依賴
- IDEA
- Maven
依賴
<!-- 父工程 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.5.RELEASE</version>
</parent>
<!-- JDK版本 -->
<properties>
<java.version>1.8</java.version>
</properties>
<!-- 各種依賴 -->
<dependencies>
<!-- Web啟動類 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 阿里巴巴數據庫連接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 連接池的啟動器 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- 添加數據庫啟動器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- 數據庫驅動,因為springboot不知道我們使用什么數據庫 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.28</version>
</dependency>
<!-- mybatis依賴 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<!-- mybatis啟動器依賴 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- Junit依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- 郵件依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
SpringBoot配置文件
# 數據庫連接池,自帶hikari
# hikari:
# maximum-pool-size: 30 # 最大連接數
# minimum-idle: 10 # 最小連接數
# 自己的郵件配置
Howl:
mail:
from: XXXXXXXXXX@qq.com
subject: 激活郵件
address: http://localhost:8080
spring:
# 數據源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?serverTimezone=UTC
username: root
password:
druid:
initial-size: 10
min-idle: 5
max-active: 20
pool-prepared-statements: true
# 郵件配置
mail:
host: smtp.qq.com
port: 465
username: XXXXXXXXXX@qq.com
password: XXXXXXXXXXXXXXXXXX #這里是smtp的密碼,不是QQ密碼
protocol: smtp
default-encoding: utf-8
properties:
mail:
imap:
ssl:
socketFactory:
fallback: false
smtp:
auth: true
ssl:
enable: true
socketFactory:
class: com.fintech.modules.base.util.mail.MailSSLSocketFactory
starttls:
enable: true
required: true
test-connection: false
# mybatis配置
mybatis:
# 別名
type-aliases-package: com.howl.dto
# 映射文件路徑,一般不用了
# mapper-locations: classpath:mappers/*.xml
configuration:
# 開啟駝峰映射
map-underscore-to-camel-case: true
2. 項目結構
3. 數據庫
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`state` int(1) NOT NULL DEFAULT '0' COMMENT '用戶激活狀態:0表示未激活,1表示激活',
`code` varchar(255) NOT NULL COMMENT '激活碼',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
4. DTO層
public class User {
private int id;
private String username;
private String password;
private String email;
private String state;
private String code;
//Getters、Setters
//Constructor
}
5. DAO層
- 使用mybatis動態代理,編寫的是接口
@Mapper
public interface UserMapper {
@Options(useGeneratedKeys = true, keyProperty = "id")
@Insert("INSERT INTO user (`username`,`password`,`email`,`code`) VALUES (#{username},#{password},#{email},#{code})")
public int register(User user);
@Select("SELECT * FROM user WHERE id = #{id}")
public User getUserById(int id);
@Update("UPDATE user SET state = 1 WHERE id = #{id} AND code = #{code}")
public int updateByIdAndCode(int id, String code);
}
6. 工具類
郵件工具類
@Component
public class EmailUtil {
@Autowired
private JavaMailSender javaMailSender;
@Value("${Howl.mail.from}")
private String from;
@Value("${Howl.mail.subject}")
private String subject;
@Value("${Howl.mail.address}")
private String address;
public void sendEmail(int id, String code, String to) {
String url = address + "/verify?id=" + id + "&code=" + code;
String label = "<a href=" + url + ">點擊此處激活賬號,有沒有反應可以復制鏈接從瀏覽器打開</a>";
try {
MimeMessage mimeMessage = javaMailSender.createMimeMessage();
MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage, true);
messageHelper.setFrom(from);
messageHelper.setTo(to);
messageHelper.setSubject(subject);
messageHelper.setText(label,true);
messageHelper.setSentDate(new Date());
javaMailSender.send(mimeMessage);
}catch (Exception e){
new RuntimeException("郵件發送失敗",e);
}
}
}
激活碼
@Component
public class CodeUtil {
public String getCode() {
//返回UUID
return UUID.randomUUID().toString().replace("-", "");
}
}
7. Service層
@Service
public class UserService {
@Autowired
UserMapper userMapper;
@Autowired
EmailUtil emailUtil;
@Autowired
CodeUtil codeUtil;
public int register(String username, String password, String email) {
int result;
String code = codeUtil.getCode();
User user = new User(username, password, email, code);
result = userMapper.register(user);
// 開線程來發郵件,提高效率,發郵件很慢
new Thread(() -> {
emailUtil.sendEmail(user.getId(), code, email);
}).run();
return result;
}
public int verify(int id, String code) {
User user = userMapper.getUserById(id);
if (user != null) {
return userMapper.updateByIdAndCode(id, code);
}
return 0;
}
}
8. Controller層
@RestController
public class UserController {
@Autowired
UserService userService;
@GetMapping(value = "/register")
public String register(String username, String password, String email) {
return userService.register(username, password, email) + "";
}
@GetMapping(value = "/verify")
public String verify(int id, String code) {
return userService.verify(id, code) + "";
}
}
9. SpringBoot入口
@SpringBootApplication
@MapperScan("com.howl.dao")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
10. 測試
都看到這里了,沒有前端頁面。。。大家自行想象登錄操作
10.1 注冊
這里使用地址欄GET方式注冊,正式注冊用POST表單的不要學我,為了懶不想寫前端
10.2 數據庫插入
10.3 收郵件
10.4 點擊鏈接激活
10.5 查看數據庫激活狀態
總結
實現太簡單,不過基本功能還是有的,細節方面可以慢慢補充