华为云云耀云服务器L实例评测|RabbitMQ的Docker版本安装 + 延迟插件安装 QQ邮箱和阿里云短信验证码的主题模式发送
前言
最近华为云云耀云服务器L实例上新,也搞了一台来玩,期间遇到各种问题,在解决问题的过程中学到不少和运维相关的知识。
本篇博客介绍RabbitMQ的Docker版本安装和配置,延迟插件的安装;结合QQ邮箱和阿里云短信验证码服务,采用主题模式进行验证码的发送。
关于邮箱验证码和手机短信验证码可以参考以下博客
SpringBoot项目(验证码整合)——springboot整合email & springboot整合阿里云短信服务
其他相关的华为云云耀云服务器L实例评测文章列表如下:
-
初始化配置SSH连接 & 安装MySQL的docker镜像 & 安装redis以及主从搭建 & 7.2版本redis.conf配置文件
-
安装Java8环境 & 配置环境变量 & spring项目部署 &【!】存在问题未解决
-
部署spring项目端口开放问题的解决 & 服务器项目环境搭建MySQL,Redis,Minio…指南
-
由于自己原因导致MySQL数据库被攻击 & MySQL的binlog日志文件的理解
-
认识redis未授权访问漏洞 & 漏洞的部分复现 & 设置连接密码 & redis其他命令学习
-
canal | 拉取创建canal镜像配置相关参数 & 搭建canal连接MySQL数据库 & spring项目应用canal初步
-
canal | 基于canal缓存自动更新流程 & SpringBoot项目应用案例和源码
-
Docker版的Minio安装 & Springboot项目中的使用 & 结合vue进行图片的存取
-
在Redis的Docker容器中安装BloomFilter & 在Spring中使用Redis插件版的布隆过滤器
-
Elasticsearch的Docker版本的安装和参数设置 & 端口开放和浏览器访问
-
Elasticsearch的可视化Kibana工具安装 & IK分词器的安装和使用
-
Elasticsearch的springboot整合 & Kibana进行全查询和模糊查询
引出
1.RabbitMQ的Docker版本安装和配置,延迟插件的安装;
2.结合QQ邮箱和阿里云短信验证码服务,采用主题模式进行验证码的发送;
RabbitMQ的Docker版本安装
1.拉取镜像创建容器
docker pull rabbitmq
docker run -itd --name=rabbitmq_pet \
-e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=123 \
-p 15672:15672 -p 5672:5672 rabbitmq
查看rabbitmq的版本,3.9.11
docker ps查看当前运行的容器
2.开放端口和访问
华为云控制台开放端口
前端访问报错
无法显示页面
打开管理页面
前端访问,需要打开管理页面
docker exec -it rabbitmq_pet bash
rabbitmq-plugins enable rabbitmq_management
输入用户名密码,进入rabbitmq管理页面
允许查看channels
进入rabbitmq容器进行修改
cd /etc/rabbitmq/conf.d/
echo management_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
一开始没有延迟插件,需要安装一下延迟插件
上传延迟插件到文件夹
docker cp ./rabbitmq_delayed_message_exchange-3.9.0.ez rabbitmq_pet:/plugins
进入容器,允许延迟插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
刷新前端页面,延迟插件安装成功
安装成功
使用rabbitmq进行验证码的发送
1.依赖导入
<!-- rabbitmq queue的包--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency>
spring:rabbitmq:host: 124.70.138.34port: 5672username: adminpassword: 123# 确认收到publisher-confirm-type: correlatedpublisher-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的配置类*/
@Configuration
public class RabbitMQConfig {/*** 创建邮箱的队列* @return 邮箱的rabbitmq队列*/@Beanpublic Queue emailQueue(){return new Queue(RabbitMQConstance.MQ_EMAIL_QUEUE,RabbitMQConstance.durable,RabbitMQConstance.exclusive,RabbitMQConstance.autoDelete);}/*** 电话队列* @return 电话的队列*/@Beanpublic Queue phoneQueue(){return new Queue(RabbitMQConstance.MQ_PHONE_QUEUE,RabbitMQConstance.durable,RabbitMQConstance.exclusive,RabbitMQConstance.autoDelete);}/*** 队列的交换机fanout* @return 队列的交换机fanout*/@Beanpublic FanoutExchange fanoutExchange(){return new FanoutExchange(RabbitMQConstance.MQ_FANOUT_EXCHANGE,RabbitMQConstance.durable,RabbitMQConstance.autoDelete);}/*** 主题模式topic的交换机* @return 主题模式的topic交换机*/@Beanpublic TopicExchange topicExchange(){return new TopicExchange(RabbitMQConstance.MQ_TOPIC_EXCHANGE,RabbitMQConstance.durable,RabbitMQConstance.autoDelete);}/*** ######################建立队列和交换机的绑定关系 ###################*//*** 建立邮箱队列和交换机的绑定关系* @return 绑定的关系*/@Beanpublic Binding emailBlinding(){return BindingBuilder.bind(emailQueue()).to(topicExchange()).with("topic.email");}/*** 建立电话队列和交换机的绑定关系* @return*/@Beanpublic Binding phoneBlinding(){return BindingBuilder.bind(phoneQueue()).to(topicExchange()).with("topic.phone");}/*** ###################### 对象转换成json字符串进行发送 ##############*/@Beanpublic MessageConverter messageConverter(){return new Jackson2JsonMessageConverter();}@Beanpublic 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 autoDeleteboolean 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接口的实现
@Overridepublic 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);}@Overridepublic void sendToEmailQueue(SMSDto smsDto) {// 发送消息给邮箱,邮箱验证码rabbitTemplate.convertAndSend(RabbitMQConstance.MQ_TOPIC_EXCHANGE,"topic.email",smsDto);log.debug("{} [ 邮箱验证码 生产者向 主题模式交换机: ] 发送一条消息 {}",new Date(), smsDto);}@Overridepublic 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
@AllArgsConstructor
public 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
@Slf4j
public class ConsumerServiceImpl implements ConsumerService {@Autowiredprivate SMSUtil smsUtil;@Autowiredprivate RedisUtil redisUtil;@RabbitListener(queues = RabbitMQConstance.MQ_EMAIL_QUEUE)@Overridepublic 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)@Overridepublic 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")
@Slf4j
public class SMSUtil {// 阿里云短信服务的配置@Value("${ali.msg.AccessIdKey}")private String AccessIdKey;@Value("${ali.msg.AccessKeySecret}")private String AccessKeySecret;// QQ邮箱的配置@Value("${spring.mail.username}")private String from;@Resourceprivate JavaMailSender javaMailSender;/*** 发送手机验证码* @param tel 接收验证码的手机号码* @param code 验证码*/public void sendPhoneCode(String tel,String code) {DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou",AccessIdKey, //AccessIdKeyAccessKeySecret); //AccessKey SecretIAcsClient 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","阿里云短信测试");//短信模板IDrequest.putQueryParameter("TemplateCode","SMS_154950909");//短信模板变量对应的实际值 ${code} 中的值Map<String,String> 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}$";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.-]+$";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;@Component
public class RedisUtil {@Autowiredprivate RedisTemplate<String,Object> redisTemplate;@Autowiredprivate 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);}}}/*** 判断是否在redis的set中* @param key* @param val* @return*/public Boolean isInSet(String key,String val){return stringRedisTemplate.opsForSet().isMember(key, val);}/*** 获得set中的值* @param key 键* @return*/public Set<String> 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")
@Slf4j
public class CustomerController {@Autowiredprivate 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.RabbitMQ的Docker版本安装和配置,延迟插件的安装;
2.结合QQ邮箱和阿里云短信验证码服务,采用主题模式进行验证码的发送;
相关文章:

华为云云耀云服务器L实例评测|RabbitMQ的Docker版本安装 + 延迟插件安装 QQ邮箱和阿里云短信验证码的主题模式发送
前言 最近华为云云耀云服务器L实例上新,也搞了一台来玩,期间遇到各种问题,在解决问题的过程中学到不少和运维相关的知识。 本篇博客介绍RabbitMQ的Docker版本安装和配置,延迟插件的安装;结合QQ邮箱和阿里云短信验证码…...
解决Linux安装AppImage文件chrome-sandbox出错问题
问题产生 在Linux版Another Redis Desktop Manager的时候,打开无反应,使用命令行运行,出现了下面的报错信息: linux: FATAL:setuid_sandbox_host.cc(158)] The SUID sandbox helper binary was found, but is not configured co…...

Axios、SASS学习笔记
目录 前言 一、Axios基础认识 1、简介 2、相关文档 3、基本配置 4、基础快捷使用 二、Axios封装 1、公共配置文件 2、细化每个接口的配置 3、使用并发送请求 三、SASS 1、简介 2、相关文档 3、使用前奏 4、使用变量 5、嵌套规则 6、父级选择器标识 & 前言…...
开发工作中常用到的免费API分享
企业行政许可:通过公司名称/公司ID/注册号或社会统一信用代码获取企业行政许可信息,企业行政许可信息包括许可文件名称、决定许可机关、许可内容、决定日期/有效期自、截止日期/有效期至、数据来源等。企业作品著作权:通过公司名称/公司ID/注…...

外汇天眼:三大方法提高容错率——成功投资者的秘密策略!
容错率是什么? 虽然A股市场投资体验不佳,但相较于中概股市场的波动,A股投资者仍有幸福感。以中概股的代表,金龙指数ETF为例,仅一年多时间内从85.90元下跌至20.47元,跌幅高达76%。 然而,有一位…...

设计模式-状态模式
介绍 一个对象有状态变化每次状态变化都会触发一个逻辑不能总是用if else来控制 示例 交通信号灯不同颜色的变化 UML类图 传统UML类图 简化后的UML类图 代码演示 // 状态(红灯、绿灯、黄灯) class State {constructor(color) {this.color col…...

支持多种格式照片处理软件Lightroom Classic 2022 mac中文功能特点
Lightroom Classic 2022 mac是一款专业级数字图像处理软件,主要用于数字照片的后期处理和管理。它提供了丰富的工具和功能,可以帮助用户对照片进行调整、修饰、管理和分享。 Lightroom Classic 2022 mac软件功能和特点 RAW格式支持:Lightroo…...

UML简介
UML,全称为Unified Modeling Language(统一建模语言),是一种用于软件工程和系统设计的标准化建模语言。它提供了一套图形化的符号和标记,用于描述和表示软件系统、系统架构、流程、数据结构、行为和交互。UML的设计旨在…...
【PostgreSQL内核学习(十七)—— (AutoAnalyze)】
AutoAnalyze 概述AutoAnaProcess 类AutoAnaProcess 函数AutoAnaProcess::executeSQLCommand 函数AutoAnaProcess::runAutoAnalyze 函数AutoAnaProcess::run 函数AutoAnaProcess::check_conditions 函数AutoAnaProcess::cancelAutoAnalyze 函数AutoAnaProcess::~AutoAnaProcess …...
C++中指向成员的指针运算符(.* 和 ->*)用法说明
目录 一 MSDN中使用说明1.1 语法1.2 备注 二 一个使用案例 一 MSDN中使用说明 1.1 语法 expression .* expression //直接成员解除引用运算符 expression –>* expression //间接成员解除引用运算符 1.2 备注 C中指向成员的指针运算符(.* 和 ->*)…...

ASUS华硕ZenBook灵耀X逍遥UXF3000E_UX363EA原装出厂预装Win11系统工厂模式安装包
下载链接:https://pan.baidu.com/s/1WLPp0e5AZErtX3bJIhTZMg?pwd2j7i 带有ASUS Recovery恢复功能、自带所有驱动、出厂主题壁纸、Office办公软件、MyASUS华硕电脑管家等预装程序 所需要工具:16G或以上的U盘(非必需) 文件格式:HDI,SWP,OFS,E…...

【数据结构】栈和队列-- OJ
目录 一 用队列实现栈 二 用栈实现队列 三 设计循环队列 四 有效的括号 一 用队列实现栈 225. 用队列实现栈 - 力扣(LeetCode) typedef int QDataType; typedef struct QueueNode {struct QueueNode* next;QDataType data; }QNode;typedef struct …...

访问Apache Tomcat的管理页面
配置访问Tomcat管理页面的用户名、密码、角色 Tomcat安装完成后,包含了一个管理应用,默认安装在 <Tomcat安装目录>/webapps/manager 例如: 要使用管理页面的功能,需要在conf/tomcat-users.xml文件中配置用户、密码及角色…...
企业组织内如何避免山头文化?
1,什么是山头文化 2,山头文化的危害 3,如何避免山头文化 01什么是山头文化 山头文化就是指某一组织中的一部分人员组成一个以共同利益为基础的集体,就如同古代占山头一样,在组织中形成一股无形的力量,其…...
【c#】线程Monitor.Wait和Monitor.Pulse使用
介绍 以一个简易版的数据库连接池的实现来说明一下 连接池的connection以队列来管理 getConnection的时候,如果队列中connection个数小于50,且暂时无可用的connection(个数为0或者peek看下头部需要先出那个元素还处于不可用状态)…...

GitLab平台安装中经典安装语句含义解析
yum -y install policycoreutils openssh-server openssh-clients postfix 这是一个Linux命令,用于使用YUM包管理器安装指定的软件包。下面是对这个命令各部分的解释: yum:这是一个Linux命令行工具,用于管理RPM(Red …...
湘潭大学 2023年下学期《C语言》作业0x03-循环1 XTU OJ 1094,1095,1096,1112,1113
第一题 #include<stdio.h>int main() {int t;int count1;scanf("%d",&t);while(t--){int a,b,c;scanf("%d%d",&a,&b);cab;printf("Case %d: %d\n",count,c);count;}return 0; } 记住多样例输入的模板,熟悉计数器…...
【Linux系统满足产品实时性需求】
一、背景: 应用实时性:应用程序1以固定周期执行实时算法; 应用程序2以固定周期,执行串口收发; 驱动实时性:驱动sdio接口,实现与FPGA数据交互,实现串口数据收发。 二、实时性保证&…...

不用休眠的 Kotlin 并发:深入对比 delay() 和 sleep()
本文翻译自: https://blog.shreyaspatil.dev/sleepless-concurrency-delay-vs-threadsleep 毫无疑问,Kotlin 语言中的协程 Coroutine 极大地帮助了开发者更加容易地处理异步编程。该特性中封装的诸多高效 API,可以确保开发者花费更小的精力去…...

在Ubuntu中批量创建用户
一、背景知识 在Linux操作系统中创建新用户可以使用useradd或adduser命令。 使用useradd命令创建用户时,不会在/home目录下创建用户文件夹,需要用户自己指定主目录和bash目录的位置。同时,创建的用户没有设置密码,无法进行登录&a…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...

调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
【Go】3、Go语言进阶与依赖管理
前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课,做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程,它的核心机制是 Goroutine 协程、Channel 通道,并基于CSP(Communicating Sequential Processes࿰…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...

以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

安宝特案例丨Vuzix AR智能眼镜集成专业软件,助力卢森堡医院药房转型,赢得辉瑞创新奖
在Vuzix M400 AR智能眼镜的助力下,卢森堡罗伯特舒曼医院(the Robert Schuman Hospitals, HRS)凭借在无菌制剂生产流程中引入增强现实技术(AR)创新项目,荣获了2024年6月7日由卢森堡医院药剂师协会࿰…...

GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...