我们在网站使用邮箱注册账户的时候,通常是注册邮箱收到一个链接,在有效时间范围内(比如说10分钟)点击这个链接就能注册成功,否则在登录的时候就会报错.
下面我们自己写一个例子来测试一下,首先我们得有一个用来发送激活链接的邮箱,我这里使用的是163邮箱.
起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
application.properties添加配置文件
domain.name=127.0.0.1:8091
#这里我用到的是163邮箱
spring.mail.host=smtp.163.com4
spring.mail.username=你的邮箱
spring.mail.password=邮箱密码
spring.mail.properties.mail.smtp.auth=true
#必须通过加密通讯
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
激活链接中通常有一长串的随机字母+数字,我们使用RandomStringUtils这个工具类来实现,我觉得这两种方法都可以啦.
而每个注册的邮箱,对应一个随机的字符串,我们把它保存在guava的Cache里(本地缓存)
RandomStringUtils.randomAlphabetic(10);//包含大小写字母,长度为10
RandomStringUtils.randomAlphanumeric(10);//包含大小写字母+数字,长度为10
//大小为100,cache内的数据在15分钟内没有被读或者写就会被回收
//RemovalListener是监听器,当从cache中移除一条数据的时候,他就会监听到
private final Cache<String, String> registerCache =
CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(15, TimeUnit.MINUTES)
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
userMapper.delete(notification.getValue());
}
}
}).build();
MailService.java
@Service
public class MailService {
@Autowired
private JavaMailSender mailSender;
@Value("${spring.mail.username}")
private String from;
@Value("${domain.name}")
private String domainName;
@Autowired
private UserMapper userMapper;
private final Cache<String, String> registerCache =
CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(15, TimeUnit.MINUTES)
.removalListener(new RemovalListener<String, String>() {
@Override
public void onRemoval(RemovalNotification<String, String> notification) {
String email = notification.getValue();
User user = new User();
user.setEmail(email);
List<User> targetUser = userMapper.selectUsersByQuery(user);
if (!targetUser.isEmpty() && Objects.equal(targetUser.get(0).getEnable(), 0)) {
userMapper.delete(email);// 代码优化: 在删除前首先判断用户是否已经被激活,对于未激活的用户进行移除操作
}
}
}).build();
private final Cache<String, String> resetCache = CacheBuilder.newBuilder().maximumSize(100).expireAfterAccess(15, TimeUnit.MINUTES).build();
@Async
public void sendMail(String title, String url, String email) {
SimpleMailMessage message = new SimpleMailMessage();
message.setFrom(from);
message.setSubject(title);
message.setTo(email);
message.setText(url);
mailSender.send(message);
}
/**
* 1.缓存key-email的关系 2.借助spring mail 发送邮件 3.借助异步框架进行异步操作
*
* @param email
*/
@Async
public void registerNotify(String email) {
String randomKey = RandomStringUtils.randomAlphabetic(10);
registerCache.put(randomKey, email);
String url = "http://" + domainName + "/accounts/verify?key=" + randomKey;
sendMail("激活邮件", url, email);
}
public boolean enable(String key) {
String email = registerCache.getIfPresent(key);
if (StringUtils.isBlank(email)) {
return false;
}
User updateUser = new User();
updateUser.setEmail(email);
updateUser.setEnable(1);
userMapper.update(updateUser);
registerCache.invalidate(key);
return true;
}
}
Service的发送邮件的方法是异步的,启动类也需要加一哈@EnableAsync注解哦