当前位置: 首页 > news >正文

华为云云耀云服务器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实例上新&#xff0c;也搞了一台来玩&#xff0c;期间遇到各种问题&#xff0c;在解决问题的过程中学到不少和运维相关的知识。 本篇博客介绍RabbitMQ的Docker版本安装和配置&#xff0c;延迟插件的安装&#xff1b;结合QQ邮箱和阿里云短信验证码…...

解决Linux安装AppImage文件chrome-sandbox出错问题

问题产生 在Linux版Another Redis Desktop Manager的时候&#xff0c;打开无反应&#xff0c;使用命令行运行&#xff0c;出现了下面的报错信息&#xff1a; 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分享

企业行政许可&#xff1a;通过公司名称/公司ID/注册号或社会统一信用代码获取企业行政许可信息&#xff0c;企业行政许可信息包括许可文件名称、决定许可机关、许可内容、决定日期/有效期自、截止日期/有效期至、数据来源等。企业作品著作权&#xff1a;通过公司名称/公司ID/注…...

外汇天眼:三大方法提高容错率——成功投资者的秘密策略!

容错率是什么&#xff1f; 虽然A股市场投资体验不佳&#xff0c;但相较于中概股市场的波动&#xff0c;A股投资者仍有幸福感。以中概股的代表&#xff0c;金龙指数ETF为例&#xff0c;仅一年多时间内从85.90元下跌至20.47元&#xff0c;跌幅高达76%。 然而&#xff0c;有一位…...

设计模式-状态模式

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

支持多种格式照片处理软件Lightroom Classic 2022 mac中文功能特点

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

UML简介

UML&#xff0c;全称为Unified Modeling Language&#xff08;统一建模语言&#xff09;&#xff0c;是一种用于软件工程和系统设计的标准化建模语言。它提供了一套图形化的符号和标记&#xff0c;用于描述和表示软件系统、系统架构、流程、数据结构、行为和交互。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中指向成员的指针运算符&#xff08;.* 和 ->*&#xff09;…...

ASUS华硕ZenBook灵耀X逍遥UXF3000E_UX363EA原装出厂预装Win11系统工厂模式安装包

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

【数据结构】栈和队列-- OJ

目录 一 用队列实现栈 二 用栈实现队列 三 设计循环队列 四 有效的括号 一 用队列实现栈 225. 用队列实现栈 - 力扣&#xff08;LeetCode&#xff09; typedef int QDataType; typedef struct QueueNode {struct QueueNode* next;QDataType data; }QNode;typedef struct …...

访问Apache Tomcat的管理页面

配置访问Tomcat管理页面的用户名、密码、角色 Tomcat安装完成后&#xff0c;包含了一个管理应用&#xff0c;默认安装在 <Tomcat安装目录>/webapps/manager 例如&#xff1a; 要使用管理页面的功能&#xff0c;需要在conf/tomcat-users.xml文件中配置用户、密码及角色…...

企业组织内如何避免山头文化?

1&#xff0c;什么是山头文化 2&#xff0c;山头文化的危害 3&#xff0c;如何避免山头文化 01什么是山头文化 山头文化就是指某一组织中的一部分人员组成一个以共同利益为基础的集体&#xff0c;就如同古代占山头一样&#xff0c;在组织中形成一股无形的力量&#xff0c;其…...

【c#】线程Monitor.Wait和Monitor.Pulse使用

介绍 以一个简易版的数据库连接池的实现来说明一下 连接池的connection以队列来管理 getConnection的时候&#xff0c;如果队列中connection个数小于50&#xff0c;且暂时无可用的connection&#xff08;个数为0或者peek看下头部需要先出那个元素还处于不可用状态&#xff09;…...

GitLab平台安装中经典安装语句含义解析

yum -y install policycoreutils openssh-server openssh-clients postfix 这是一个Linux命令&#xff0c;用于使用YUM包管理器安装指定的软件包。下面是对这个命令各部分的解释&#xff1a; yum&#xff1a;这是一个Linux命令行工具&#xff0c;用于管理RPM&#xff08;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; } 记住多样例输入的模板&#xff0c;熟悉计数器…...

【Linux系统满足产品实时性需求】

一、背景&#xff1a; 应用实时性&#xff1a;应用程序1以固定周期执行实时算法&#xff1b; 应用程序2以固定周期&#xff0c;执行串口收发&#xff1b; 驱动实时性&#xff1a;驱动sdio接口&#xff0c;实现与FPGA数据交互&#xff0c;实现串口数据收发。 二、实时性保证&…...

不用休眠的 Kotlin 并发:深入对比 delay() 和 sleep()

本文翻译自&#xff1a; https://blog.shreyaspatil.dev/sleepless-concurrency-delay-vs-threadsleep 毫无疑问&#xff0c;Kotlin 语言中的协程 Coroutine 极大地帮助了开发者更加容易地处理异步编程。该特性中封装的诸多高效 API&#xff0c;可以确保开发者花费更小的精力去…...

在Ubuntu中批量创建用户

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

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

R语言AI模型部署方案:精准离线运行详解

R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...