mysql镜像文件怎么安装

发布时间: 2023-11-21 11:06 阅读: 文章来源:1MUMB947PS

前言

最近华为云云耀云服务器L实例上新,也搞了一台来玩,期间遇到各种问题,在解决问题的过程中学到不少和运维相关的知识。

本篇博客介绍RabbitMQDocker版本安装和配置,延迟插件的安装;结合QQ邮箱和阿里云短信验证码服务,采用主题模式进行验证码的发送。

关于邮箱验证码和手机短信验证码可以参考以下博客

SpringBoot项目(验证码整合)——springboot整合email & springboot整合阿里云短信服务

其他相关的华为云云耀云服务器L实例评测文章列表如下:

·初始化配置SSH连接 & 安装MySQLdocker镜像 & 安装redis以及主从搭建 & 7.2版本redis.conf配置文件

·安装Java8环境 & 配置环境变量 & spring项目部署 &!】存在问题未解决

·部署spring项目端口开放问题的解决 & 服务器项目环境搭建MySQLRedisMinio...指南

·由于自己原因导致MySQL数据库被攻击 & MySQLbinlog日志文件的理解

·认识redis未授权访问漏洞 & 漏洞的部分复现 & 设置连接密码 & redis其他命令学习

·canal | 拉取创建canal镜像配置相关参数 & 搭建canal连接MySQL数据库 & spring项目应用canal初步

·canal | 基于canal缓存自动更新流程 & SpringBoot项目应用案例和源码

·Docker版的Minio安装 & Springboot项目中的使用 & 结合vue进行图片的存取

·RedisDocker容器中安装BloomFilter & Spring中使用Redis插件版的布隆过滤器

·ElasticsearchDocker版本的安装和参数设置 & 端口开放和浏览器访问

·Elasticsearch的可视化Kibana工具安装 & IK分词器的安装和使用

·Elasticsearchspringboot整合 & Kibana进行全查询和模糊查询

引出

1.RabbitMQDocker版本安装和配置,延迟插件的安装; 2.结合QQ邮箱和阿里云短信验证码服务,采用主题模式进行验证码的发送;

RabbitMQDocker版本安装

1.拉取镜像创建容器

dockerpullrabbitmq

dockerrun-itd--name=rabbitmq_pet\-eRABBITMQ_DEFAULT_USER=admin-eRABBITMQ_DEFAULT_PASS=123\-p15672:15672-p5672:5672rabbitmq

查看rabbitmq的版本,3.9.11

docker ps查看当前运行的容器

2.开放端口和访问

华为云控制台开放端口

前端访问报错

无法显示页面

打开管理页面

前端访问,需要打开管理页面

dockerexec-itrabbitmq_petbash

rabbitmq-pluginsenablerabbitmq_management

输入用户名密码,进入rabbitmq管理页面

允许查看channels

进入rabbitmq容器进行修改

cd/etc/rabbitmq/conf.d/

echomanagement_agent.disable_metrics_collector=false>management_agent.disable_metrics_collector.conf

重启后可以进入channels页面

3.安装延迟插件

下载支持3.9.x的插件

https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases?after=rabbitmq_v3_6_12

一开始没有延迟插件,需要安装一下延迟插件

上传延迟插件到文件夹

dockercp ./rabbitmq_delayed_message_exchange-3.9.0.ezrabbitmq_pet:/plugins

进入容器,允许延迟插件

rabbitmq-pluginsenablerabbitmq_delayed_message_exchange

刷新前端页面,延迟插件安装成功

安装成功

使用rabbitmq进行验证码的发送

1.依赖导入

org.springframework.bootspring-boot-starter-amqp

spring: rabbitmq: host: 124.70.138.34 port: 5672 username: admin password: 123 # 确认收到 publisher-confirm-type: correlated publisher-returns: true

2.配置文件

package com.tianju.fresh.config;import com.tianju.fresh.util.RabbitMQConstance;import org.springframework.amqp.core.*;import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;import org.springframework.amqp.support.converter.MessageConverter;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.amqp.rabbit.connection.ConnectionFactory;import org.springframework.amqp.rabbit.core.RabbitTemplate;/** * rabbitmq的配置类 */@Configurationpublic class RabbitMQConfig { /** * 创建邮箱的队列 * @return 邮箱的rabbitmq队列 */ @Bean public Queue emailQueue(){ return new Queue( RabbitMQConstance.MQ_EMAIL_QUEUE, RabbitMQConstance.durable, RabbitMQConstance.exclusive, RabbitMQConstance.autoDelete ); } /** * 电话队列 * @return 电话的队列 */ @Bean public Queue phoneQueue(){ return new Queue( RabbitMQConstance.MQ_PHONE_QUEUE, RabbitMQConstance.durable, RabbitMQConstance.exclusive, RabbitMQConstance.autoDelete ); } /** * 队列的交换机fanout * @return 队列的交换机fanout */ @Bean public FanoutExchange fanoutExchange(){ return new FanoutExchange( RabbitMQConstance.MQ_FANOUT_EXCHANGE, RabbitMQConstance.durable, RabbitMQConstance.autoDelete ); } /** * 主题模式topic的交换机 * @return 主题模式的topic交换机 */ @Bean public TopicExchange topicExchange(){ return new TopicExchange( RabbitMQConstance.MQ_TOPIC_EXCHANGE, RabbitMQConstance.durable, RabbitMQConstance.autoDelete ); } /** * ######################建立队列和交换机的绑定关系 ################### */ /** * 建立邮箱队列和交换机的绑定关系 * @return 绑定的关系 */ @Bean public Binding emailBlinding(){ return BindingBuilder.bind(emailQueue()) .to(topicExchange()) .with("topic.email"); } /** * 建立电话队列和交换机的绑定关系 * @return */ @Bean public Binding phoneBlinding(){ return BindingBuilder.bind(phoneQueue()) .to(topicExchange()) .with("topic.phone"); } /** * ###################### 对象转换成json字符串进行发送 ############## */ @Bean public MessageConverter messageConverter(){ return new Jackson2JsonMessageConverter(); } @Bean public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){ RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); rabbitTemplate.setMessageConverter(messageConverter());// 修改转换器 return rabbitTemplate; }}

package com.tianju.fresh.util;/** * 项目中用的常量 */public interface RabbitMQConstance { /** * rabbitmq相关的常量 */ String MQ_EMAIL_QUEUE="mq_email_queue"; String MQ_PHONE_QUEUE="mq_phone_queue"; String MQ_FANOUT_EXCHANGE="mq_fanout_exchange"; String MQ_TOPIC_EXCHANGE="mq_topic_exchange"; // 参数 String name, boolean durable, boolean exclusive, boolean autoDelete boolean durable = true; // 表示队列是否持久化 boolean exclusive = false; // 是否排它式 boolean autoDelete = false;}

3.发送的业务service代码

/** * ########################## 用户注册需要的东西 ################### */ HttpResp getRegisterSMSCode(String input); /** * 发送消息给主题模式的交换机, * 交换机将消息转发给邮箱队列 * @param smsDto */ void sendToEmailQueue(SMSDto smsDto); /** * 发送消息给主题模式的交换机, * 交换机把消息发送给电话队列 * @param smsDto */ void sendToPhoneQueue(SMSDto smsDto);

service接口的实现

@Override public HttpResp getRegisterSMSCode(String input) { // 1.输入邮箱或者手机号码是否合法 // 2.redis里面是否有 // 3.根据邮箱手机发送不同的消息给交换机 // 4.返回给前端验证码 if(!SMSUtil.isEmailOrPhone(input)){ return HttpResp.failed("输入的邮箱手机号码不合法"); } if (redisUtil.isKeyInRedis(input)){ return HttpResp.failed("验证码已发送,请检查,稍后重试"); } String code = SMSUtil.getCode(); if (SMSUtil.isEmail(input)){ // 发送邮箱验证码 sendToEmailQueue( new SMSDto(input,"邮箱验证码",code) ); Map map = new HashMap(); map.put(input, code); return HttpResp.success(map); } sendToPhoneQueue( new SMSDto(input, null, code) ); return HttpResp.success(code); } @Override public void sendToEmailQueue(SMSDto smsDto) { // 发送消息给邮箱,邮箱验证码 rabbitTemplate.convertAndSend( RabbitMQConstance.MQ_TOPIC_EXCHANGE, "topic.email", smsDto ); log.debug("{} [ 邮箱验证码生产者向主题模式交换机: ] 发送一条消息 {}",new Date(), smsDto); } @Override public void sendToPhoneQueue(SMSDto smsDto) { // 生产者:发送消息给主题交换机,主题交换机把消息给电话队列 // 消费者:监听电话队列,如果电话队列有消息,就进行消费,调用发送电话验证码的方法,发送手机验证码 rabbitTemplate.convertAndSend( RabbitMQConstance.MQ_TOPIC_EXCHANGE, "topic.phone", smsDto ); log.debug("{} [ 手机验证码生产者向主题模式交换机: ] 发送一条消息 {}",new Date(), smsDto); }

smsDto实体类,进行验证码对象传输

package com.tianju.fresh.entity.dto;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data@NoArgsConstructor@AllArgsConstructorpublic class SMSDto { private String target;// 目标邮箱或者手机号码 private String msg; // 补充的消息 private String code; // 验证码}

4.监听队列消息发送验证码

package com.tianju.fresh.rabbitMQ;import com.tianju.fresh.entity.dto.SMSDto;/** * 监听手机验证码邮箱的队列 * 如果有消息,就进行消费发送验证码 */public interface ConsumerService { /** * 调用给邮箱发送验证码 * @param smsDto 数据传输层对象,包含目标邮箱,消息,验证码 */ void callSendToEmail(SMSDto smsDto); /** * 调用给手机发送短信验证码 * @param smsDto 数据传输层对象,包含目标手机号码,验证码 */ void callSendToPhone(SMSDto smsDto);}

接口代码的实现类

package com.tianju.fresh.rabbitMQ.impl;import com.tianju.fresh.entity.dto.SMSDto;import com.tianju.fresh.rabbitMQ.ConsumerService;import com.tianju.fresh.util.RabbitMQConstance;import com.tianju.fresh.util.RedisUtil;import com.tianju.fresh.util.SMSUtil;import lombok.extern.slf4j.Slf4j;import org.springframework.amqp.rabbit.annotation.RabbitListener;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import java.util.Date;@Service@Slf4jpublic class ConsumerServiceImpl implements ConsumerService { @Autowired private SMSUtil smsUtil; @Autowired private RedisUtil redisUtil; @RabbitListener(queues = RabbitMQConstance.MQ_EMAIL_QUEUE) @Override public void callSendToEmail(SMSDto smsDto) { log.debug("[ 邮箱队列消费者模块:] {} 获得一条消息{},即将发送邮箱验证码",new Date(),smsDto); smsUtil.sendEmailCode(smsDto.getTarget(),smsDto.getMsg(),smsDto.getCode()); // 存到redis里面,有效时间是5分钟 redisUtil.saveStringValue(smsDto.getTarget(), smsDto.getCode(), 60*5); log.debug("邮箱验证码存到redis中,有效期为 5分钟"); } @RabbitListener(queues = RabbitMQConstance.MQ_PHONE_QUEUE) @Override public void callSendToPhone(SMSDto smsDto) { log.debug("[ 电话队列消费者模块:] {} 获得一条消息{},即将发送手机验证码",new Date(),smsDto); smsUtil.sendPhoneCode(smsDto.getTarget(), smsDto.getCode()); // 验证码存到redis redisUtil.saveStringValue(smsDto.getTarget(), smsDto.getCode(), 60*5); log.debug("手机验证码存到redis中,有效期为 5分钟"); }}

5.用到的工具类

package com.tianju.fresh.util;import com.aliyuncs.CommonRequest;import com.aliyuncs.CommonResponse;import com.aliyuncs.DefaultAcsClient;import com.aliyuncs.IAcsClient;import com.aliyuncs.exceptions.ClientException;import com.aliyuncs.exceptions.ServerException;import com.aliyuncs.http.MethodType;import com.aliyuncs.profile.DefaultProfile;import lombok.extern.slf4j.Slf4j;import net.minidev.json.JSONObject;import org.springframework.beans.factory.annotation.Value;import org.springframework.context.annotation.PropertySource;import org.springframework.mail.SimpleMailMessage;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.text.SimpleDateFormat;import java.util.Date;import java.util.HashMap;import java.util.Map;import java.util.Random;import java.util.regex.Matcher;import java.util.regex.Pattern;@Component@PropertySource("classpath:config/ali.properties")@Slf4jpublic class SMSUtil { // 阿里云短信服务的配置 @Value("${ali.msg.AccessIdKey}") private String AccessIdKey; @Value("${ali.msg.AccessKeySecret}") private String AccessKeySecret; // QQ邮箱的配置 @Value("${spring.mail.username}") private String from; @Resource private JavaMailSender javaMailSender; /** * 发送手机验证码 * @param tel 接收验证码的手机号码 * @param code 验证码 */ public void sendPhoneCode(String tel,String code) { DefaultProfile profile = DefaultProfile.getProfile( "cn-hangzhou", AccessIdKey, //AccessIdKey AccessKeySecret); //AccessKey Secret IAcsClient client = new DefaultAcsClient(profile); CommonRequest request = new CommonRequest(); request.setSysMethod(MethodType.POST); //下面这3个不要改动 request.setSysDomain("dysmsapi.aliyuncs.com"); request.setSysVersion("2017-05-25"); request.setSysAction("SendSms"); //接收短信的手机号码 request.putQueryParameter("PhoneNumbers",tel);//此处写电话号码 //短信签名名称 request.putQueryParameter("SignName","阿里云短信测试"); //短信模板ID request.putQueryParameter("TemplateCode","SMS_154950909"); //短信模板变量对应的实际值 ${code} 中的值 Map param = new HashMap(2); param.put("code", String.valueOf(code)); //写入的短信内容,验证码 request.putQueryParameter("TemplateParam", JSONObject.toJSONString(param)); try { CommonResponse response = client.getCommonResponse(request); System.out.println(response.getData()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); Date date = new Date(); String formattedDate = sdf.format(date); log.debug(" {} 时,发送一条短信验证码[ {} ]给手机 {}",formattedDate,code,tel); } catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) { e.printStackTrace(); } } /** * 发送qq邮箱的代码 * @param email 接收邮件信息的邮箱地址 * @param subject 邮件的主题:标题 * @param content 邮件的内容:你的验证码是3927 */ public void sendEmailCode(String email, String subject, String content) { SimpleMailMessage mailMessage = new SimpleMailMessage(); mailMessage.setSubject(subject); mailMessage.setTo(email); mailMessage.setText(content); mailMessage.setSentDate(new Date()); mailMessage.setFrom(from); javaMailSender.send(mailMessage); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); String formattedDate = sdf.format(mailMessage.getSentDate()); log.debug(" {} 发送一条邮件[ {} ] {}",formattedDate,mailMessage.getText(),mailMessage.getTo()); } /** * 判断是不是合法的手机号码 * @param input 待判断的手机号码 * @return */ public static boolean isPhoneNumber(String input) { String pattern = "^1[3456789]\\d{9}#34;; Pattern regex = Pattern.compile(pattern); Matcher matcher = regex.matcher(input); return matcher.matches(); } /** * 判断是不是合法的邮箱 * @param input 待判断的邮箱 * @return */ public static boolean isEmail(String input) { String pattern = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+#34;; Pattern regex = Pattern.compile(pattern); Matcher matcher = regex.matcher(input); return matcher.matches(); } /** * 判断是不是合法的手机号码,或者邮箱 * @param input * @return */ public static boolean isEmailOrPhone(String input){ if (isPhoneNumber(input)){ return true; }else return isEmail(input); } /** * 获取随机生成的4位密码 * @return 随机生成的4位密码 */ public static String getCode(){ Random random = new Random(); return random.nextInt(900000) + 100000 +""; } public static void main(String[] args) { System.out.println(getCode()); }}

package com.tianju.fresh.util;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.core.StringRedisTemplate;import org.springframework.stereotype.Component;import java.util.Set;import java.util.concurrent.TimeUnit;@Componentpublic class RedisUtil { @Autowired private RedisTemplate redisTemplate; @Autowired private StringRedisTemplate stringRedisTemplate; public void saveObjectToRedis(String key,Object json){ redisTemplate.opsForValue().set(key,json); } /** * redis里面获取json对象,如果没有,返回null * @param key * @return */ public Object getJsonFromRedis(String key){ return redisTemplate.opsForValue().get(key); } /** * 删除redis里面的值,键 * @param key 删除的键 * @return */ public Boolean deleteKey(String key){ return redisTemplate.delete(key); } /** * 存到Redis里面的 set * @param key 存的键 * @param value 存到set的值 */ public void saveSetToRedis(String key,String... value){ for (String s:value){ if (s!=null && !s.equals("")){ stringRedisTemplate.opsForSet().add(key, s); } } } /** * 判断是否在redisset * @param key * @param val * @return */ public Boolean isInSet(String key,String val){ return stringRedisTemplate.opsForSet().isMember(key, val); } /** * 获得set中的值 * @param key * @return */ public Set getSet(String key){ return stringRedisTemplate.opsForSet().members(key); } /** * redis里面的set删除数据 * @param key * @param val */ public void removeFromSet(String key,String val){ stringRedisTemplate.opsForSet().remove(key, val); } /** * 获得存到redis里面的键对应的string类型的值 * @param key * @return */ public String getStringValue(String key){ return stringRedisTemplate.opsForValue().get(key); } /** * 保存到redis里面string * @param key * @param timeout 过期时间,传的是多少s之后过期 * @param val */ public void saveStringValue(String key,String val,Integer... timeout){ if (timeout==null){ stringRedisTemplate.opsForValue().set(key,val); }else { stringRedisTemplate.opsForValue().set(key,val,timeout[0], TimeUnit.SECONDS); } } /** * 看某个键是否存在于Redis * @param key 待检验的键 * @return */ public Boolean isKeyInRedis(String key){ return stringRedisTemplate.hasKey(key); }}

6.controller层代码

package com.tianju.fresh.controller;import com.tianju.fresh.entity.vo.LoginVo;import com.tianju.fresh.resp.HttpResp;import com.tianju.fresh.service.CustomerService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;@RestController@RequestMapping("/api/user")@Slf4jpublic class CustomerController { @Autowired private CustomerService customerService; @PostMapping("/login") public HttpResp login(@RequestBody LoginVo loginVo){ log.debug("登陆前端传的参数>>>"+loginVo); return customerService.login(loginVo); } @GetMapping("/login/getSMSCode/{str}") public HttpResp getSMSCode(@PathVariable("str") String str){ log.debug("即将给邮箱/手机 "+str+"发送验证码"); return customerService.getLoginSMSCode(str); } @GetMapping("/register/getSMSCode/{str}") public HttpResp getRegisterSMSCode(@PathVariable("str") String str){ log.debug("即将给邮箱/手机 "+str+"发送验证码"); return customerService.getRegisterSMSCode(str); }}

效果展示

项目启动后,主题模式的交换机和两个队列初始化成功

邮箱队列和电话队列

交换机和队列之间的绑定关系

手机验证码

调用controller层代码后,后台打印日志

手机验证码存储到Redis里面,有效期5分钟

获得阿里云发送的短信

邮箱验证码

调用controller层接口发送邮箱验证码

邮箱验证码存到Redis里面

收到邮箱验证码

总结

1.RabbitMQDocker版本安装和配置,延迟插件的安装; 2.结合QQ邮箱和阿里云短信验证码服务,采用主题模式进行验证码的发送;

-----已授权转载

•••展开全文