han-note项目初始化完毕!
- 邮箱验证码接口完成
This commit is contained in:
@@ -42,6 +42,30 @@
|
||||
<groupId>com.hanserwei</groupId>
|
||||
<artifactId>hanserwei-spring-boot-starter-jackson</artifactId>
|
||||
</dependency>
|
||||
<!-- Sa-Token 权限认证 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
</dependency>
|
||||
<!-- Redis -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!-- Redis 连接池 -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-mail</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.hanserwei.hannote.auth.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
@Configuration
|
||||
public class RedisTemplateConfig {
|
||||
|
||||
@Bean
|
||||
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||
// 设置 RedisTemplate 的连接工厂
|
||||
redisTemplate.setConnectionFactory(connectionFactory);
|
||||
|
||||
// 使用 StringRedisSerializer 来序列化和反序列化 redis 的 key 值,确保 key 是可读的字符串
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
|
||||
// 使用 Jackson2JsonRedisSerializer 来序列化和反序列化 redis 的 value 值, 确保存储的是 JSON 格式
|
||||
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||
redisTemplate.setValueSerializer(serializer);
|
||||
redisTemplate.setHashValueSerializer(serializer);
|
||||
|
||||
redisTemplate.afterPropertiesSet();
|
||||
return redisTemplate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.hanserwei.hannote.auth.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
|
||||
@Configuration
|
||||
public class ThreadPoolConfig {
|
||||
@Bean(name = "authTaskExecutor")
|
||||
public ThreadPoolTaskExecutor taskExecutor() {
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
//核心线程数
|
||||
executor.setCorePoolSize(10);
|
||||
//最大线程数
|
||||
executor.setMaxPoolSize(50);
|
||||
//队列容量
|
||||
executor.setQueueCapacity(200);
|
||||
//活跃时间
|
||||
executor.setKeepAliveSeconds(30);
|
||||
//线程名前缀
|
||||
executor.setThreadNamePrefix("AuthExecutor-");
|
||||
|
||||
//拒绝策略:由调用线程处理,一般为主线程
|
||||
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
|
||||
// 等待所有任务结束后再关闭线程池
|
||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||
// 设置等待时间,如果超过这个时间还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是被没有完成的任务阻塞
|
||||
executor.setAwaitTerminationSeconds(60);
|
||||
|
||||
executor.initialize();
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.hanserwei.hannote.auth.constant;
|
||||
|
||||
public class RedisKeyConstants {
|
||||
|
||||
/**
|
||||
* 验证码 KEY 前缀
|
||||
*/
|
||||
private static final String VERIFICATION_CODE_KEY_PREFIX = "verification_code:";
|
||||
|
||||
/**
|
||||
* 构建验证码 KEY
|
||||
* @param email 手机号
|
||||
* @return 验证码key
|
||||
*/
|
||||
public static String buildVerificationCodeKey(String email) {
|
||||
return VERIFICATION_CODE_KEY_PREFIX + email;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.hanserwei.hannote.auth.controller;
|
||||
|
||||
import com.hanserwei.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import com.hanserwei.framework.common.response.Response;
|
||||
import com.hanserwei.hannote.auth.model.vo.SendVerificationCodeReqVO;
|
||||
import com.hanserwei.hannote.auth.service.VerificationCodeService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@Slf4j
|
||||
@RequiredArgsConstructor
|
||||
public class VerificationCodeController {
|
||||
|
||||
private final VerificationCodeService verificationCodeService;
|
||||
|
||||
@PostMapping("/verification/code/send")
|
||||
@ApiOperationLog(description = "发送邮件验证码")
|
||||
public Response<?> send(@Validated @RequestBody SendVerificationCodeReqVO sendVerificationCodeReqVO) {
|
||||
return verificationCodeService.send(sendVerificationCodeReqVO);
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,9 @@ public enum ResponseCodeEnum implements BaseExceptionInterface {
|
||||
PARAM_NOT_VALID("AUTH-10001", "参数错误!!!"),
|
||||
|
||||
// ----------- 业务异常状态码 -----------
|
||||
VERIFICATION_CODE_SEND_FREQUENTLY("AUTH-20000", "请求太频繁,请3分钟后再试"),
|
||||
MAIL_SEND_ERROR("AUTH-20001", "邮件发送失败,请稍后再试"),
|
||||
TEMPLATE_RENDER_ERROR("AUTH-20002", "模板渲染错误")
|
||||
;
|
||||
|
||||
// 异常码
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.hanserwei.hannote.auth.model.vo;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
public class SendVerificationCodeReqVO {
|
||||
|
||||
@NotBlank(message = "邮箱不能为空")
|
||||
private String email;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.hanserwei.hannote.auth.service;
|
||||
|
||||
import com.hanserwei.framework.common.response.Response;
|
||||
import com.hanserwei.hannote.auth.model.vo.SendVerificationCodeReqVO;
|
||||
|
||||
public interface VerificationCodeService {
|
||||
|
||||
/**
|
||||
* 发送短信验证码
|
||||
*
|
||||
* @param sendVerificationCodeReqVO 发送验证码VO
|
||||
* @return 返回响应
|
||||
*/
|
||||
Response<?> send(SendVerificationCodeReqVO sendVerificationCodeReqVO);
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package com.hanserwei.hannote.auth.service.impl;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.hanserwei.framework.common.exception.ApiException;
|
||||
import com.hanserwei.framework.common.response.Response;
|
||||
import com.hanserwei.hannote.auth.constant.RedisKeyConstants;
|
||||
import com.hanserwei.hannote.auth.enums.ResponseCodeEnum;
|
||||
import com.hanserwei.hannote.auth.model.vo.SendVerificationCodeReqVO;
|
||||
import com.hanserwei.hannote.auth.service.VerificationCodeService;
|
||||
import com.hanserwei.hannote.auth.utils.MailHelper;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Service
|
||||
@Slf4j
|
||||
public class VerificationCodeServiceImpl implements VerificationCodeService {
|
||||
|
||||
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final MailHelper mailHelper;
|
||||
@Resource(name = "authTaskExecutor")
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||
|
||||
/**
|
||||
* 发送短信验证码!
|
||||
*
|
||||
* @param sendVerificationCodeReqVO 发送验证码VO
|
||||
* @return 响应
|
||||
*/
|
||||
@Override
|
||||
public Response<?> send(SendVerificationCodeReqVO sendVerificationCodeReqVO) {
|
||||
// 邮箱
|
||||
String email = sendVerificationCodeReqVO.getEmail();
|
||||
//构建Redis的Key
|
||||
String codeKey = RedisKeyConstants.buildVerificationCodeKey(email);
|
||||
// 判断是否发送!
|
||||
Boolean hasKey = redisTemplate.hasKey(codeKey);
|
||||
if (hasKey) {
|
||||
//若之前发送的验证码未过期,则提示发送频繁
|
||||
throw new ApiException(ResponseCodeEnum.VERIFICATION_CODE_SEND_FREQUENTLY);
|
||||
}
|
||||
//生成六位数随机验证码
|
||||
String verificationCode = RandomUtil.randomNumbers(6);
|
||||
threadPoolTaskExecutor.submit(() -> mailHelper.sendMail(verificationCode, email));
|
||||
log.info("==> 邮箱: {}, 已发送验证码:【{}】", email, verificationCode);
|
||||
// 存储验证码到 redis, 并设置过期时间为 3 分钟
|
||||
redisTemplate.opsForValue().set(codeKey, verificationCode, 3, TimeUnit.MINUTES);
|
||||
return Response.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
package com.hanserwei.hannote.auth.utils;
|
||||
|
||||
import com.hanserwei.framework.common.exception.ApiException;
|
||||
import com.hanserwei.hannote.auth.enums.ResponseCodeEnum;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.mail.javamail.MimeMessageHelper;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class MailHelper {
|
||||
|
||||
@Resource
|
||||
private JavaMailSender mailSender;
|
||||
|
||||
@Resource
|
||||
private TemplateEngine templateEngine;
|
||||
|
||||
@Value("${spring.mail.username}")
|
||||
private String username;
|
||||
|
||||
|
||||
public boolean sendMail(String verificationCode, String email) {
|
||||
Context context = new Context();
|
||||
context.setVariable("verifyCode", Arrays.asList(verificationCode.split("")));
|
||||
|
||||
String process;
|
||||
try {
|
||||
// 确保这里的 templateEngine 能够正确处理 context
|
||||
process = templateEngine.process("EmailVerificationCode.html", context);
|
||||
} catch (Exception e) {
|
||||
// 处理模板渲染失败的异常
|
||||
throw new ApiException(ResponseCodeEnum.TEMPLATE_RENDER_ERROR);
|
||||
}
|
||||
|
||||
MimeMessage mimeMessage = mailSender.createMimeMessage();
|
||||
|
||||
try {
|
||||
MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
|
||||
helper.setSubject("【Han-note】验证码");
|
||||
helper.setFrom(username);
|
||||
helper.setTo(email);
|
||||
helper.setSentDate(new Date());
|
||||
helper.setText(process, true);
|
||||
|
||||
mailSender.send(mimeMessage); // 可能会抛出 MailException (RuntimeException)
|
||||
log.info("邮件发送成功!");
|
||||
} catch (MessagingException | org.springframework.mail.MailException e) {
|
||||
// 捕获 MimeMessageHelper 配置异常 和 mailSender 发送异常
|
||||
log.error("邮件发送失败:{}", e.getMessage());
|
||||
throw new ApiException(ResponseCodeEnum.MAIL_SEND_ERROR);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,29 @@ spring:
|
||||
url: ${spring.datasource.url}
|
||||
username: ${spring.datasource.username} # 数据库用户名
|
||||
password: ${spring.datasource.password} # 数据库密码
|
||||
data:
|
||||
redis:
|
||||
database: 5 # Redis 数据库索引(默认为 0)
|
||||
host: 127.0.0.1 # Redis 服务器地址
|
||||
port: 6379 # Redis 服务器连接端口
|
||||
password: redis # Redis 服务器连接密码(默认为空)
|
||||
timeout: 5s # 读超时时间
|
||||
connect-timeout: 5s # 链接超时时间
|
||||
lettuce:
|
||||
pool:
|
||||
max-active: 200 # 连接池最大连接数
|
||||
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
|
||||
min-idle: 0 # 连接池中的最小空闲连接
|
||||
max-idle: 10 # 连接池中的最大空闲连接
|
||||
mail:
|
||||
host: smtp.qq.com
|
||||
port: 587
|
||||
username: 2628273921@qq.com
|
||||
password: ${MAIL_PASSWORD:}
|
||||
properties:
|
||||
mail.smtp.auth: true
|
||||
mail.smtp.starttls.enable: true
|
||||
mail.smtp.starttls.required: true
|
||||
server:
|
||||
port: 8080 # 项目启动的端口
|
||||
mybatis-plus:
|
||||
@@ -21,3 +44,19 @@ mybatis-plus:
|
||||
logging:
|
||||
level:
|
||||
com.hanserwei.hannote.auth.domain.mapper: debug
|
||||
############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
|
||||
sa-token:
|
||||
# token 名称(同时也是 cookie 名称)
|
||||
token-name: satoken
|
||||
# token 有效期(单位:秒) 默认30天,-1 代表永久有效
|
||||
timeout: 2592000
|
||||
# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结
|
||||
active-timeout: -1
|
||||
# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)
|
||||
is-concurrent: true
|
||||
# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)
|
||||
is-share: true
|
||||
# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)
|
||||
token-style: simple-uuid
|
||||
# 是否输出操作日志
|
||||
is-log: true
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>邮箱验证码</title>
|
||||
<style>
|
||||
table {
|
||||
width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#top {
|
||||
width: 700px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
margin: 0 auto 30px;
|
||||
}
|
||||
|
||||
#top table {
|
||||
font: 12px Tahoma, Arial, 宋体;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#content {
|
||||
width: 680px;
|
||||
padding: 0 10px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#content_top {
|
||||
line-height: 1.5;
|
||||
font-size: 14px;
|
||||
margin-bottom: 25px;
|
||||
color: #4d4d4d;
|
||||
}
|
||||
|
||||
#content_top strong {
|
||||
display: block;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#content_top strong span {
|
||||
color: #f60;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#verificationCode {
|
||||
color: #f60;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
#content_bottom {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
#content_bottom small {
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
font-size: 12px;
|
||||
color: #747474;
|
||||
}
|
||||
|
||||
#bottom {
|
||||
width: 700px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#bottom div {
|
||||
padding: 10px 10px 0;
|
||||
border-top: 1px solid #ccc;
|
||||
color: #747474;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.3em;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
#content_top strong span {
|
||||
font-size: 18px;
|
||||
color: #FE4F70;
|
||||
}
|
||||
|
||||
#sign {
|
||||
text-align: right;
|
||||
font-size: 18px;
|
||||
color: #FE4F70;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#verificationCode {
|
||||
height: 100px;
|
||||
width: 680px;
|
||||
text-align: center;
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
#verificationCode div {
|
||||
height: 100px;
|
||||
width: 680px;
|
||||
|
||||
}
|
||||
|
||||
.button {
|
||||
color: #FE4F70;
|
||||
margin-left: 10px;
|
||||
height: 80px;
|
||||
width: 80px;
|
||||
resize: none;
|
||||
font-size: 42px;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 10px 15px;
|
||||
background: #ededed;
|
||||
text-align: center;
|
||||
border-radius: 17px;
|
||||
box-shadow: 6px 6px 12px #cccccc,
|
||||
-6px -6px 12px #ffffff;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
box-shadow: inset 6px 6px 4px #d1d1d1,
|
||||
inset -6px -6px 4px #ffffff;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="top">
|
||||
<table>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="content">
|
||||
<div id="content_top">
|
||||
<strong>尊敬的用户,您好!</strong>
|
||||
<strong>
|
||||
您正在使用验证码校验,请在5分钟内填写如下验证码,如非本人操作请忽略该邮件
|
||||
</strong>
|
||||
<div id="verificationCode">
|
||||
<button class="button" th:each="a:${verifyCode}">[[${a}]]</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="content_bottom">
|
||||
<small>
|
||||
注意:此操作可能会修改您的密码、登录邮箱或绑定手机。如非本人操作,请及时登录并修改密码以保证帐户安全
|
||||
<br>(工作人员不会向你索取此验证码,请勿泄漏!)
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bottom">
|
||||
<div>
|
||||
<p>此为系统邮件,请勿回复<br>
|
||||
请保管好您的邮箱,避免账号被他人盗用
|
||||
</p>
|
||||
<p id="sign">——Han-note官方</p>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</body>
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.hanserwei.hannote.auth;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
class RedisTests {
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* set key value
|
||||
*/
|
||||
@Test
|
||||
void testSetKeyValue() {
|
||||
// 添加一个 key 为 name, value 值为 Hanserwei
|
||||
redisTemplate.opsForValue().set("name", "Hanserwei");
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断某个 key 是否存在
|
||||
*/
|
||||
@Test
|
||||
void testHasKey() {
|
||||
log.info("key 是否存在:{}", redisTemplate.hasKey("name"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取某个 key 的 value
|
||||
*/
|
||||
@Test
|
||||
void testGetValue() {
|
||||
log.info("value 值:{}", redisTemplate.opsForValue().get("name"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除某个 key
|
||||
*/
|
||||
@Test
|
||||
void testDelete() {
|
||||
redisTemplate.delete("name");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.hanserwei.hannote.auth;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
|
||||
@SpringBootTest
|
||||
@Slf4j
|
||||
public class ThreadPoolTaskExecutorTests {
|
||||
|
||||
@Resource
|
||||
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
|
||||
|
||||
/**
|
||||
* 测试线程池
|
||||
*/
|
||||
@Test
|
||||
void testSubmit() {
|
||||
threadPoolTaskExecutor.submit(() -> log.info("异步线程中说: Hanserwei是傻逼"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user