Redis学习(二.集成邮件发送与验证)

本文介绍了如何在SpringBoot项目中集成Redis和邮件发送功能。首先,通过添加相关依赖,配置QQ邮箱的SMTP服务来实现邮件发送。接着,配置Redis,包括YAML设置及RedisTemplate的个性化配置。最后,展示了前端发送邮箱验证码的逻辑和后端整合Redis存储验证码并与邮件验证的实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇文章中我们了解了Redis的数据类型,接下来进入Redis的实操。

一.springboot集成邮件发送功能

1.引入依赖:

 <!--邮箱发送依赖-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!--redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
<!--hutool工具类-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.12</version>
        </dependency>

2.开启qq邮箱发送邮件功能

首先登录qq邮箱,进入设置选项

 下拉找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务

 开启STMP服务,并获取邮箱发送密码(不是qq邮箱的密码,是发送邮件需要的密码)

2.springboot配置email信息

在spring配置信息下新增mail的配置,下面是参考配置

 application.yml的参考配置

mail:
    username: 你的qq邮箱号
    password: 刚刚我们获取的stmp的密码
    host: smtp.qq.com
    default-encoding: UTF-8

3.引入邮件发送的Util

下面是我当时网上找的一个我认为还不错的一个sendEmailUtils,具体是出自哪篇文章忘了,非常抱歉。

@Component
@Slf4j
public class SendEmailUtils {
    @Autowired
    private JavaMailSender javaMailSender;

    @Value("${spring.mail.username}")
    String userName;

    /**
     * 发送邮箱方法
     * @param title 标题
     * @param html 发送的html内容
     * @param message 发送的信息
     */
    public void sendHtml(String title, String html, String message) {
        MimeMessage mailMessage = javaMailSender.createMimeMessage();
        //需要借助Helper类
        MimeMessageHelper helper = new MimeMessageHelper(mailMessage);
        try {
            helper.setFrom(userName);  // 必填
            helper.setTo(message);   // 必填
//            helper.setBcc("密送人");   // 选填
            helper.setSubject(title);  // 必填
            helper.setSentDate(new Date());//发送时间
            helper.setText(html, true);   // 必填  第一个参数要发送的内容,第二个参数是不是Html格式。
            javaMailSender.send(mailMessage);
        } catch (MessagingException e) {
            log.error("发送邮件失败", e);
            throw new RuntimeException(e);
        }
    }

}

二.springboot集成redis

上面我们已经引入了依赖了,现在我们配置一下Redis

1.application.yml配置Reids

redis:
    host: 127.0.0.1
    port: 6379
    lettuce:
      pool:
        max-active: 8 #最大连接
        max-idle: 8 #最大空闲连接
        min-idle: 0 #最小空闲连接
        max-wait: 100 #连接等待时间
    database: 0

2.个性化配置Redis

@Configuration
public class RedisConfiguration {

    @Bean
    @Primary
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 为了开发方便,一般直接使用<String, Object>
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory);

        // 配置具体的序列化方式
        // JSON解析任意对象
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
        // 设置日期格式
        om.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
        jackson2JsonRedisSerializer.setObjectMapper(om);
        // String的序列化
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        //key采用String的序列化
        template.setKeySerializer(stringRedisSerializer);
        //hash的key也采用String的序列化
        template.setHashKeySerializer(stringRedisSerializer);
        //value的序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        //hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        //设置所有配置
        template.afterPropertiesSet();

        return template;
    }

}

三.整合Redis和email

1.前端内容准备

<div class="layui-form-item">
    <input id="send-email-code" name="send-email-code" style="" type="button" class="layui-btn layui-btn layui-btn-normal layui-btn-fluid" value="获取验证码"/>
</div>
var InterValObj; //timer变量,控制时间
var count = 60; //间隔函数,1秒执行
var curCount;//当前剩余秒数
//向邮箱发送验证码
$('#send-email-code').click(function(){
    //校验邮箱
    var email = $("#email").val();
    if(!email.match(/^[a-z0-9]+([._]*[a-z0-9]+)*@[a-z0-9]+([_.][a-z0-9]+)+$/gi)){
        layer.msg("邮箱格式不正确!请重新输入", {icon: 5});
        return false;
    }

    // 设置button效果,开始计时
    curCount = count;
    document.getElementById("send-email-code").setAttribute("disabled","true" );//设置按钮为禁用状态
    document.getElementById("send-email-code").value=curCount + "秒后重获";//更改按钮文字
    InterValObj = window.setInterval(SetRemainTime, 1000); // 启动计时器timer处理函数,1秒执行一次

    //请求发送验证码
     $.ajax({
        type:"get",
        url:"/email/sendEmail",
        async:false,
        data:{"email":email},
        success:function(data){
            if(data.code === 200){//验证码发送成功
                layer.msg('发送成功', {icon: 1, time: 1000}, function () {
                    $("#emailCode").removeAttr("style")
                });
            }else{
                layer.msg(data.message, {icon: 5});
            }
        },
     });
});

//timer处理函数
function SetRemainTime() {
    if (curCount == 0) {//超时重新获取验证码
        window.clearInterval(InterValObj);// 停止计时器
        document.getElementById("send-email-code").removeAttribute("disabled");//移除禁用状态改为可用
        document.getElementById("send-email-code").value="重获验证码";
    }else {
        curCount--;
        document.getElementById("send-email-code").value=curCount + "秒后重获";
    }
}

2.后端整合Redis和email

@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class EmailServiceImpl implements EmailService {

    @Resource
    private SendEmailUtils sendEmailUtils;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result sendEmail(String email) {
        String emailCode = RandomUtil.randomNumbers(6);
        log.info("本次验证码为:{}",emailCode);
        String context = "<b>尊敬的用户:</b><br><br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;您好," +
                "校园代取快递系统提醒您本次的验证码是:<b>{}</b>," +
                "有效期5分钟。<br><br><br><b>校园代取快递系统</b>";
        String html = StrUtil.format(context, emailCode);
        //发送邮件
        try {
            sendEmailUtils.sendHtml("【校园代取快递系统】邮箱注册验证", html, email);
        }catch (Exception e){
            throw new RuntimeException("邮件发送失败");
        }
        //将验证码信息存储至redis中并设置过期时间
        stringRedisTemplate.opsForValue().set(REGISTER_CODE_KEY+email,emailCode,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        Result result = new Result();
        result.setCode(NumberUtils.TWO_HUNDRED);
        result.setMessage("邮件发送成功");
        return result;
    }
}

在该方法中我们首先生成了一个随机的六位验证码,然后尝试发送邮件,发送成功后我们将我们的验证码信息存储在Redis中,并设置过期时间,这样我们就能完成邮件发送码,并设置过期时间的功能,在后面我们只需要将前端用户输入的验证码与Redis中的验证码做对比即可判断是否正确。

@Override
    public Result<HnUser> register(HnUser user, String type) {
        Result result = new Result();
        if (StringUtils.isBlank(user.getEmailCode())
                || StringUtils.isBlank(user.getUserEmail()) ){
            result.setCode(500);
            result.setMessage("邮箱或验证码错误,请重试");
            return result;
        }
        // 判断验证码是否过期
        String redisCode = stringRedisTemplate.opsForValue().get(REGISTER_CODE_KEY + user.getUserEmail());
        if (StringUtils.isBlank(redisCode)){
            result.setCode(500);
            result.setMessage("验证码已过期");
            return result;
        }
        if (!redisCode.equals(user.getEmailCode())){
            result.setCode(500);
            result.setMessage("验证码错误");
        }
        if("common".equals(type)){
            user.setUserRoleId(1);
        }else{
            user.setUserRoleId(0);
        }
        // 密码加密
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        user.setUserPassword(passwordEncoder.encode(user.getUserPassword()));
        user.setVersionNumber(0);
        List<HnUser> hnUserList = userMapper.selectByUserNameList(user);
        if(hnUserList.size() != NumberUtils.ZERO){
            result.setCode(500);
            result.setMessage("当前用户已存在");
            return result;
        }else{
            try {
                userMapper.insertSelective(user);
                result.setCode(200);
                result.setMessage("注册成功");
            }catch (Exception e){
                throw new RuntimeException(e);
            }
        }
        return result;
    }

四.功能演示

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值