【.NET 8 实战--孢子记账--从单体到微服务】--角色(增加/删除/修改/查询)
本节我们将开始编写角色相关的接口
一、需求
本节的要做的需求如下:
| 编号 | 需求标题 | 需求内容 |
|---|---|---|
| 1 | 增加角色 | 角色名称不能重复 |
| 2 | 删除角色 | 角色逻辑删除 |
| 3 | 修改角色 | 修改的名称不能和已有名称重复 |
| 4 | 查询角色 | 不分页查询,根据角色名模糊匹配 |
二、Role类和Role表
这一小节和创建User类和User表类似,这里就不多讲了,我把类代码和要在数据库连接上下文 SporeAccountingDBContext 类中加入的代码列出来,同学们根据前面学习的内容自行操作这一小节。
新建SysRole 类:
using SporeAccounting.BaseModels;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;namespace SporeAccounting.Models;/// <summary>
/// 角色
/// </summary>
[Table(name: "SysRole")]
public class SysRole : BaseModel
{/// <summary>/// 角色名称/// </summary>[Column(TypeName = "nvarchar(20)")][Required]public string RoleName { get; set; }/// <summary>/// 导航属性/// </summary>public SysUser User { get; set; }
}
修改SysUser类:
using SporeAccounting.BaseModels;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;namespace SporeAccounting.Models;/// <summary>
/// 用户表自定义属性类
/// </summary>
[Table(name:"SysUser")]
public class SysUser:BaseModel
{//++++++++++++++++//// Other Code////++++++++++++++++/// <summary>/// 导航属性/// </summary>public ICollection<SysRole> Roles { get; set; }
}
在上面代码中我们增加了两个导航属性,这两个导航属性标明了SysRole 类和SysUser它们之间的关系是一对多的关系(一个用户创建多个角色)。
TIP:导航属性的作用和用法,请同学们访问专栏《轻松学EntityFramework Core》 中的文章《关系映射》
修改数据库连接上下文SporeAccountingDBContext类:
using Microsoft.EntityFrameworkCore;
using SporeAccounting.BaseModels;
using SporeAccounting.Models;
using System.Reflection.Metadata;
using System.Security.Cryptography;
using System.Text;namespace SporeAccounting;/// <summary>
/// 数据库连接上下文
/// </summary>
public class SporeAccountingDBContext : DbContext
{/// <summary>/// 用户表/// </summary>public DbSet<SysUser> SysUsers { get; set; }/// <summary>/// 角色表/// </summary>public DbSet<SysRole> SysRoles { get; set; }IConfiguration _dbConfig;public SporeAccountingDBContext(IConfiguration dbConfig){_dbConfig = dbConfig;}protected override void OnModelCreating(ModelBuilder modelBuilder){//++++++++++++++++//// Other Code////++++++++++++++++modelBuilder.Entity<SysRole>().HasData(new List<SysRole>(){new SysRole(){RoleName = "Administrator",CreateUserId = adminUserId},new SysRole(){RoleName = "Consumer",CreateUserId =adminUserId}});base.OnModelCreating(modelBuilder);}//++++++++++++++++//// Other Code////++++++++++++++++private static string HashPasswordWithSalt(string password, string salt){using (var sha256 = SHA256.Create()){string saltedPassword = password + salt;byte[] saltedPasswordBytes = Encoding.UTF8.GetBytes(saltedPassword);byte[] hashBytes = sha256.ComputeHash(saltedPasswordBytes);return Convert.ToBase64String(hashBytes);}}
}
|2|删除角色|角色逻辑删除|
|3|修改角色|修改的名称不能和已有名称重复|
|4|查询角色|不分页查询,根据角色名模糊匹配|
三、增加角色
这一小节我们一起来看一下如何实现角色的新增功能。
首先,我们来看一下需求:角色名称不能重复。从中我们可以推断出代码中需要有一个根据角色名判断角色名是否重复的方法。下面我们就来一起看一下代码。
3.1 ViewModel 定义
第一步,我们来创建视图模型SysRoleViewModel,它接收来自客户端的数据,代码如下:
namespace SporeAccounting.Models.ViewModels;/// <summary>
/// 角色视图模型
/// </summary>
public class SysRoleViewModel
{/// <summary>/// 角色名称/// </summary>public string RoleName { get; set; }
}
类比较简单,因此我们不再讲解。
3.2 服务开发
我们创建 ISysRoleServer接口和SysRoleImp实现类,并增加IsExistByRoleName和Add方法。
//ISysRoleServer 接口
using SporeAccounting.Models;namespace SporeAccounting.Server.Interface;
/// <summary>
/// 角色数据库操作接口
/// </summary>
public interface ISysRoleServer
{/// <summary>/// 新增角色/// </summary>/// <param name="role"></param>void Add(SysRole role);/// <summary>/// 角色是否存在/// </summary>/// <param name="roleName"></param>/// <returns></returns>bool IsExistByRoleName(string roleName);
}//SysRoleImp 实现类
using SporeAccounting.Models;
using SporeAccounting.Server.Interface;
using System.Data;namespace SporeAccounting.Server;public class SysRoleImp : ISysRoleServer
{private SporeAccountingDBContext _dbContext;public SysRoleImp(SporeAccountingDBContext dbContext){_dbContext = dbContext;}/// <summary>/// 新增角色/// </summary>/// <param name="role"></param>public void Add(SysRole role){try{_dbContext.SysRoles.Add(role);_dbContext.SaveChanges();}catch (Exception ex){throw ex;}}/// <summary>/// 角色是否存在/// </summary>/// <param name="roleName"></param>/// <returns></returns>public bool IsExistByRoleName(string roleName){try{return _dbContext.SysRoles.Any(p => p.RoleName == roleName && !p.IsDeleted);}catch (Exception ex){throw ex;}}
}
在上面的代码中,定义了一个角色管理接口 ISysRoleServer 及其实现类 SysRoleImp,用于在数据库中操作角色信息。ISysRoleServer 接口定义了两个方法:添加角色方法Add 检查是否存在指定名称的角色的方法IsExistByRoleName。而SysRoleImp 类则实现了 ISysRoleServer 接口。
3.3 Controller 开发
Controller 代码的编写和前面几篇文章讲解的类似,在这里就不多讲解了,代码如下:
using System.Data;
using System.Net;
using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using SporeAccounting.BaseModels;
using SporeAccounting.Models;
using SporeAccounting.Models.ViewModels;
using SporeAccounting.Server.Interface;namespace SporeAccounting.Controllers
{/// <summary>/// 角色接口/// </summary>[Route("api/[controller]/")][ApiController]public class SysRoleController : ControllerBase{private readonly ISysRoleServer _sysRoleServer;private readonly IMapper _mapper;public SysRoleController(ISysRoleServer sysRoleServer, IMapper mapper){_sysRoleServer = sysRoleServer;_mapper = mapper;}/// <summary>/// 新增角色/// </summary>/// <param name="role"></param>/// <returns></returns>[HttpPost][Route("Add")]public ActionResult<ResponseData<bool>> Add([FromBody] SysRoleViewModel role){try{bool isExist = _sysRoleServer.IsExistByRoleName(role.RoleName);if (isExist){return Ok(new ResponseData<bool>(HttpStatusCode.Conflict, $"角色{role.RoleName}已存在!", false));}SysRole dbRole = _mapper.Map<SysRole>(role);//TODO:这里暂时写死,等权限和授权完成后再改为动态获取dbRole.CreateUserId = "08f35c1e-117f-431d-979d-9e51e29b0b7d";_sysRoleServer.Add(dbRole);return Ok(new ResponseData<bool>(HttpStatusCode.OK, data: true));}catch (Exception e){return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常", false));}}}
}
这段代码中实现了新增角色接口 Add, 它是一个只接受POST请求的方法,路由地址为 api/SysRole/Add,参数是来自Body 的SysRoleViewModel类型的参数。Add接口首先使用我们在上一小节中定义并实现的 IsExistByRoleName 方法来检查数据库中是否已存在同名角色,如果角色存在,返回 409 状态码并提示角色名称已存在,否则利用 AutoMapper 将SysRoleViewModel 映射为数据库实体 SysRole。这里我们通过硬编码设置了 CreateUserId(未来会替换为动态获取用户信息),最后我们调用 Add 方法将角色添加到数据库中,并返回 200 状态码。
3.4 Profile
在 SporeAccountingProfile 中加入如下代码
CreateMap<SysRoleViewModel, SysRole>().ForMember(d => d.RoleName, opt =>opt.MapFrom(s => s.RoleName));
四、删除角色
删除角色在某些情况下是必要的,下面我们就来实现这个功能。
4.1 服务开发
我们首先在ISysRoleServer接口和SysRoleImp类中增加Delete方法和IsExistById。
//ISysRoleServer 接口
/// <summary>
/// 删除角色(逻辑)
/// </summary>
/// <param name="roleId"></param>
/// <param name="userId"></param>
void Delete(string roleId, string userId);
/// <summary>
/// 角色是否存在
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
bool IsExistById(string roleId);//SysRoleImp 类
/// <summary>
/// 删除角色(逻辑)
/// </summary>
/// <param name="roleId"></param>
/// <param name="userId"></param>
public void Delete(string roleId, string userId)
{try{SysRole role = _dbContext.SysRoles.FirstOrDefault(p => p.Id == roleId)!;role.IsDeleted = true;role.DeleteDateTime = DateTime.Now;role.DeleteUserId = userId;_dbContext.SysRoles.Update(role);_dbContext.SaveChanges();}catch (Exception ex){throw ex;}
}
/// <summary>
/// 角色是否存在
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public bool IsExistById(string roleId)
{try{return _dbContext.SysRoles.Any(p => p.Id == roleId && !p.IsDeleted);}catch (Exception ex){throw ex;}
}
代码和User的删除代码类似这里我们就不讲解了,需要注意的是这里我们的删除操作是逻辑删除,而不是物理删除。在实现IsExistById方法时一定要注意加上!p.IsDeleted这个过滤条件
Tip:从这篇文章开始,我们项目中简单的代码以及和已有代码类似的代码将不再详细讲解,只列出代码。我们只针对详复杂的业务代码以及架构代码进行讲解。
4.2 Controller 开发
我们在 SysRoleController 中添加Remove方法并实现删除功能,代码如下:
/// <summary>
/// 删除角色(逻辑删除)
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
[HttpDelete]
[Route("Remove/{roleId}")]
public ActionResult<ResponseData<bool>> Remove([FromQuery] string roleId)
{try{bool isExist = _sysRoleServer.IsExistById(roleId);if (!isExist){return Ok(new ResponseData<bool>(HttpStatusCode.Conflict, $"角色不存在!", false));}//TODO:这里暂时写死,等权限和授权完成后再改为动态获取_sysRoleServer.Delete(roleId, "08f35c1e-117f-431d-979d-9e51e29b0b7d");return Ok(new ResponseData<bool>(HttpStatusCode.OK, data: true));}catch (Exception e){return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常", false));}
}
代码中需要注意的是,在删除前我们需要查询一次角色是否存在
Tip:这一小节我们暂时不去考虑删除角色后,绑定了该角色的用户该如何处理。这个问题我们将会在下一篇文章《补充单元测试》中处理。
五、修改角色
修改角色我们修改的时角色的名称,这一小节我们来看一下实现。
5.1 ViewModel
新建SysRoleEditViewModel视图类,类中的内容如下:
using System.ComponentModel.DataAnnotations;namespace SporeAccounting.Models.ViewModels;
/// <summary>
/// 修改角色视图类
/// </summary>
public class SysRoleEditViewModel
{/// <summary>/// 角色id/// </summary>[Required(ErrorMessage = "角色Id不能为空")]public string RoleId { get; set; }/// <summary>/// 角色名称/// </summary>[Required(ErrorMessage = "角色名称不能为空")]public string RoleName { get; set; }
}
5.2 服务开发
和前面类似,我们在ISysRoleServer接口和SysRoleImp类中增加Update方法和IsRepeat方法,其中IsRepeat方法用来验证新的角色名称是否重复。实现如下:
//ISysRoleServer 接口
/// <summary>
/// 修改角色
/// </summary>
/// <param name="role"></param>
void Update(SysRole role);
/// <summary>
/// 角色是否重复
/// </summary>
/// <param name="roleId"></param>
/// <param name="roleName"></param>
/// <returns></returns>
bool IsRepeat(string roleId, string roleName);//SysRoleImp 方法
/// <summary>
/// 修改角色
/// </summary>
/// <param name="role"></param>
public void Update(SysRole role)
{try{SysRole dbRole = _dbContext.SysRoles.FirstOrDefault(p => p.Id == role.Id)!;dbRole.RoleName = role.RoleName;dbRole.UpdateDateTime = DateTime.Now;_dbContext.SysRoles.Update(role);_dbContext.SaveChanges();}catch (Exception ex){throw ex;}
}
/// <summary>
/// 角色是否重复
/// </summary>
/// <param name="roleId"></param>
/// <param name="roleName"></param>
/// <returns></returns>
public bool IsRepeat(string roleId, string roleName)
{try{return _dbContext.SysRoles.Any(p => p.Id != roleId && p.RoleName == roleName && !p.IsDeleted);}catch (Exception ex){throw ex;}
}
这里需要注意,IsRepeat方法传入角色Id的目的是在判断角色名是否重复时屏蔽当前要修改的角色,这是因为如果不屏蔽当前角色的话,在不修改角色直接保存的情况下会出现提示角色重复的情况。
5.3 Controller 开发
在 SysRoleController 中添加Edit方法,代码如下:
/// <summary>
/// 修改角色
/// </summary>
/// <param name="roleView"></param>
/// <returns></returns>
[HttpPut]
[Route("Edit")]
public ActionResult<ResponseData<bool>> Edit([FromBody] SysRoleEditViewModel roleView)
{try{//判断角色是否存在bool isExist = _sysRoleServer.IsExistById(roleView.RoleId);if (!isExist){return Ok(new ResponseData<bool>(HttpStatusCode.Conflict, $"角色不存在!", false));}//判断角色名字是否重复isExist = _sysRoleServer.IsRepeat(roleView.RoleId, roleView.RoleName);if (isExist){return Ok(new ResponseData<bool>(HttpStatusCode.Conflict, $"角色{roleView.RoleName}已存在!", false));}SysRole role = _mapper.Map<SysRole>(roleView);//TODO:这里暂时写死,等权限和授权完成后再改为动态获取role.UpdateUserId = "08f35c1e-117f-431d-979d-9e51e29b0b7d";_sysRoleServer.Update(role);return Ok(new ResponseData<bool>(HttpStatusCode.OK, data: true));}catch (Exception e){return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常", false));}
}
5.4 Profile
在 SporeAccountingProfile 中加入如下代码
CreateMap<SysRoleEditViewModel, SysRole>().ForMember(d => d.RoleName, opt =>opt.MapFrom(s => s.RoleName));
六、查询角色
查询角色是最后一个功能,一起来看一下实现代码。
6.1 ViewModel
新建SysRoleQueryViewModel类,并写入如下代码:
namespace SporeAccounting.Models.ViewModels;public class SysRoleQueryViewModel
{/// <summary>/// 角色id/// </summary>public string RoleId { get; set; }/// <summary>/// 角色名/// </summary>public string RoleName { get; set; }
}
6.2 服务开发
在ISysRoleServer接口和SysRoleImp类中增加Query方法
//ISysRoleServer 接口
/// <summary>
/// 查询角色
/// </summary>
/// <param name="roleName"></param>
List<SysRole> Query(string roleName);//SysRoleImp 方法
/// <summary>
/// 查询角色
/// </summary>
/// <param name="roleName"></param>
public List<SysRole> Query(string roleName)
{try{List<SysRole> sysRoles = _dbContext.SysRoles.Where(p => p.RoleName.Contains(roleName)).ToList();return sysRoles;}catch (Exception ex){throw ex;}
}
在Query 方法中我们并没有使用 == 来查询角色,而是使用 Contains 方法。这是因为客户端传递过来的角色名称有很大的可能性不是完整的角色名。
6.3 Controller 开发
最后在SysRoleController 中实现Query 方法
/// <summary>
/// 根据角色名查询
/// </summary>
/// <param name="roleName"></param>
/// <returns></returns>
[HttpGet]
[Route("Query/{roleName}")]
public ActionResult<ResponseData<List<SysRoleQueryViewModel>>> Query([FromQuery] string roleName)
{try{List<SysRole> roles = _sysRoleServer.Query(roleName);List<SysRoleQueryViewModel> rolesQuery = _mapper.Map<List<SysRoleQueryViewModel>>(roles);return Ok(new ResponseData<List<SysRoleQueryViewModel>>(HttpStatusCode.OK, data: rolesQuery));}catch (Exception e){return Ok(new ResponseData<bool>(HttpStatusCode.InternalServerError, "服务器异常", false));}
}
6.4 Profile
在 SporeAccountingProfile 中加入如下代码
CreateMap<SysRole, SysRoleQueryViewModel>().ForMember(d => d.RoleName, opt =>opt.MapFrom(s => s.RoleName));
七、总结
这篇文章我们一起实现了角色的增删改查功能,并对主要代码进行了讲解。
相关文章:
【.NET 8 实战--孢子记账--从单体到微服务】--角色(增加/删除/修改/查询)
本节我们将开始编写角色相关的接口 一、需求 本节的要做的需求如下: 编号需求标题需求内容1增加角色角色名称不能重复2删除角色角色逻辑删除3修改角色修改的名称不能和已有名称重复4查询角色不分页查询,根据角色名模糊匹配 二、Role类和Role表 这一…...
数据结构-栈与队列笔记
普通的双端队列 用栈实现队列 232. 用栈实现队列 - 力扣(LeetCode) import java.util.ArrayDeque; import java.util.Deque;class MyQueue {// 使用双端队列(Deque)来实现一个队列Deque<Integer> input; // 用于存放新加…...
DevExpress WPF中文教程:如何解决数据更新的常见问题?
DevExpress WPF拥有120个控件和库,将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序,这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…...
SpringBoot基础(四):bean的多种加载方式
SpringBoot基础系列文章 SpringBoot基础(一):快速入门 SpringBoot基础(二):配置文件详解 SpringBoot基础(三):Logback日志 SpringBoot基础(四):bean的多种加载方式 目录 一、xml配置文件二、注解定义bean1、使用AnnotationCon…...
JavaScript网页设计案例:构建动态交互的在线图书管理系统
JavaScript网页设计案例:构建动态交互的在线图书管理系统 在当今的数字化时代,网页设计不仅仅是关于美观和布局,更重要的是用户体验和互动性。JavaScript,作为一种强大的编程语言,在网页开发中扮演着至关重要的角色&a…...
嵌入式数据结构中线性表的具体实现
大家好,今天主要给大家分享一下,如何使用数据结构中的线性表以及具体的实现。 第一:线性表的定义和表示方法 线性表的定义 – 线性表就是零个或多个相同数据元素的有限序列。 • 线性表的表示方法 – 线性表记为: L=(a0,∙∙∙∙∙∙∙∙ai-1aiai+1 ∙∙∙∙∙∙an-1) •…...
Redis高级篇 —— 分布式缓存
Redis高级篇 —— 分布式缓存 文章目录 Redis高级篇 —— 分布式缓存1 Redis持久化1.1 RDB1.2 RDB的fork原理1.3 RDB总结1.4 AOF持久化1.5 RDB和AOF的对比 2 Redis主从2.1 搭建主从架构2.2 数据同步原理2.2.1 全量同步2.2.2 增量同步 3 Redis哨兵3.1 哨兵的作用和原理3.1.1 哨兵…...
彩族相机内存卡恢复多种攻略:告别数据丢失
在数字时代,相机内存卡作为我们存储珍贵照片和视频的重要媒介,其数据安全性显得尤为重要。然而,意外删除、错误格式化、存储卡损坏等情况时有发生,导致数据丢失,给用户带来不小的困扰。本文将详细介绍彩族相机内存卡数…...
【C语言】计算需要的缓冲区大小
使用 snprintf 函数计算缓冲区大小的方法其实是一个常见的技巧,因为 snprintf 会返回所需的缓冲区大小,而不需要实际写入任何数据。当传入 NULL 指针时,`snprintf` 并不会尝试写入数据,而是仅仅返回格式化后的字符串长度。如果再加上终止符(即 \0),我们就可以知道实际需…...
Renesas R7FA8D1BH (Cortex®-M85) 上超声波测距模块(HC-SR04)驱动开发
目录 概述 1 软硬件 1.1 软硬件环境信息 1.2 开发板信息 1.3 调试器信息 2 硬件架构 2.1 硬件框架结构 2.2 测距模块(HC-SR04)介绍 2.2.1 HC-SR04特性 2.2.2 HC-SR04操作时序 2.2.3 计算距离 3 软件实现 3.1 FSP配置项目 3.1.1 配置IO口的外…...
短视频矩阵系统独立源码/源头开发
短视频矩阵系统独立源码/源头开发 #抖音矩阵系统源码开发 #短视频矩阵系统源码开发 #短视频seo源码开发 一、 抖音短视频seo矩阵系统源码开发,需要掌握以下技术: 网络编程:能够使用Python、Java或其他编程语言进行网络编程,比如…...
k8s部署jenkins集群,配置集群kubernetes plugin的pod模板
一、配置集群 填写k8s地址:https://kubernetes.default.svc.cluster.local 命名空间:kubernetes-plugin Jenkins地址:http://jenkins:18080 Jenkins通道:jenkins:50000 jenkins是容器别名 设置jenkinsslave的标签属性 二、…...
微软确认Word离奇Bug 命名不当会导致文件被删
微软近日确认Word应用中存在一个Bug,该漏洞可能导致用户在特定情况下错误地删除文件。该问题主要出现在文件命名过程中,如果用户在保存Word文件时采用特定的命名方式,文件可能会被移动到回收站。 根据微软支持中心的消息,如果用户…...
Vue包的安装使用
文章目录 vue介绍一、灵活易用1.渐进式框架2.简洁的语法 二、高效的响应式系统1.数据驱动2.响应式原理 三、强大的组件化开发1.组件化思想2.组件通信 四、丰富的生态系统1.插件和库2.社区支持 安装依赖删除新增文件夹components设置(1)home.vue(2)data.vue(3)zero.vue router配…...
大模型1-本地部署实现交互问答
任务 在本地部署大模型,调用大模型进行对话。 添加库: 1、Transformer Transformers 是由 Hugging Face 开发的一个开源库,广泛应用于自然语言处理(NLP)任务。其主要功能是简化了对大型预训练语言模型的加载和使用…...
鸿蒙架构-系统架构师(七十八)
1信息加密是保证系统机密性的常用手段。使用哈希校验是保证数据完整性的常用方法。可用性保证合法用户对资源的正常访问,不会被不正当的拒绝。()就是破坏系统的可用性。 A 跨站脚本攻击XSS B 拒绝服务攻击DoS C 跨站请求伪造攻击CSRF D 缓…...
大数据存储计算平台EasyMR:多集群统一管理助力企业高效运维
随着全球企业进入数字化转型的快车道,数据已成为企业运营、决策和增长的核心驱动力。为了处理海量数据,同时应对数据处理的复杂性和确保系统的高可用性,企业往往选择部署多个Hadoop集群,这样的策略可以将生产环境、测试环境和灾备…...
代理IP的类型及其在爬虫中的应用
1 动态住宅代理 这些IP地址来自真实的住宅用户,因此具有很高的匿名性和隐私性,不易被别为代理IP。而增加了爬虫任务的安全性。这类代理有以下特点: 高安全性:使用这类代理可发起真实有效的请求,提高爬虫效率的同时&am…...
鸿蒙Swiper动态加载翻页数据(等同于安卓动态加载viewPager)
我这里是加载一个实体类列表 类似 List 的数据,那么首先写一个dataSource: export class MyDataSource implements IDataSource {private list: MyBean[] []constructor(list: MyBean[]) {this.list list}totalCount(): number {return this.list.len…...
嵌入式面试——FreeRTOS篇(八) Tickless低功耗
本篇为:FreeRTOS Tickless 低功耗模式篇 一、低功耗模式简介 1、低功耗介绍 答: 很多应用场合对于功耗的要求很严格,比如可穿戴低功耗产品、物联网低功耗产品等;一般MCU都有相应的低功耗模式,裸机开发时可以使用MCU的…...
多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度
一、引言:多云环境的技术复杂性本质 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时,基础设施的技术债呈现指数级积累。网络连接、身份认证、成本管理这三大核心挑战相互嵌套:跨云网络构建数据…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Spring是如何解决Bean的循环依赖:三级缓存机制
1、什么是 Bean 的循环依赖 在 Spring框架中,Bean 的循环依赖是指多个 Bean 之间互相持有对方引用,形成闭环依赖关系的现象。 多个 Bean 的依赖关系构成环形链路,例如: 双向依赖:Bean A 依赖 Bean B,同时 Bean B 也依赖 Bean A(A↔B)。链条循环: Bean A → Bean…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
MFC 抛体运动模拟:常见问题解决与界面美化
在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...
论文阅读笔记——Muffin: Testing Deep Learning Libraries via Neural Architecture Fuzzing
Muffin 论文 现有方法 CRADLE 和 LEMON,依赖模型推理阶段输出进行差分测试,但在训练阶段是不可行的,因为训练阶段直到最后才有固定输出,中间过程是不断变化的。API 库覆盖低,因为各个 API 都是在各种具体场景下使用。…...
ui框架-文件列表展示
ui框架-文件列表展示 介绍 UI框架的文件列表展示组件,可以展示文件夹,支持列表展示和图标展示模式。组件提供了丰富的功能和可配置选项,适用于文件管理、文件上传等场景。 功能特性 支持列表模式和网格模式的切换展示支持文件和文件夹的层…...
