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

java后端项目技术记录

后端使用技术记录

  • 一、软件
    • 1. apifox,API管理软件
      • 问题
    • 2. nginx前端服务器
      • (1) 反向代理
      • (2) 负载均衡
  • 二、问题
    • 1. 使用spring全局异常处理器处理特定的异常
    • 2. 扩展springmvc的消息转换器(对象和json数据的转换)
    • 3. 路径参数的接收
    • 4. 实体构建器(lombok包的方法)
    • 5. 使用自定义注解和AOP实现公共字段填充
      • 实现方法
        • ① 自定义注解声明方法类型
        • ② 定义切面类(切入点和对应处理方法)
        • ③ 在方法上添加对应类型的注解即可
    • 6. mybatis执行数据操作后把主键id返回
      • 实现
    • 7. springboot中操作redis数据库
      • (1) 数据库配置
      • (2) java客户端操作redis数据库
        • ① 引入依赖
        • ② 在spring配置文件中添加redis的信息
        • ③ 创建自己的RedisTemplate类注入到容器中
        • ④ 使用时直接取出容器中的RedisTemplate对象获取redis的操作来操作redis
  • 参考

一、软件

1. apifox,API管理软件

apifox是管理API的工具,apifox整合了多个工具
Apifox = Postman + Swagger + Mock + JMeter

地址apifox。
使用比较简单,创建项目,编写API就行,然后测试就行

问题

① 关于API调试时的跨域问题(内网不能访问)
解决方法就是下载一下apifox的浏览器插件就行
② 全局参数的设置(请求头中添加token)
在这里插入图片描述在这里插入图片描述

2. nginx前端服务器

nginx是一款高性能的http服务器/反向代理服务器及电子邮件代理服务器。官方测试nginx能够支撑5万并发链接,并且CPU、内存等资源消耗非常低、运行稳定。

(1) 反向代理

客户端发出的请求不是直接传递给后端,而是先到达nginx服务器,然后进行转发。
这样做的好处是:

  1. 提高访问速度,nginx上可以缓存数据
  2. 进行负载均衡
  3. 保证后端服务安全,服务器不可以直接被外网访问,安全

反向代理需要在nginx服务器的配置文件中进行配置
在这里插入图片描述
相当于会把路径中含有/API/的请求的api和之前的东西换成proxy_pass
在这里插入图片描述

(2) 负载均衡

由于用户众多,一台服务器可能满足不了需求,就需要多台服务器,这时怎么进行请求分配就是一个问题。
nginx可以把请求转发给不同的服务器,其中有多种策略可以进行请求分发的平衡

负载均衡的实现和上面的反向代理差不多
在这里插入图片描述
负载均衡的策略
在这里插入图片描述

二、问题

1. 使用spring全局异常处理器处理特定的异常

在这里插入图片描述

package com.sky.handler;import com.sky.constant.MessageConstant;
import com.sky.exception.BaseException;
import com.sky.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;import java.sql.SQLIntegrityConstraintViolationException;/*** 全局异常处理器,处理项目中抛出的业务异常*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {/*** 捕获业务异常* @param ex* @return*/@ExceptionHandlerpublic Result exceptionHandler(BaseException ex){log.error("异常信息:{}", ex.getMessage());return Result.error(ex.getMessage());}/*** 捕获sql异常* @param ex* @return*/@ExceptionHandlerpublic Result exceptionHandler(SQLIntegrityConstraintViolationException ex){log.error("异常信息:{}", ex.getMessage());String message = ex.getMessage();if (message.contains("Duplicate entry")){String[] split = message.split(" ");String name = split[2];return Result.error(name + MessageConstant.ALREADY_EXISTS);}return Result.error(MessageConstant.UNKNOWN_ERROR);}
}

2. 扩展springmvc的消息转换器(对象和json数据的转换)

消息转换器定义了java对象的序列化和反序列化的规则

这里以处理时间为例子。
对于时间的显示,可以采用在实体类的时间属性上添加注解的方式
在这里插入图片描述
这种方法在存在很多时间属性时就不好用了,需要添加大量的重复注解。
这时就可以给MVC添加一个消息转换器,处理时间的格式


使用方法
消息转换器的定义是在mvc的配置类public class WebMvcConfiguration extends WebMvcConfigurationSupport中重载protected void extendMessageConverters(List<HttpMessageConverter<?>> converters)方法进行添加
添加分为三步

在第二步中存在对象转换器,对象转换器是需要自己实现的,但是代码都相对固定,这里直接给出

package com.sky.json;import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;/*** 对象映射器:基于jackson将Java对象转为json,或者将json转为Java对象* 将JSON解析为Java对象的过程称为 [从JSON反序列化Java对象]* 从Java对象生成JSON的过程称为 [序列化Java对象到JSON]*/
public class JacksonObjectMapper extends ObjectMapper {public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";//public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm";public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";public JacksonObjectMapper() {super();//收到未知属性时不报异常this.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);//反序列化时,属性不存在的兼容处理this.getDeserializationConfig().withoutFeatures(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);SimpleModule simpleModule = new SimpleModule().addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT))).addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))).addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT))).addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));//注册功能模块 例如,可以添加自定义序列化器和反序列化器this.registerModule(simpleModule);}
}

3. 路径参数的接收

更为详细的SpringBoot Controller接收参数的几种常用方式
路径参数的接收主要是通过在方法参数前面添加注解@PathVariable
当参数名和前端传回参数名不一样时通过name属性指定
在这里插入图片描述

4. 实体构建器(lombok包的方法)

使用构建器可以快速完成对象的创建赋值,就不用一次一次的调用对象的set方法


使用
需要在实体类属性上添加注解@Builder
在这里插入图片描述
使用时直接调用builder进行创建就行
在这里插入图片描述

5. 使用自定义注解和AOP实现公共字段填充

在开发过程中可能存在大量跟业务无关的操作,如更新最近操作时间和操作人,这时就可以把无关操作通关AOP的方式添加到代码中,减少代码冗余和重复代码。

场景
在这里插入图片描述
实现思路
在这里插入图片描述

  1. 可以在数据库操作的操作方法上添加一个自定义注解说明操作类型
  2. 通过AOP的方式拦截数据库的插入、更新方法,在操作数据库前对公共字段进行填充(可以通过反射的方式)

实现方法

① 自定义注解声明方法类型

在这里插入图片描述

② 定义切面类(切入点和对应处理方法)

a. 在aspect包下创建类
在这里插入图片描述

b. 定义切点
在这里插入图片描述
c. 定义处理方法

在这里插入图片描述获取方法上注解的值(操作类型)
在这里插入图片描述
获取方法中传入的,需要填充字段的对象
在这里插入图片描述
通过反射对对象进行字段填充
在这里插入图片描述
封装方法名的常量类
在这里插入图片描述

完整代码

package com.sky.aspect;import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.LocalDateTime;@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 切入点*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointcut(){}/*** 使用前置通知*/@Before(value = "autoFillPointcut()")public void autoFill(JoinPoint joinPoint){log.info("填充公共字段");// 获取方法的操作类型MethodSignature signature = (MethodSignature) joinPoint.getSignature();//获取方法签名AutoFill annotation = signature.getMethod().getAnnotation(AutoFill.class);//获取方法上注解OperationType operationType = annotation.value();//获取注解的值// 获取需要填充的对象, 这里约定需要填充的对象是参数的第一个Object[] args = joinPoint.getArgs();if (args == null || args.length == 0){return;}Object o = args[0];//通过反射获取set方法进行字段填充LocalDateTime now = LocalDateTime.now();Long userId = BaseContext.getCurrentId();try {if (operationType == OperationType.INSERT){//获取对应方法。 为了减少固定字符串的,方法名字字符串封装为了常量Method setCreateTime = o.getClass().getDeclaredMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);Method setUpdateTime = o.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setCreateUser = o.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);Method setUpdateUser = o.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);//调用set方法setCreateTime.invoke(o, now);setUpdateTime.invoke(o, now);setUpdateUser.invoke(o, userId);setCreateUser.invoke(o, userId);}else if (operationType == OperationType.UPDATE){Method setUpdateTime = o.getClass().getDeclaredMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);Method setUpdateUser = o.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);setUpdateTime.invoke(o,now);setUpdateUser.invoke(o,userId);}} catch (Exception e) {throw new RuntimeException(e);}}
}
③ 在方法上添加对应类型的注解即可

在这里插入图片描述

6. mybatis执行数据操作后把主键id返回

当表B中的数据需要引用表A中的主键时,表A数据插入,表B也需要插入一条对应的数据,这时需要获取刚刚表A中插入数据的主键,这就需要把插入以后数据的注解放回来(要不然重新执行一次查询比较麻烦)。

实现

服务层代码
在这里插入图片描述

mapper接口方法
在这里插入图片描述
Mapper配置文件中写的动态sql语句

在这里插入图片描述
其中对应的Dish实体类
在这里插入图片描述
不同之处就是在sql动态语句的标签上加了 <insert id="insert" useGeneratedKeys="true" keyProperty="id">
useGeneratedKeys表示需要返回生成的id
keyProperty表示接收属性

7. springboot中操作redis数据库

(1) 数据库配置

开启redis密码
在这里插入图片描述
启动redis服务
在这里插入图片描述
启动客户端的方法

-h 指定主机, -p指定端口。 -a指定密码。 redis没有用户一说,所有指定密码就行
在这里插入图片描述

(2) java客户端操作redis数据库

Redis 的 Java 客户端很多,常用的几种:

  • Jedis
  • Lettuce
  • Spring Data Redis

这里介绍Spring Data Redis


Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。

① 引入依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

Spring Data Redis中提供了一个高度封装的类:RedisTemplate,对相关api进行了归类封装,将同一类型操作封装为operation接口,具体分类如下:

  • ValueOperations:string数据操作
  • SetOperations:set类型数据操作
  • ZSetOperations:zset类型数据操作
  • HashOperations:hash类型的数据操作
  • ListOperations:list类型的数据操作
② 在spring配置文件中添加redis的信息
spring:profiles:active: devredis:host: localhostport: 6379password: 123456database: 10

在配置文件中有database字段是表示哪个数据库,redis默认有16个数据库(0到15)。当然也可以在配置文件中修改数据库的数量

③ 创建自己的RedisTemplate类注入到容器中

当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为JdkSerializationRedisSerializer,导致我们存到Redis中后的数据和原始数据有差别,故设置为6StringRedisSerializer序列化器。

package com.sky.config;import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;@Configuration
@Slf4j
public class RedisConfiguration {@Beanpublic RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory){log.info("开始创建redis模板对象...");RedisTemplate redisTemplate = new RedisTemplate();//设置redis的连接工厂对象redisTemplate.setConnectionFactory(redisConnectionFactory);//设置redis key的序列化器redisTemplate.setKeySerializer(new StringRedisSerializer());return redisTemplate;}
}
④ 使用时直接取出容器中的RedisTemplate对象获取redis的操作来操作redis

在这里插入图片描述

参考

  1. java后端项目课程地址
  2. SpringBoot Controller接收参数的几种常用方式

相关文章:

java后端项目技术记录

后端使用技术记录 一、软件1. apifox&#xff0c;API管理软件问题 2. nginx前端服务器(1) 反向代理(2) 负载均衡 二、问题1. 使用spring全局异常处理器处理特定的异常2. 扩展springmvc的消息转换器&#xff08;对象和json数据的转换&#xff09;3. 路径参数的接收4. 实体构建器…...

PostgreSQL数据库与PostGIS在Windows中的部署与运行

本文介绍在Windows电脑中&#xff0c;下载、安装、部署并运行PostgreSQL与PostGIS数据库服务的方法。 PostgreSQL是一种功能强大的开源关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;以其稳定性、可靠性和丰富的功能而闻名&#xff1b;其支持多种高级特性&…...

高级算法设计与分析 学习笔记10 平摊分析

动态表&#xff0c;可以变长。 一溢出就另起一个两倍大小的表。 可以轻易证明把n个数字放进去的时间复杂度是O(n)&#xff0c;n n/2 n/4……也就2n&#xff0c;插入数字本身也就是n&#xff0c;加起来最多不超过3n. 这种复杂度究竟是怎么算的&#xff1f;毕竟每次插入复杂度…...

从“纸面算力”到“好用算力”,超聚变打通AI+“最后一公里”

如果要评选2024年的年度科技名词&#xff0c;AI当属最热门的候选项。 年初的《政府工作报告》中首次提出了“人工智能”行动&#xff0c;正在从顶层设计着手&#xff0c;加快形成以人工智能为引擎的新质生产力。 折射到市场层面&#xff0c;AI作为一种新的范式&#xff0c;不…...

【有啥问啥】具身智能(Embodied AI):人工智能的新前沿

具身智能&#xff08;Embodied AI&#xff09;&#xff1a;人工智能的新前沿 引言 在人工智能&#xff08;AI&#xff09;的进程中&#xff0c;具身智能&#xff08;Embodied AI&#xff09;正逐渐成为研究与应用的焦点。具身智能不仅关注于机器的计算能力&#xff0c;更强调…...

11-pg内核之锁管理器(六)死锁检测

概念 每个事务都在等待集合中的另一事务&#xff0c;由于这个集合是一个有限集合&#xff0c;因此一旦在这个等待的链条上产生了环&#xff0c;就会产生死锁。自旋锁和轻量锁属于系统锁&#xff0c;他们目前没有死锁检测机制&#xff0c;只能靠内核开发人员在开发过程中谨慎的…...

Git 与标签管理

在 Git 中&#xff0c;标签 tag 是指向某个 commit 的指针&#xff08;所以创建和删除都很快&#xff09;。Git 有 commit id 了&#xff0c;为什么还要有 tag&#xff1f;commit id 是一串无规律的数字&#xff0c;不好记&#xff1b;而 tag 是我们自定义的&#xff0c;例如我…...

【0334】Postgres内核之 auxiliary process(辅助进程)初始化 MyPgXact

1. MyPgXact(ProcGlobal->allPgXact)间接初始化 在上一篇文章【0333】Postgres内核之 auxiliary process(辅助进程)创建 PGPROC 中, 讲解了Postgres内核完成 AuxiliaryProcess 初始化 pid、lxid、procLatch、myProcLocks、lockGroupMembers等所有成员的过程。 这些成员…...

20.1 分析pull模型在k8s中的应用,对比push模型

本节重点介绍 : push模型和pull模型监控系统对比为什么在k8s中只能用pull模型的k8s中主要组件的暴露地址说明 push模型和pull模型监控系统 对比下两种系统采用的不同采集模型&#xff0c;即push型采集和pull型采集。不同的模型在性能的考虑上是截然不同的。下面表格简单的说…...

Ubuntu 镜像替换为阿里云镜像:简化你的下载体验

Ubuntu&#xff0c;作为一款广受欢迎的Linux发行版&#xff0c;以其稳定性和易用性著称。但你是否曾因为下载速度慢而感到沮丧&#xff1f;现在&#xff0c;你可以通过将Ubuntu的默认下载源替换为阿里云镜像来解决这个问题。本文将指导你如何完成这一过程。 为什么选择阿里云镜…...

The Sandbox 游戏制作教程第 6 章|如何使用装备制作出色的游戏 —— 避免环境危险

欢迎回到我们的系列&#xff0c;我们将记录 The Sandbox Game Maker 的 “On-Equip”&#xff08;装备&#xff09;功能的多种用途。 如果你刚加入 The Sandbox&#xff0c;装备功能是 “可收集组件”&#xff08;Collectable Component&#xff09;中的一个多功能工具&#xf…...

JavaScript中的输出方式

1. console.log() console.log() 是开发者在调试代码时最常用的方法。它将信息打印到浏览器的控制台&#xff0c;使开发者能够查看变量的值、程序的执行状态以及其他有用的信息。 用途&#xff1a;用于调试和记录程序运行时的信息。优点&#xff1a;简单易用&#xff0c;适合…...

力扣9.25

2306. 公司命名 给你一个字符串数组 ideas 表示在公司命名过程中使用的名字列表。公司命名流程如下&#xff1a; 从 ideas 中选择 2 个 不同 名字&#xff0c;称为 ideaA 和 ideaB 。 交换 ideaA 和 ideaB 的首字母。 如果得到的两个新名字 都 不在ideas 中&#xff0c;那么 …...

从零开始之AI面试小程序

从零开始之AI面试小程序 文章目录 从零开始之AI面试小程序前言一、工具列表二、开发部署流程1. VMWare安装2. Centos安装3. Centos环境配置3.1. 更改子网IP3.2. 配置静态IP地址 4. Docker和Docker Compose安装5. Docker镜像加速源配置6. 部署中间件6.1. MySQL部署6.2. Redis部署…...

Html2OpenXml:HTML转化为OpenXml的.Net库,轻松实现Html转为Word。

推荐一个开源库&#xff0c;轻松实现HTML转化为OpenXml。 01 项目简介 Html2OpenXml 是一个开源.Net库&#xff0c;旨在将简单或复杂的HTML内容转换为OpenXml组件。 该项目始于2009年&#xff0c;最初是为了将用户评论转换为Word文档而设计的 随着时间的推移&#xff0c;Ht…...

HumanNeRF:Free-viewpoint Rendering of Moving People from Monocular Video 精读

1. 姿态估计和骨架变换模块 人体姿态估计&#xff1a;HumanNeRF 通过已知的单目视频对视频中人物的姿态进行估计。常见的方法是通过人体姿态估计器&#xff08;如 OpenPose 或 SMPL 模型&#xff09;提取人物的骨架信息&#xff0c;获取 3D 关节的位置信息。这些关节信息可以帮…...

Springboot中基于注解实现公共字段自动填充

1.使用场景 当我们有大量的表需要管理公共字段&#xff0c;并且希望提高开发效率和确保数据一致性时&#xff0c;使用这种自动填充方式是很有必要的。它可以达到一下作用 统一管理数据库表中的公共字段&#xff1a;如创建时间、修改时间、创建人ID、修改人ID等&#xff0c;这些…...

Android 已经过时的方法用什么新方法替代?

过时修正举例 (Kotlin): getColor(): resources.getColor(R.color.white) //已过时// 修正后:ContextCompat.getColor(this, R.color.white) getDrawable(): resources.getDrawable(R.mipmap.test) //已过时//修正后:ContextCompat.getDrawable(this, R.mipmap.test) //…...

【RocketMQ】MQ与RocketMQ介绍

&#x1f3af; 导读&#xff1a;本文介绍了消息队列&#xff08;MQ&#xff09;的基本概念及其在分布式系统中的作用&#xff0c;包括实现异步通信、削峰限流和应用解耦等方面的优势&#xff0c;并对ActiveMQ、RabbitMQ、RocketMQ及Kafka四种MQ产品进行了对比分析&#xff0c;涵…...

【笔记】自动驾驶预测与决策规划_Part4_时空联合规划

文章目录 0. 前言1. 时空联合规划的基本概念1.1 时空分离方法1.2 时空联合方法 2.基于搜索的时空联合规划 &#xff08;Hybrid A* &#xff09;2.1 基于Hybrid A* 的时空联合规划建模2.2 构建三维时空联合地图2.3 基于Hybrid A*的时空节点扩展2.4 Hybrid A* &#xff1a;时空节…...

Admin.Net中的消息通信SignalR解释

定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

Typeerror: cannot read properties of undefined (reading ‘XXX‘)

最近需要在离线机器上运行软件&#xff0c;所以得把软件用docker打包起来&#xff0c;大部分功能都没问题&#xff0c;出了一个奇怪的事情。同样的代码&#xff0c;在本机上用vscode可以运行起来&#xff0c;但是打包之后在docker里出现了问题。使用的是dialog组件&#xff0c;…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

Kubernetes 网络模型深度解析:Pod IP 与 Service 的负载均衡机制,Service到底是什么?

Pod IP 的本质与特性 Pod IP 的定位 纯端点地址&#xff1a;Pod IP 是分配给 Pod 网络命名空间的真实 IP 地址&#xff08;如 10.244.1.2&#xff09;无特殊名称&#xff1a;在 Kubernetes 中&#xff0c;它通常被称为 “Pod IP” 或 “容器 IP”生命周期&#xff1a;与 Pod …...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...