Springboot整合阿里云腾讯云发送短信验证码 可随时切换短信运营商
本文描述了在springboot项目中整合实现对接阿里云 和 腾讯云的短信验证码发送,可通过更改配置文件达到切换短信发送运营商(申请签名、短信模版这些本文不在叙述)。
首先看下大体结构:
一、需要导入的jar
<dependency><groupId>com.tencentcloudapi</groupId><artifactId>tencentcloud-sdk-java</artifactId><version>4.0.11</version> </dependency> <dependency><groupId>com.aliyun</groupId><artifactId>dysmsapi20170525</artifactId><version>2.0.24</version> </dependency><dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-core</artifactId><version>2.18.3</version> </dependency>
二、 短信枚举类
/*** 短信平台枚举类*/
public enum UnitySmsType {Qcloud,Aliyun,//其它运营商xxx;private UnitySmsType() {}
}
三、短信配置类
package com.starlink.phonerent.modules.common.sms;import java.util.Map;import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;/*** 短信配置类*/
@Data
@Component
@ConfigurationProperties("my_project.sms")
public class UnitySmsProperties {public static final String PREFIX = "jip.sms";private UnitySmsType unitySmsType;private String accessKeyId;private String accessKeySecret;private Map<String, Object> extend;private Map<String, SignTemplate> configs;private String region;private String smsSdkAppid;public UnitySmsProperties() {this.unitySmsType = UnitySmsType.Aliyun;}@Datapublic static class SignTemplate {private static final Integer DEFAULT_LENGTH = 6;private static final Integer DEFAULT_TIMEOUT = 60;private static final Integer DEFAULT_EXPIRE = 300;private String sign;private String templateCode;private Integer length;private Integer timeout;private Integer expire;private boolean enabledTest;public boolean getEnabledTest() {return this.enabledTest;}public SignTemplate() {this.length = DEFAULT_LENGTH;this.timeout = DEFAULT_LENGTH;this.expire = DEFAULT_EXPIRE;this.enabledTest = false;}}
}
yml配置
my_project: #自定义配置前缀(配置类用得到)sms:smsType: Aliyun # 类型 枚举类中的类型accessKeyId: xxxxxx #短信平台申请的accessKeyIdaccessKeySecret: xxxxx #短信平台申请的accessKeySecretsmsSdkAppid: xxxxx #腾讯云需配置该参数configs:SMS_MOBILE_LOGIN: #场景值(自定义)enabledTest: true #是否测试(不会真实发短信,也不会效验)sign: 测试平台 #短信签名template-code: xxxxxxx #模板编号timeout: 60 #xxx时间内不能重新发送expire: 300 #验证码有效时间 length: 4 #生成的验证码长度
四、短信接口服务类
import java.util.List;
import java.util.Map;/*** 短信服务类*/
public interface UnitySmsService {Object getSmsClient();UnitySmsProperties getSmsConfig();JsonResult sendSms(String var1, String var2, Map var3, String var4);JsonResult sendSms(String var1, String[] var2, List<Map> var3, String[] var4);}
五、短信实现类
1.阿里云
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendBatchSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendBatchSmsResponse;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.google.gson.Gson;
import java.util.List;
import java.util.Map;
import com.starlink.phonerent.common.JsonResult;
import com.starlink.phonerent.modules.common.sms.UnitySmsProperties;
import com.starlink.phonerent.modules.common.sms.UnitySmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;/*** 阿里云短信服务实现类*/
@Slf4j
@Service
public class UnitySmsServiceAliyunImpl implements UnitySmsService {private Client client;private UnitySmsProperties unitySmsProperties;public UnitySmsServiceAliyunImpl(UnitySmsProperties unitySmsProperties) throws Exception {this.unitySmsProperties = unitySmsProperties;Config smsConfig = (new Config()).setAccessKeyId(unitySmsProperties.getAccessKeyId()).setAccessKeySecret(unitySmsProperties.getAccessKeySecret());smsConfig.endpoint = "dysmsapi.aliyuncs.com";this.client = new Client(smsConfig);}public Object getSmsClient() {return this.client;}public UnitySmsProperties getSmsConfig() {return this.unitySmsProperties;}public JsonResult sendSms(String templateCode, String phoneNumber, Map templateParam, String signName) {SendSmsRequest sendSmsRequest = (new SendSmsRequest()).setPhoneNumbers(phoneNumber).setSignName(signName).setTemplateCode(templateCode).setTemplateParam((new Gson()).toJson(templateParam));try {SendSmsResponse sendSmsResponse = this.client.sendSms(sendSmsRequest);return "OK".equals(sendSmsResponse.getBody().getCode()) ? JsonResult.success(sendSmsResponse.getBody().toMap()) : JsonResult.failed(sendSmsResponse.getBody().getMessage());} catch (Exception var7) {log.error("发送短信失败", var7);return JsonResult.failed("发送短信失败," + var7.getMessage());}}public JsonResult sendSms(String templateCode, String[] phoneNumber, List<Map> templateParams, String[] signNames) {if (phoneNumber != null && templateParams != null && signNames != null) {if (phoneNumber.length == templateParams.size() && templateParams.size() == signNames.length) {Gson gson = new Gson();SendBatchSmsRequest sendBatchSmsRequest = (new SendBatchSmsRequest()).setTemplateCode(templateCode).setPhoneNumberJson(gson.toJson(phoneNumber)).setSignNameJson(gson.toJson(signNames)).setTemplateParamJson(gson.toJson(templateParams));try {SendBatchSmsResponse sendBatchSmsResponse = this.client.sendBatchSms(sendBatchSmsRequest);return "ok".equals(sendBatchSmsResponse.getBody().getCode().toLowerCase()) ? JsonResult.success(sendBatchSmsResponse.getBody().toMap()) : JsonResult.failed(sendBatchSmsResponse.getBody().getMessage());} catch (Exception var8) {log.error("发送短信失败", var8);return JsonResult.failed("发送短信失败," + var8.getMessage());}} else {return JsonResult.failed("短信签名名称、手机号码、内容需保持个数相同,内容一一对应");}} else {return JsonResult.failed("短信签名名称、手机号码、内容需保持个数相同,内容一一对应");}}
}
2.腾讯云
import com.google.gson.Gson;
import com.starlink.phonerent.common.JsonResult;
import com.starlink.phonerent.modules.common.sms.UnitySmsProperties;
import com.starlink.phonerent.modules.common.sms.UnitySmsService;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20190711.SmsClient;
import com.tencentcloudapi.sms.v20190711.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20190711.models.SendSmsResponse;import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;@Service
public class UnitySmsServiceQcloudImpl implements UnitySmsService {private static final Logger log = LoggerFactory.getLogger(UnitySmsServiceQcloudImpl.class);private SmsClient client;private UnitySmsProperties unitySmsProperties;public UnitySmsServiceQcloudImpl(UnitySmsProperties unitySmsProperties) {this.unitySmsProperties = unitySmsProperties;Credential cred = new Credential(unitySmsProperties.getAccessKeyId(), unitySmsProperties.getAccessKeySecret());HttpProfile httpProfile = new HttpProfile();httpProfile.setEndpoint("sms.tencentcloudapi.com");ClientProfile clientProfile = new ClientProfile();clientProfile.setHttpProfile(httpProfile);this.client = new SmsClient(cred, unitySmsProperties.getRegion(), clientProfile);}public Object getSmsClient() {return this.client;}public UnitySmsProperties getSmsConfig() {return this.unitySmsProperties;}public JsonResult sendSms(String templateCode, String phoneNumber, Map templateParam, String signName) {if (!phoneNumber.startsWith("86") && phoneNumber.length() == 11) {phoneNumber = "86" + phoneNumber;}SendSmsRequest req = new SendSmsRequest();try {req.setSmsSdkAppid(this.unitySmsProperties.getSmsSdkAppid());req.setSign(signName);req.setTemplateID(templateCode);req.setPhoneNumberSet(new String[]{phoneNumber});req.setTemplateParamSet((String[]) ((String[]) templateParam.values().stream().map((s) -> {return String.valueOf(s);}).toArray((x$0) -> {return new String[x$0];})));SendSmsResponse res = this.client.SendSms(req);if ("ok".equals(res.getSendStatusSet()[0].getCode().toLowerCase())) {HashMap<String, String> rm = new HashMap();res.getSendStatusSet()[0].toMap(rm, "");return JsonResult.success(rm);} else {return JsonResult.failed("发送短信失败," + res.getSendStatusSet()[0].getCode() + "," + res.getSendStatusSet()[0].getMessage());}} catch (TencentCloudSDKException var8) {return JsonResult.failed("发送短信失败," + var8.getMessage());}}public JsonResult sendSms(String templateCode, String[] phoneNumber, List<Map> templateParams, String[] signNames) {for (int i = 0; i < phoneNumber.length; ++i) {if (!phoneNumber[i].startsWith("86") && phoneNumber[i].length() == 11) {phoneNumber[i] = "86" + phoneNumber[i];}}SendSmsRequest req = new SendSmsRequest();Gson gson = new Gson();try {req.setSmsSdkAppid(this.unitySmsProperties.getSmsSdkAppid());if (signNames != null) {req.setSign(signNames[0]);}req.setTemplateID(templateCode);req.setPhoneNumberSet(phoneNumber);Stream var10001 = templateParams.stream();gson.getClass();req.setTemplateParamSet((String[]) ((String[]) var10001.map(gson::toJson).toArray()));SendSmsResponse res = this.client.SendSms(req);if ("ok".equals(res.getSendStatusSet()[0].getCode().toLowerCase())) {HashMap<String, String> rm = new HashMap();res.getSendStatusSet()[0].toMap(rm, "");return JsonResult.success(rm);} else {return JsonResult.failed("发送短信失败");}} catch (TencentCloudSDKException var9) {return JsonResult.failed("发送短信失败," + var9.getMessage());}}
}
3.其它运营商可编写各自的服务实现类即可
六、短信发送处理类
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;/*** 短信发送处理类*/
@Slf4j
@Component
public class SmsSendHandler {@Autowiredprivate UnitySmsService unitySmsService;@Autowiredprivate RedisTemplate<String, String> redisTemplate;/*** 发送短信验证码** @param scene* @param phoneNumber* @return*/public String sendCode(String scene, String phoneNumber) {if (!Validator.isMobile(phoneNumber)) {throw new AppException("不正确的手机号码");} else {UnitySmsProperties config = this.unitySmsService.getSmsConfig();UnitySmsProperties.SignTemplate signTemplate = (UnitySmsProperties.SignTemplate) config.getConfigs().get(scene);if (signTemplate == null) {throw new AppException("短信配置错误,未找到场景值:" + scene);} else {String lockKey = RedisKey.SMS_MOBILE_LOCK.get(phoneNumber);boolean check = this.redisTemplate.opsForValue().setIfAbsent(lockKey, phoneNumber, (long) signTemplate.getTimeout(), TimeUnit.SECONDS);String code;if (!check) {code = "触发[" + signTemplate.getTimeout() + "s]流控";throw new AppException(code);} else {code = RandomUtil.randomNumbers(signTemplate.getLength());Map<String, String> paramMap = new HashMap(1);paramMap.put("code", code);if (!signTemplate.getEnabledTest()) {JsonResult rs = this.unitySmsService.sendSms(signTemplate.getTemplateCode(), phoneNumber, paramMap, signTemplate.getSign());if (ObjectUtil.notEqual(BaseApiCode.SUCCESS.getCode(), rs.getCode())) {throw new AppException("短信发送失败:" + rs.getMsg());}}this.redisTemplate.opsForValue().set(RedisKey.get(scene, phoneNumber), code, (long) signTemplate.getExpire(), TimeUnit.SECONDS);return code;}}}}/*** 验证码校验** @param code* @param phoneNumber* @param scene* @return*/public boolean checkCode(String code, String phoneNumber, String scene) {UnitySmsProperties config = this.unitySmsService.getSmsConfig();UnitySmsProperties.SignTemplate signTemplate = (UnitySmsProperties.SignTemplate) config.getConfigs().get(scene);if (signTemplate == null) {throw new AppException("短信配置错误,未找到场景值:" + scene);} else if (signTemplate.getEnabledTest()) {return true;} else {String cacheKey = RedisKey.get(scene, phoneNumber);String cacheCode = (String) this.redisTemplate.opsForValue().get(cacheKey);boolean result = StrUtil.equals(code, cacheCode);if (result && code != null) {this.redisTemplate.delete(cacheKey);return true;} else {return false;}}}
}
补充统一结果返回类JsonResult(其他的异常类可根据自己项目设置)
@Data
public class JsonResult<T> implements Serializable {private int code;private T data;private String msg;private long time;public JsonResult(String msg, T result) {this.msg = msg;this.data = result;this.time = System.currentTimeMillis();}public JsonResult(ApiCode apiCode, String msg, T data) {this.msg = msg;this.code = apiCode.getCode();this.data = data;this.time = System.currentTimeMillis();}public JsonResult(ApiCode apiCode, String msg) {this.msg = msg;this.code = apiCode.getCode();this.time = System.currentTimeMillis();}public JsonResult(Integer code, String msg, T data) {this.msg = msg;this.code = code;this.data = data;this.time = System.currentTimeMillis();}public static JsonResult success(Object data, String msg) {return new JsonResult(BaseApiCode.SUCCESS, msg, data);}public static JsonResult success(Object data) {return new JsonResult(BaseApiCode.SUCCESS, null, data);}public static JsonResult success() {return new JsonResult(BaseApiCode.SUCCESS, (String) null);}public static JsonResult failed(ApiCode apiCode, String msg) {return new JsonResult(apiCode, msg);}public static JsonResult failed(String msg) {return new JsonResult(BaseApiCode.FAILED, msg);}public static JsonResult failed(Integer code, String msg) {return new JsonResult(code, msg, (Object) null);}
}
相关文章:
Springboot整合阿里云腾讯云发送短信验证码 可随时切换短信运营商
本文描述了在springboot项目中整合实现对接阿里云 和 腾讯云的短信验证码发送,可通过更改配置文件达到切换短信发送运营商(申请签名、短信模版这些本文不在叙述)。 首先看下大体结构: 一、需要导入的jar <dependency><groupId>com.…...
git 查看用户信息
在 Git 中查看用户信息是一项常见的任务,可以帮助你确认当前仓库的配置或全局的 Git 配置是否正确设置。你可以通过多种方式来查看这些信息。 查看全局用户信息 全局用户信息是应用于所有 Git 仓库的默认设置。要查看全局用户信息,可以使用以下命令&am…...
JAVA基础:Collections 工具类实战指南-从排序到线程安全
在 Java 开发中,集合类几乎贯穿每一个项目,而Collections工具类提供了一系列强大的方法,用于操作和增强集合的功能。无论是排序、查找还是线程安全的封装,Collections工具类都是提升代码效率和质量的重要工具。 一、Collections …...
【计算机视觉】TorchVision 深度解析:从核心功能到实战应用 ——PyTorch 官方计算机视觉库的全面指南
TorchVision 深度解析:从核心功能到实战应用 ——PyTorch 官方计算机视觉库的全面指南 1. TorchVision 项目概览核心模块 2. 实战案例:10 大应用场景详解案例 1:使用预训练 ResNet 进行图像分类代码实现常见问题相关论文 案例 2:加…...
case和字符串操作
使用if选择结构 if [];then elif [];then #注意这个地方,java是else if else ; fi 使用for循环结构 使用for循环,语法结构如下所示: for 变量名 in 值1 值2 值3 #值的数量决定循环任务的次数 do命令序列 done#循环输出1到10 for i in {1..10} #注…...
Golang|外观模式和具体逻辑
最终返回的是Document的切片,然后取得Bytes自己再去做反序列化拿到文档的各种详细信息。 外观模式是一种结构型设计模式,它的目的是为复杂的子系统提供一个统一的高层接口,让外部调用者(客户端)可以更简单地使用子系统…...
关于kafka
1.为什么需要消息队列 举个经典的例子。 你是一个网购达人,经常在网上购物。快递小哥到了你的小区后,立刻给你打电话说:“你的快递到了,请马上来取。” 但你是一个合格的牛马,在上班,不方便取快递&#…...
OpenCV 图形API(67)图像与通道拼接函数-----水平拼接(横向连接)两个输入矩阵(GMat 类型)函数concatHor()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 该函数用于水平拼接两个 GMat 矩阵,要求输入矩阵的行数必须一致: GMat A { 1, 4,2, 5,3, 6 }; GMat B { 7, 10,8, 11,9, 12 }; GM…...
夜莺 v8.0.0-beta.10 部署
夜莺 v8.0.0-beta.10 部署 1. mariadb-server2. Redis安装3. 下载 n9e-v8.0.0-beta.10-linux-amd64.tar.gz设置 root 用户密码配置文件 配置mariadb的登录密码导入数据库表结构配置为 systemd 启动服务重新加载 systemd配置日志 访问夜莺VictoriaMetrics 时序数据库安装接入数据…...
HTML5好看的水果蔬菜在线商城网站源码系列模板7
文章目录 1.设计来源1.1 主界面1.2 关于我们界面1.3 商城界面1.4 商品信息界面1.5 我的账户界面1.6 联系我们界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板,程序开发,在线开发,在线沟通 作者:xcLeigh 文章地址&#…...
优化问题中变量分类与作用分析
优化问题中的变量分类与作用 在优化问题中,变量的定义和作用因问题类型和建模需求而异。以下从决策变量、控制变量的区别与联系出发,结合其他相关变量进行系统分析: 1. 决策变量(Decision Variables) 定义:…...
RSS‘25|CMU提出统一空中操作框架:以末端执行器为中心,无人机实现高精度遥操作
导读在科技飞速发展的当下,机器人技术不断拓展其应用边界,空中操作领域成为了研究的热点之一。无人空中操纵器(UAMs)凭借其在高空复杂任务中的巨大潜力,正逐渐改变着诸如高空设备维护、桥梁检测等传统行业的作业模式&a…...
智能指针之设计模式6
本系列文章探讨了智能指针和设计模式的关系,前面五篇文章介绍的是使用设计模式实现了智能指针的相关特性,比如使用工厂模式控制了智能指针对象的创建,使用代理模式控制了资源对象的销毁。本文介绍一下使用智能指针来帮助我们实现相关的设计模…...
【设计模式】GOF概括
一、创建型模式(5种) 1. 单例模式 (Singleton) 适用场景:全局唯一实例(如配置管理、日志工具)。C示例:// 所谓的scott mayer单例模式 class Singleton { public:static Singleton& getInstance() {st…...
深入浅出限流算法(三):追求极致精确的滑动日志
在限流的世界里,精度往往是关键。我们已经讨论过固定窗口(简单但有突刺)和滑动窗口(更平滑但仍有格子边界)。如果我们需要更精确的控制,滑动日志 (Sliding Log) 算法便登场了。 核心思想:记录每…...
一文读懂Tomcat应用之 CentOS安装部署Tomcat服务
目录 一、Tomcat概述 (一)、Tomcat安装目录简介 (二)、Tomcat配置文件简介 1、server.xml文件 2、web.xml 3、context.xml 4、tomcat-users.xml 5、logging.properties 二、Tomcat安装部署 (一)、环境规划 (二)、安装JDK 1、下载JDK二进制安装包 2、解压JDK二进制…...
JVM 内存分配策略
引言 在 Java 虚拟机(JVM)中,内存分配与垃圾回收是影响程序性能的核心机制。内存分配的高效性直接决定了对象创建的速率,而垃圾回收策略则决定了内存的利用率以及系统的稳定性。为了在复杂多变的应用场景中实现高效的内存管理&am…...
轻松上手:使用 Docker Compose 部署 TiDB 的简易指南
作者:ShunWah 在运维管理领域,我拥有多年深厚的专业积累,兼具坚实的理论基础与广泛的实践经验。精通运维自动化流程,对于OceanBase、MySQL等多种数据库的部署与运维,具备从初始部署到后期维护的全链条管理能力。拥有Oc…...
Linux权限管理
权限的概念 在 Linux 系统里,权限管理是系统安全的关键环节。权限管理的核心目的是明确不同用户对文件和目录的操作许可范围,以此来保障系统资源的安全与合理使用。权限管理涉及三种不同的用户角色和三种基本的操作权限。 用户角色 所有者(…...
Crusader Kings III 王国风云 3(十字军之王 3) [DLC 解锁] [Steam] [Windows SteamOS macOS]
Crusader Kings III 王国风云 3(十字军之王 3) [DLC 解锁] [Steam] [Windows & SteamOS & macOS] DLC 版本 至最新全部 DLC 后续可能无法及时更新文章,具体最新版本见下载文件说明; DLC 解锁列表(仅供参考&am…...
架构风格对比
架构风格深度对比:从管道-过滤器到微内核 📜 引言 在软件架构设计中,不同的架构风格适用于不同的业务场景。本文将深入解析 7种主流架构风格,包括它们的核心思想、优缺点、适用场景,并通过对比表格和示例帮助您选择最…...
V Rising 夜族崛起 [DLC 解锁] [Steam] [Windows SteamOS]
V Rising 夜族崛起 [DLC 解锁] [Steam] [Windows & SteamOS] 注意 这个符号表示 可打开折叠内容 需要有游戏正版基础本体,安装路径不能带有中文,或其它非常规拉丁字符;仅限用于自建服务器,并禁用 VAC !࿰…...
HTML标记语言_@拉钩教育
目录 1.文本标签 2.格式化标签 3.图片标签 4.超链接标签 5.表格标签 6表单标签 6.1 6.2 6.3 7.行内框架(超链接内套一个页面) 8.多媒体标签(音/视频) 1.文本标签 2.格式化标签 3.图片标签 4.超链接标签 5.表格标签 6表单标签 6.1 6.2 6.3 7.行内框架(超链接内套一个…...
云原生开发革命:iVX 如何实现 “资源即插即用” 的弹性架构?
云原生技术正以惊人的速度重塑软件开发的版图。短短几年间,它从少数技术先驱的实验性方案,迅速崛起为全球企业数字化转型的核心驱动力。Gartner 预测,到 2026 年,全球 85% 的企业将全面采用云原生技术进行应用开发与部署。云原生架…...
whois为什么有时会返回两个不同的域名状态
前阵子发现一直想注册但被别人注册了的一个域名快要过期了,就想着写个脚本跑在电脑上,每分钟检查一次域名状态,一旦域名被正式删除,就发封邮件通知我,这样就不用频繁手动检查域名状态了。 写脚本时发现一个有趣的现象…...
跨境电商店铺矩阵布局:多账号运营理论到实操全解析
在当今竞争激烈的全球电商市场中,跨境电商店铺矩阵布局已成为卖家脱颖而出的关键策略。本文将深入剖析跨境电商店铺矩阵布局的本质、优势,并提供从理论到实操的全方位指导,助力您在全球市场中开启属于自己的销售新篇章。 一、是什么ÿ…...
安卓基础(强制转换)
一、强制转换(Type Casting) 1. 什么是强制转换? 当你想将一个类型的对象转换为另一个类型时,如果它们之间存在继承关系,就需要强制转换。 注意:只有存在继承关系的类型…...
VS2022+OpenCasCade配置编译
一、Open CASCADE Technology介绍及安装(windows10) Open CASCADE Technology(简称OCCT)是一款开源的 3D CAD/CAM/CAE 软件开发平台,广泛应用于工业设计、工程仿真、制造等领域。开源OCC对象库是一个面向对象C类库&…...
AIGC重构元宇宙:从内容生成到沉浸式体验的技术革命
1. 引言 当数字技术掀开人类交互的新篇章,元宇宙正从科幻构想蜕变为现实——这个由虚拟与现实交织的数字宇宙,承载着未来社会的娱乐、工作与社交形态。作为核心赋能技术,AIGC(人工智能生成内容)正以惊人的创造力&…...
当所有人都用上先进ai,如何保持你的优势?
这不再是你能用上openai模型别人只能用文心一言的时候,而是每个人都可以免费用deepseek r1的时代。如今,办公室里每个人都能随时调用deepseek模型,喊一声“帮我写段代码”便轻松解决问题。在这种情况下,单纯“会用AI”已经很难再形…...
【浙江大学DeepSeek公开课】人类经验与AI算法的镜像之旅
人类经验与AI算法的镜像之旅 人类经验与 AI 算法的镜像之旅一、语言的奥秘:人类如何解码世界二、从符号到智能:AI 的语言理解之路三、DeepSeek - V3:大语言模型的构建与进化四、DeepSeek - R1:推理模型的诞生与突破五、智能体时代…...
【前端】从零开始的搭建顺序指南(技术栈:Node.js + Express + MongoDB + React)book-management
项目路径总结 后端结构 server/ ├── controllers/ # 业务逻辑 │ ├── authController.js │ ├── bookController.js │ ├── genreController.js │ └── userController.js ├── middleware/ # 中间件 │ ├── authMiddleware…...
探针台维护方法
探针台的维护直接影响其测试精度与使用寿命,需结合日常清洁、环境控制、定期校准等多维度操作,具体方法如下: 一、日常清洁与保养 1.表面清洁 使用无尘布或软布擦拭探针台表面,避免残留清洁剂或硬物划伤精密部件。探针头清…...
js day8
事件绑定 事件:发生在html元素上的特定动作,鼠标点击,键盘按下,鼠标移入 事件三要素:事件源(触发事件的元素) 事件类型,事件触发后执行的函数 通过html触发事件(不建议…...
大模型训练平台:重构 AI 研发范式的智慧基建
当 AI 研发陷入“高耗低效”困局,如何破局? 在大模型技术爆发的今天,企业 AI 研发正面临前所未有的挑战:某金融机构为训练风控模型投入大量算力,却因数据标注耗时半年延误项目;某制造企业搭建的训练集群利…...
vuex刷新数据丢失解决方案-vuex-persist
安装 npm install -S vuex-persist(yarn add vuex-persist) 使用: /store/index.js引入vuex-persist配置: import Vue from vue import Vuex from vuex import VuexPersistence from vuex-persist import user from ./modules/use…...
多模态革命!拆解夸克AI相机技术架构:如何用视觉搜索重构信息交互?(附开源方案对比)
一、技术人必看:视觉搜索背后的多模态架构设计 夸克「拍照问夸克」功能绝非简单的OCRQA拼接,而是一套多模态感知-推理-生成全链路系统,其技术栈值得开发者深挖: 视觉编码器:基于Swin Transformer V2,支持4…...
Python依据卫星TLE轨道根数,计算可见时间窗口
1.卫星TLE数据 概括:两行字符串表示的卫星参数 字段 字符串位置(以0为起点) 描述内容注释1 01–01卫星编号203-07卫星类别卫星类别(U表示不保密,可供公众使用的;C 表示保密,仅限NORAD使用&…...
C++?模板!!!
一、引言 在之前我们一起学习了C中类和对象、动态内存管理等相关知识,今天我们将一起学习C中有关模板的相关知识,学完模板之后我们就可以进入C中非常重要的库---STL了,那么模板究竟有什么奥秘呢?让我们一起来看看吧! …...
web技术与nginx网站服务
一、Web服务基础概念 Web服务器核心功能 通过HTTP/HTTPS协议提供网页内容,支持HTML、CSS、JavaScript等静态资源,动态内容需结合后端语言(如PHP、Python)处理36。常用软件:Nginx、Apache、Lighttpd。Nginx以高并发、低…...
关系数据的可视化
目录 【实验目的】 【实验原理】 【实验环境】 【实验步骤】 一、安装Python所需要的第三方模块 二、实验 【实验总结】 【实验目的】 1.掌握关系数据在大数据中的应用 2.掌握关系数据可视化方法 3. python 程序实现图表 【实验原理】 在传统的观念里面࿰…...
MATLAB小试牛刀系列(1)
问题描述 某机床厂生产甲、乙两种机床,每台机床销售后的利润分别为 4 千元与 3 千元。生产甲机床需用 A、B 机器加工,加工时间分别为每台 2h 和每台 1h;生产乙机床需用 A、B、C 三种机器加工,加工时间均为每台 1h。若每天可用于加…...
CUDA、pytorch、配置环境教程合集
1.CUDA卸载 参考: 【环境搭建】卸载&重新安装cudacudnnanacondagpu版pytorch_卸载cuda-CSDN博客 【cuda】cuda安装与卸载升级_升级cuda-CSDN博客 检测代码: https://www.zhihu.com/question/482335084 import torch print(CUDA版本:,torch.vers…...
代码随想录打卡|Day29 动态规划Part02(不同路径、不同路径2、整数拆分、不同的二叉树搜索)
动态规划Part02 不同路径 力扣题目链接 代码随想录链接 视频讲解链接 题目描述: 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角…...
Leetcode刷题 | Day49_图论01
一、学习任务 深度优先搜索理论基础深度优先搜索理论基础 | 代码随想录98. 所有可达路径(ACM)797. 所有可能的路径(Leetcode)广度优先搜索理论基础 二、具体题目 1.深度优先搜索理论基础 类似回溯算法,二叉树的前中后序遍历是其在二叉树领域的应用。 代码框架&am…...
if consteval
if consteval 是 C23 引入的新特性,该特性是关于immediate function 的,即consteval function。用于在编译时检查当前是否处于 立即函数上下文(即常量求值环境),并根据结果选择执行不同的代码路径。它是对 std::is_con…...
【iOS】OC源码阅读——alloc源码分析
文章目录 前言基本调试方法allocalloc函数逐步调试空类检查快速路径:默认内存分配慢速路径:自定义内存分配slowpath和fastpath alloc核心操作cls->instanceSize:计算所需内存大小内存字节对齐原则为什么要16字节对齐内存字节对齐总结 其他…...
[JavaScript]对象关联风格与行为委托模式
对象关联. “[[prototype)]的机制就是存在于对象中的一个内部链接,它会引用其它对象” 为何创建原型链(关联)? Object.create()会创建一个新对象,参数对象会作为新对象的__proto__. “我们并不需要类来创建两个对象之间的关系,只需要通过委托来关联对象就足够了.而Object.c…...
在 Ubuntu 24.04 LTS 一台机子上同时部署Dify 1.3.1 和 RAGflow 0.18.0
一、RAGflow 0.18.0 简介 有关 Dify 的简介,可以查看我之前分享的 《在 Ubuntu24.04 LTS 上 Docker Compose 部署 Dify 社区版 1.0.1》文章。RAGFlow是一款基于深度文档理解(deepdoc)构建的开源 RAG引擎。其中,深度文档理解&#…...
小熊派BearPi-Pico H3863(二)环境配置 Ubuntu编译源码与VSCode远程开发指南
BearPi-H3863 Ubuntu编译源码与VSCode远程开发指南 摘要开发环境配置方案选型环境部署实战手册一、基础环境配置1. 镜像准备2. 虚拟机初始化3. 网络异常处理 二、VSCode远程开发配置1. SSH服务验证2. VSCode插件安装3. 远程连接实战4. 项目管理 关键要点总结 摘要 本文针对Bea…...