springboot使用TemplateEngine修改邮箱后发送验证码示例
生活随笔
收集整理的這篇文章主要介紹了
springboot使用TemplateEngine修改邮箱后发送验证码示例
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 實體類
- controller:
- 前端頁面(Vue)
- 生成校驗驗證碼service:
- ftl模板:
- 真正發送郵箱的EmailConfigService
實體類
驗證碼pojo
@Data @AllArgsConstructor @NoArgsConstructor @TableName("verification_code") public class VerificationCode implements Serializable {@TableId//@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;private String code;/** 使用場景,自己定義 */private String scenes;/** true 為有效,false 為無效,驗證時狀態+時間+具體的郵箱或者手機號 */private Boolean status = true;/** 類型 :phone 和 email */private String type;/** 具體的phone與email */private String value;/** 創建日期 */@TableField(fill = FieldFill.INSERT)// @Column(name = "create_time")private Timestamp createTime;public VerificationCode(String code, String scenes, @NotBlank String type, @NotBlank String value) {this.code = code;this.scenes = scenes;this.type = type;this.value = value;} }郵箱配置pojo:
@Data @TableName("email_config") public class EmailConfig implements Serializable {/** ID */@TableId//@GeneratedValue(strategy = GenerationType.IDENTITY)// @Column(name = "id")private Long id;/** 收件人 */// @Column(name = "from_user")private String fromUser;/** 郵件服務器SMTP地址 */// @Column(name = "host")private String host;/** 密碼 */// @Column(name = "pass")private String pass;/** 端口 */// @Column(name = "port")private String port;/** 發件者用戶名 */// @Column(name = "user")private String user;public void copy(EmailConfig source) {BeanUtil.copyProperties(source, this, CopyOptions.create().setIgnoreNullValue(true));} }sql:
DROP TABLE IF EXISTS `verification_code`; CREATE TABLE `verification_code` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',`code` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '驗證碼',`create_time` datetime DEFAULT NULL COMMENT '創建日期',`status` bit(1) DEFAULT NULL COMMENT '狀態:1有效、0過期',`type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '驗證碼類型:email或者短信',`value` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '接收郵箱或者手機號碼',`scenes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '業務名稱:如重置郵箱、重置密碼等',PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='驗證碼'; DROP TABLE IF EXISTS `email_config`; CREATE TABLE `email_config` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',`from_user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '收件人',`host` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '郵件服務器SMTP地址',`pass` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '密碼',`port` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '端口',`user` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '發件者用戶名',PRIMARY KEY (`id`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='郵箱配置';郵箱vo
@Data @AllArgsConstructor @NoArgsConstructor public class EmailVo {/** 收件人,支持多個收件人 */@NotEmptyprivate List<String> tos;@NotBlankprivate String subject;@NotBlankprivate String content; }controller:
@RestController @RequestMapping("/api/code") @Api(tags = "工具:驗證碼管理") public class VerificationCodeController {@PostMapping(value = "/resetEmail")@ApiOperation("重置郵箱,發送驗證碼")public ResponseEntity<Object> resetEmail(@RequestBody VerificationCode code) throws Exception {code.setScenes(YshopConstant.RESET_MAIL);EmailVo emailVo = verificationCodeService.sendEmail(code);emailService.send(emailVo, emailService.find());return new ResponseEntity<>(HttpStatus.OK);}前端頁面(Vue)
<template><div style="display: inline-block;"><el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="title" append-to-body width="475px" @close="cancel"><el-form ref="form" :model="form" :rules="rules" size="small" label-width="88px"><el-form-item label="新郵箱" prop="email"><el-input v-model="form.email" auto-complete="on" style="width: 200px;" /><el-button :loading="codeLoading" :disabled="isDisabled" size="small" @click="sendCode">{{ buttonName }}</el-button></el-form-item><el-form-item label="驗證碼" prop="code"><el-input v-model="form.code" style="width: 320px;" /></el-form-item><el-form-item label="當前密碼" prop="pass"><el-input v-model="form.pass" type="password" style="width: 320px;" /></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button type="text" @click="cancel">取消</el-button><el-button :loading="loading" type="primary" @click="doSubmit">確認</el-button></div></el-dialog></div> </template><script> import store from '@/store' import { validEmail } from '@/utils/validate' import { updateEmail } from '@/api/system/user' import { resetEmail } from '@/api/system/code' export default {props: {email: {type: String,required: true}},data() {const validMail = (rule, value, callback) => {if (value === '' || value === null) {callback(new Error('新郵箱不能為空'))} else if (value === this.email) {callback(new Error('新郵箱不能與舊郵箱相同'))} else if (validEmail(value)) {callback()} else {callback(new Error('郵箱格式錯誤'))}}return {loading: false, dialog: false, title: '修改郵箱', form: { pass: '', email: '', code: '' },user: { email: '', password: '' }, codeLoading: false,codeData: { type: 'email', value: '' },buttonName: '獲取驗證碼', isDisabled: false, time: 60,rules: {pass: [{ required: true, message: '當前密碼不能為空', trigger: 'blur' }],email: [{ required: true, validator: validMail, trigger: 'blur' }],code: [{ required: true, message: '驗證碼不能為空', trigger: 'blur' }]}}},methods: {cancel() {this.resetForm()},sendCode() {if (this.form.email && this.form.email !== this.email) {this.codeLoading = truethis.buttonName = '驗證碼發送中'this.codeData.value = this.form.emailconst _this = thisresetEmail(this.codeData).then(res => {this.$message({showClose: true,message: '發送成功,驗證碼有效期5分鐘',type: 'success'})this.codeLoading = falsethis.isDisabled = truethis.buttonName = this.time-- + '秒后重新發送'this.timer = window.setInterval(function() {_this.buttonName = _this.time + '秒后重新發送'--_this.timeif (_this.time < 0) {_this.buttonName = '重新發送'_this.time = 60_this.isDisabled = falsewindow.clearInterval(_this.timer)}}, 1000)}).catch(err => {this.resetForm()this.codeLoading = falseconsole.log(err.response.data.message)})}},doSubmit() {this.$refs['form'].validate((valid) => {if (valid) {this.loading = trueupdateEmail(this.form).then(res => {this.loading = falsethis.resetForm()this.$notify({title: '郵箱修改成功',type: 'success',duration: 1500})store.dispatch('GetInfo').then(() => {})}).catch(err => {this.loading = falseconsole.log(err.response.data.message)})} else {return false}})},resetForm() {this.dialog = falsethis.$refs['form'].resetFields()window.clearInterval(this.timer)this.time = 60this.buttonName = '獲取驗證碼'this.isDisabled = falsethis.form = { pass: '', email: '', code: '' }}} } </script><style scoped></style>js: import request from '@/utils/request'export function resetEmail(data) {return request({url: 'api/code/resetEmail',method: 'post',data}) }export function updatePass(pass) {return request({url: 'api/users/updatePass/' + pass,method: 'get'}) }生成校驗驗證碼service:
import cn.hutool.core.lang.Dict; import cn.hutool.core.util.RandomUtil; import cn.hutool.extra.template.Template; import cn.hutool.extra.template.TemplateConfig; import cn.hutool.extra.template.TemplateEngine; import cn.hutool.extra.template.TemplateUtil; import co.yixiang.common.service.impl.BaseServiceImpl; import co.yixiang.exception.BadRequestException; import co.yixiang.tools.domain.VerificationCode; import co.yixiang.tools.domain.vo.EmailVo; import co.yixiang.tools.service.VerificationCodeService; import co.yixiang.tools.service.mapper.VerificationCodeMapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; @Service @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class VerificationCodeServiceImpl extends BaseServiceImpl<VerificationCodeMapper, VerificationCode> implements VerificationCodeService {@Value("${code.expiration}")private Integer expiration;@Override@Transactional(rollbackFor = Exception.class)public EmailVo sendEmail(VerificationCode code) {EmailVo emailVo;String content;VerificationCode verificationCode = this.getOne(new LambdaQueryWrapper<VerificationCode>().eq(VerificationCode::getScenes, code.getScenes()).eq(VerificationCode::getType, code.getType()).eq(VerificationCode::getValue, code.getValue()));// 如果不存在有效的驗證碼,就創建一個新的TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));Template template = engine.getTemplate("email/email.ftl");if (verificationCode == null) {code.setCode(RandomUtil.randomNumbers(6));//package cn.hutool.core.util包下的RandomUtil工具content = template.render(Dict.create().set("code", code.getCode()));emailVo = new EmailVo(Collections.singletonList(code.getValue()), "yxiang后臺管理系統", content);this.save(code);timedDestruction(code);// 存在就再次發送原來的驗證碼} else {content = template.render(Dict.create().set("code", verificationCode.getCode()));emailVo = new EmailVo(Collections.singletonList(verificationCode.getValue()), "yshop后臺管理系統", content);}return emailVo;}@Overridepublic void validated(VerificationCode code) {VerificationCode verificationCode = this.getOne(new LambdaQueryWrapper<VerificationCode>().eq(VerificationCode::getScenes, code.getScenes()).eq(VerificationCode::getType, code.getType()).eq(VerificationCode::getValue, code.getValue()).eq(VerificationCode::getStatus, true));if (verificationCode == null || !verificationCode.getCode().equals(code.getCode())) {throw new BadRequestException("無效驗證碼");} else {verificationCode.setStatus(false);this.save(verificationCode);}}/*** 定時任務,指定分鐘后改變驗證碼狀態* @param verifyCode 驗證碼*/private void timedDestruction(VerificationCode verifyCode) {//以下示例為程序調用結束繼續運行ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1,new BasicThreadFactory.Builder().namingPattern("verifyCode-schedule-pool-%d").daemon(true).build());try {executorService.schedule(() -> {verifyCode.setStatus(false);this.save(verifyCode);}, expiration * 60 * 1000L, TimeUnit.MILLISECONDS);} catch (Exception e) {e.printStackTrace();}} }ftl模板:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/><style>@page {margin: 0;}</style> </head> <body style="margin: 0px;padding: 0px;font: 100% SimSun, Microsoft YaHei, Times New Roman, Verdana, Arial, Helvetica, sans-serif;color: #000;"> <div style="height: auto;width: 820px;min-width: 820px;margin: 0 auto;margin-top: 20px;border: 1px solid #eee;"><div style="padding: 10px;padding-bottom: 0px;"><p style="margin-bottom: 10px;padding-bottom: 0px;">尊敬的用戶,您好:</p><p style="text-indent: 2em; margin-bottom: 10px;">您正在申請郵箱驗證,您的驗證碼為:</p><p style="text-align: center;font-family: Times New Roman;font-size: 22px;color: #C60024;padding: 20px 0px;margin-bottom: 10px;font-weight: bold;background: #ebebeb;">${code}</p><div class="foot-hr hr" style="margin: 0 auto;z-index: 111;width: 800px;margin-top: 30px;border-top: 1px solid #DA251D;"></div></div> </div> </body> </html>真正發送郵箱的EmailConfigService
public interface EmailConfigService extends BaseService<EmailConfig> {/*** 更新郵件配置* @param emailConfig 郵件配置* @param old 舊的配置* @return EmailConfig*/void update(EmailConfig emailConfig, EmailConfig old);/*** 查詢配置* @return EmailConfig 郵件配置*/EmailConfig find();/*** 發送郵件* @param emailVo 郵件發送的內容* @param emailConfig 郵件配置* @throws Exception /*/@Asyncvoid send(EmailVo emailVo, EmailConfig emailConfig) throws Exception; } import cn.hutool.extra.mail.Mail; import cn.hutool.extra.mail.MailAccount; @Service @AllArgsConstructor //@CacheConfig(cacheNames = "emailConfig") @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class) public class EmailConfigServiceImpl extends BaseServiceImpl<EmailConfigMapper, EmailConfig> implements EmailConfigService {private final IGenerator generator;@Override // @CachePut(key = "'1'")@Transactional(rollbackFor = Exception.class)public void update(EmailConfig emailConfig, EmailConfig old) {try {if (!emailConfig.getPass().equals(old.getPass())) {// 對稱加密emailConfig.setPass(EncryptUtils.desEncrypt(emailConfig.getPass()));}} catch (Exception e) {e.printStackTrace();}this.save(emailConfig);}@Override // @Cacheable(key = "'1'")public EmailConfig find() {EmailConfig emailConfig = this.list().get(0);return emailConfig;}@Override@Transactional(rollbackFor = Exception.class)public void send(EmailVo emailVo, EmailConfig emailConfig) {if (emailConfig == null) {throw new BadRequestException("請先配置,再操作");}// 封裝MailAccount account = new MailAccount();account.setHost(emailConfig.getHost());account.setPort(Integer.parseInt(emailConfig.getPort()));account.setAuth(true);try {// 對稱解密account.setPass(EncryptUtils.desDecrypt(emailConfig.getPass()));} catch (Exception e) {throw new BadRequestException(e.getMessage());}account.setFrom(emailConfig.getUser() + "<" + emailConfig.getFromUser() + ">");// ssl方式發送account.setSslEnable(true);// 使用STARTTLS安全連接account.setStarttlsEnable(true);String content = emailVo.getContent();// 發送try {int size = emailVo.getTos().size();Mail.create(account).setTos(emailVo.getTos().toArray(new String[size])).setTitle(emailVo.getSubject()).setContent(content).setHtml(true)//關閉session.setUseGlobalSession(false).send();} catch (Exception e) {throw new BadRequestException(e.getMessage());}} }總結
以上是生活随笔為你收集整理的springboot使用TemplateEngine修改邮箱后发送验证码示例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: redis+aop防重复提交
- 下一篇: Java多线程环境检测系统中是否存在死锁