赞
踩
目录
获取授权码链接:什么是授权码,它又是如何设置?_QQ邮箱帮助中心
2、在applicaion.yml资源文件中加入redis资源
starter会把所有用到的依赖都给包含进来,避免了开发者自己去引入依赖所带来的麻烦。 需要注意的是不同的starter是为了解决不同的依赖,所以它们内部的实现可能会有很大的差异,例如jpa的starter和Redis的starter可能实现就不一样,这是因为starter的本质在于synthesize, 这是一层在逻辑层面的抽象,也许这种理念有点类似于Docker,因为它们都是在做一个“包装”的操作。
虽然不同的starter实现起来各有差异, 但是他们基本上都会使用到两个相同的内容:ConfigurationProperties和AutoConfiguration。 因为SpringBoot坚信“约定大于配置”这一理念,所以我们使用ConfigurationProperties来保存我们的配置, 并且这些配置都可以有一个默认值,即在我们没有主动覆写原始配置的情况下,默认值就会生效,这在很多情况下是非常有用的。除此之外,starter的ConfigurationProperties还使得所有的配置属性被聚集到一个文件中 (一般在resources目录下的application.properties),这样我们就告别了Spring项目中XML地狱。
注意:其中最关键的是配置文件,用户可以自定义配置文件将自己的邮箱地址写入,以便提高邮箱灵活性
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-mail</artifactId>
- </dependency>
spring: application: name: springBoot_06 mail: host: smtp.qq.com username: 自己qq@qq.com password: exgdllmxqrhrieae properties: mail: smtp: auth: true starttls: enable: true required: true
- package com.zj.code;
-
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.mail.SimpleMailMessage;
- import org.springframework.mail.javamail.JavaMailSender;
-
- @SpringBootTest
- class SpringBoot06ApplicationTests {
-
- @Autowired
- JavaMailSender mailSender;
-
- @Test
- void contextLoads() {
- SimpleMailMessage message = new SimpleMailMessage();
- message.setFrom("1551506470@qq.com");
- message.setTo("1551506470@qq.com");
- message.setSubject("主题:简单邮件");
- message.setText("测试邮件内容");
- mailSender.send(message);
-
-
- }
- }
注意:在测试类中特别要注意的地方就是要将以下注解打上
@Autowired JavaMailSender mailSender;
测试成功
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-mail</artifactId>
- </dependency>
注意:在yml文件中四个属性的意思分别是
email:
enable: true --是否开启邮箱验证
host: smtp.qq.com --主机
username:自己qq@qq.com --账号(发送方)
password: uqoimlnpljuqihdd --密码(注意,此处这里是授权码,而不是密码)
EmailProperties:
- package com.yzm.yzmspringbootstarter;
-
- import lombok.AllArgsConstructor;
- import lombok.Data;
- import lombok.NoArgsConstructor;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.context.properties.ConfigurationProperties;
- import org.springframework.stereotype.Component;
-
- /**
- * @author T440s
- */
-
-
- @NoArgsConstructor
- @AllArgsConstructor
- @Data
- @ConfigurationProperties(prefix= "email")
- public class EmailProperties {
-
- private String host;
- private String username;
- private String password;
- private String enable;
-
- }
关于四个注解的说明:
@NoArgsConstructor:无参构造
@AllArgsConstructor:有参构造
@Data:get和set方法
@ConfigurationProperties(prefix= "email")作用:根据属性完成yml注入(需要bean对象被spring容器管理)
接口:EmailSender:
- package com.yzm.yzmspringbootstarter;
-
- public interface EmailSender {
- String sendText(String receiver);
- }
接口实现类:
EmailSenderImpl:
- package com.yzm.yzmspringbootstarter;
-
-
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
- import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
- import org.springframework.boot.context.properties.EnableConfigurationProperties;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.mail.SimpleMailMessage;
- import org.springframework.mail.javamail.JavaMailSenderImpl;
-
- import java.util.Properties;
-
- @Configuration
- @Slf4j
- @EnableConfigurationProperties(value = EmailProperties.class)
- @ConditionalOnProperty(prefix = "email", value = "enable", havingValue = "true")
- public class EmailSenderImpl implements EmailSender {
-
- private final EmailProperties emailProperties;
- private final JavaMailSenderImpl mailSender;
-
-
- @Autowired
- public EmailSenderImpl(EmailProperties emailProperties) {
- this.emailProperties = emailProperties;
- mailSender = new JavaMailSenderImpl();
- mailSender.setHost(emailProperties.getHost());
- mailSender.setUsername(emailProperties.getUsername());
- mailSender.setPassword(emailProperties.getPassword());
- mailSender.setDefaultEncoding("Utf-8");
- Properties p = new Properties();
- p.setProperty("mail.smtp.auth", "true");
- p.setProperty("mail.smtp.starttl .enable", "true");
- p.setProperty("mail.smtp.starttls.required", "true");
- mailSender.setJavaMailProperties(p);
- }
-
-
- @Override//此方法是发送验证码,并且是要显示接受方
- public String sendText(String receiver) {
- SimpleMailMessage message = new SimpleMailMessage();
- message.setFrom(emailProperties.getUsername());
- message.setTo(receiver);
- message.setSubject("网站验证码");
- message.setText("aabb");
- mailSender.send(message);
- return "aabb";
- }
-
- }
关于此类四个注解的说明:
@Configuration:将此类声明为组件,并且交给spring进行管理
@Slf4j:日志输出
@EnableConfigurationProperties(value = EmailProperties.class)完成对应元素组件化
@ConditionalOnProperty(prefix = "email", value = "enable", havingValue = "true")控制邮件功能是否可用
测试类:
- package com.yzm.yzmspringbootstarter;
-
- import org.junit.jupiter.api.Test;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.boot.test.context.SpringBootTest;
-
- @SpringBootTest
- class YzmSpringBootStarterApplicationTests {
-
-
- @Autowired
- private EmailSender sender;
-
- @Test
- void contextLoads() {
- sender.sendText("1551506470@qq.com");
- }
- }
测试成功
注意:在制作邮箱的过程中需要注意两个问题:
1、在yml文件中的email中的格式要规范(中间要空一格)
()()email: enable: true host: smtp.qq.com username: 自己qq@qq.com password: uqoimlnpljuqihdd
2、账号以及收件方的都是写qq号码+qq.com,而不是创建邮箱时的账号
username: 自己qq@qq.com
由于每个人的邮箱都不一样,不可能将发送和收件人的邮箱以及是否启用邮箱都固定,所以要将yml中的内容进行更改,提高邮箱使用灵活性。
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-configuration-processor</artifactId>
- <optional>true</optional>
- </dependency>
-
-
- <plugin>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-maven-plugin</artifactId>
- <version>2.4.1</version>
- <configuration><classifier>exec</classifier></configuration>
- </plugin>
-
-
META-INF > spring.factories
文件内容:
org.springframework.boot.autoconfigure.
EnableAutoConfiguration=com.yzm.yzmspringbootstarter.EmailSenderImpl
此段代码的说明:当整个项目运行时,对应类就会随着运行
查看是否添加文件成功:
最后到本地仓库中查看有没有yzm这个文件夹(这个名字就是自己命名的)可以在pom文件中查看
<modelVersion>4.0.0</modelVersion> <groupId>com.yzm</groupId> <artifactId>yzm-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> <name>yzm-spring-boot-starter</name> <description>yzm-spring-boot-starter</description>
打包成功。
<dependency> <groupId>com.yzm</groupId> <artifactId>yzm-spring-boot-starter</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency>
@Autowired private EmailSender emailSender;
导入此注解时会进行报错,原因:没有配置资源文件
spring: application: name: springBoot_06 email: host: smtp.qq.com username: 自己qq@qq.com password: exgdllmxqrhrieae
加了基本配置文件后,还是报错(原因:没有开启邮箱,有提示说明导入依赖成功)
导入成功
由于现在数据繁多,不可能每次都会进入到数据库拿取数据,这时候就会运用缓存来提高程序运行速度。
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-data-redis</artifactId>
- </dependency>
- redis:
- database: 0 #数据库索引
- host: 127.0.0.1 #主机位置
- port: 6379 #端口
- password: #密码
- jedis:
- pool:
- max-active: 8 #最大连接数
- max-wait: -1 #最大阻塞等待时间(负数表示没限制)
- max-idle: 8 #最大空闲
- min-idle: 0 #最小空闲
- timeout: 10000 #连接超时时间
conf--->CrossConfiguration
- package com.zj.code.conf;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.CorsRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
-
- /**
- * @author 银喾
- */
- @Configuration
- public class CrossConfiguration extends WebMvcConfigurerAdapter {
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry
- /*可以跨域的路径*/
- .addMapping("/**")
- /*可以跨域的ip*/
- .allowedOrigins("*")
- /*可以跨域的方法*/
- .allowedMethods("*")
- /*设置预检请求多就失效*/
- .maxAge(6000)
- /*允许携带的头部*/
- .allowedHeaders("*");
- }
-
- }
conf--->RedisConfiguration
- package com.zj.code.conf;
-
- import org.springframework.cache.CacheManager;
- import org.springframework.cache.annotation.CachingConfigurerSupport;
- import org.springframework.cache.annotation.EnableCaching;
- import org.springframework.cache.interceptor.KeyGenerator;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Primary;
- import org.springframework.data.redis.cache.RedisCacheConfiguration;
- import org.springframework.data.redis.cache.RedisCacheManager;
- import org.springframework.data.redis.connection.RedisConnectionFactory;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
- import org.springframework.data.redis.serializer.RedisSerializationContext;
- import org.springframework.data.redis.serializer.RedisSerializer;
- import org.springframework.data.redis.serializer.StringRedisSerializer;
- import org.springframework.util.ClassUtils;
-
- import java.lang.reflect.Array;
- import java.lang.reflect.Method;
- import java.time.Duration;
-
- /**
- * @author 银喾
- */
- @Configuration
- @EnableCaching
- public class RedisConfiguration extends CachingConfigurerSupport {
-
- @Bean
- @Primary
- CacheManager cacheManager(RedisConnectionFactory factory) {
- RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
- .computePrefixWith(cacheName -> cacheName + ":-cache-:")
- /*设置缓存过期时间*/
- .entryTtl(Duration.ofHours(1))
- /*禁用缓存空值,不缓存null校验*/
- .disableCachingNullValues()
- /*设置CacheManager的值序列化方式为json序列化,可使用加入@Class属性*/
- .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(
- new GenericJackson2JsonRedisSerializer()
- ));
- /*使用RedisCacheConfiguration创建RedisCacheManager*/
- RedisCacheManager manager = RedisCacheManager.builder(factory)
- .cacheDefaults(cacheConfiguration)
- .build();
- return manager;
- }
-
- @Bean
- @Primary
- public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
- RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
- redisTemplate.setConnectionFactory(factory);
- RedisSerializer stringSerializer = new StringRedisSerializer();
- /* key序列化 */
- redisTemplate.setKeySerializer(stringSerializer);
- /* value序列化 */
- redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
- /* Hash key序列化 */
- redisTemplate.setHashKeySerializer(stringSerializer);
- /* Hash value序列化 */
- redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
- redisTemplate.afterPropertiesSet();
- return redisTemplate;
- }
-
- @Bean
- @Primary
- @Override
- public KeyGenerator keyGenerator() {
- return (Object target, Method method, Object... params) -> {
- final int NO_PARAM_KEY = 0;
- final int NULL_PARAM_KEY = 53;
- StringBuilder key = new StringBuilder();
- /* Class.Method: */
- key.append(target.getClass().getSimpleName())
- .append(".")
- .append(method.getName())
- .append(":");
- if (params.length == 0) {
- return key.append(NO_PARAM_KEY).toString();
- }
- int count = 0;
- for (Object param : params) {
- /* 参数之间用,进行分隔 */
- if (0 != count) {
- key.append(',');
- }
- if (param == null) {
- key.append(NULL_PARAM_KEY);
- } else if (ClassUtils.isPrimitiveArray(param.getClass())) {
- int length = Array.getLength(param);
- for (int i = 0; i < length; i++) {
- key.append(Array.get(param, i));
- key.append(',');
- }
- } else if (ClassUtils.isPrimitiveOrWrapper(param.getClass()) || param instanceof String) {
- key.append(param);
- } else {
- /*JavaBean一定要重写hashCode和equals*/
- key.append(param.hashCode());
- }
- count++;
- }
- return key.toString();
- };
- }
-
- }
util-->RedisUtil(由于内容过长,这个类在上一篇博客中有,建议到上篇博客摘要)
https://blog.csdn.net/m0_53151031/article/details/122831095?spm=1001.2014.3001.5501
pojo:
- package com.zj.code.pojo;
-
-
- import lombok.Data;
-
- @Data
- public class User {
- private String account;
- }
UserController:
- package com.zj.code.controller;
-
-
- import com.yzm.yzmspringbootstarter.EmailSender;
- import com.zj.code.pojo.User;
- import com.zj.code.util.RedisUtil;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.cache.annotation.CachePut;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import java.util.concurrent.TimeUnit;
-
-
- @RestController
- @RequestMapping("/user")
- public class UserController {
-
-
- private EmailSender sender;
-
-
- @GetMapping("/register")
- public String register(User user) {
- if (user.getAccount().length() < 5) {
- return "不符合规则";
- }
- String yzm = RedisUtil.StringOps.get(user.getAccount());
- if (yzm == null) {
- yzm = sender.sendText(user.getAccount());
- RedisUtil.StringOps.setEx(user.getAccount(), yzm, 1, TimeUnit.MINUTES);
- return "验证码已发送";
- }
- return "验证码还是有效期";
- }
-
- /**
- * 判断当前验证码与缓存中的验证码一致
- * @param user 用户
- * @param yzm 当前验证码
- * @return 当前验证码与该用户在缓存中的验证是否是一致的
- */
- @GetMapping("/verify")
- public String verify(User user,String yzm) {
- String code = RedisUtil.StringOps.get(user.getAccount());
- if(code==null){
- return "验证码无效";
- }
- return code.equals(yzm)?"yes":"no";
- }
-
- }
运行之后出现一个错误:
原因是没有打上自动注入注解
运行成功
前言:在我们注册一个邮箱时,往往会出现注册缓慢,理想状态应该为先出现注册成功,在之后出现邮箱发送成功
1、消息队列
2、异步操作
通常采取第二种方法,使用异步操作
1、创建一个task类,专用来发送验证码
- package com.zj.code.util;
-
-
- import com.yzm.yzmspringbootstarter.EmailSender;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.scheduling.annotation.Async;
- import org.springframework.stereotype.Component;
-
- import java.util.concurrent.TimeUnit;
-
- @Component
- public class Task {
-
- @Autowired
- private EmailSender sender;
-
- @Async
- public void sendYzm(String account){
- String yzm = sender.sendText(account);
- RedisUtil.StringOps.setEx(account, yzm, 1, TimeUnit.MINUTES);
-
- }
-
-
- }
注意点:
一定要注入注解,不然会报错
其中
@Component(将此类声明为bean对象交给spring进行管理)
@Autowired(将其他类注入进来)
@Async(异步注解)这三个注解尤为重要
2、在启动类中注入开启异步注解
@EnableAsync
3、在controller类中注入task注解,
@Autowired private Task task;
- package com.zj.code.controller;
-
-
- import com.yzm.yzmspringbootstarter.EmailSender;
- import com.zj.code.pojo.User;
- import com.zj.code.util.RedisUtil;
- import com.zj.code.util.Task;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.cache.annotation.CachePut;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.web.bind.annotation.GetMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.RestController;
-
- import java.util.concurrent.TimeUnit;
-
-
- @RestController
- @RequestMapping("/user")
- public class UserController {
-
-
-
- @Autowired
- private Task task;
-
-
- @GetMapping("/register")
- public String register(User user) {
- if (user.getAccount().length() < 5) {
- return "不符合规则";
- }
- String yzm = RedisUtil.StringOps.get(user.getAccount());
- if (yzm == null) {
- task.sendYzm(user.getAccount());
- return "验证码已发送";
- }
- return "验证码还是有效期";
- }
-
- /**
- * 判断当前验证码与缓存中的验证码一致
- * @param user 用户
- * @param yzm 当前验证码
- * @return 当前验证码与该用户在缓存中的验证是否是一致的
- */
- @GetMapping("/verify")
- public String verify(User user,String yzm) {
- String code = RedisUtil.StringOps.get(user.getAccount());
- if(code==null){
- return "验证码无效";
- }
- return code.equals(yzm)?"yes":"no";
- }
-
- }
4、进行测试
很明显和之前的运行结果进行比较得出,使用异步操作可以提高程序运行速度,对于此上,真正的验证码还没有发送。
今天的知识就分享到这了,希望能够帮助到大家,制作不易,点赞则是对我最大的鼓励。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。