基于常用设计模式的业务框架
前言
做开发也有好几年时间了,最近总结和梳理自己在工作中遇到的一些问题,工作中最容易写出BUG的需求就是改造需求了。一个成熟的业务系统是需要经过无数次迭代而成的,也意味着经过很多开发人员之手,最后到你这里,大部分时间都是在梳理代码,理解别人的用意。有的业务功能里面一堆IF嵌套嵌套,耦合度太过,理解起来比较费劲,也容易改出BUG。
不同人有不同的编码习惯,这没有办法,但如果系统中能用一些常用的设计模式来编码,那多多少少能增加可读性,降低耦合度,所以想做出几种常用的设计模式工具类,开发时可以直接使用,让我们更加专注于业务代码开发。
正文
框架基于常用的设计模式,策略模式、模板方法模式、工厂模式、责任链模式等,结合Spring IOC,Spring AOP,Springboot自动装配;
Github地址:点击查看
主要有4个通用的设计模式处理器:
通用策略模式处理器
业务场景
购买保险产品的费用计算方法有多种,按日计算、按月计算、按费率表计算。不同产品可选择的计费选项可能不一样,如下:
日计算(01):支持 A产品、B产品
月计算(02):支持 A产品、C产品
费率表计算(03):支持 A产品、B产品、C产品
代码演示
//计算类型String calculateType="01";//产品编号String productNo="A";if(calculateType.equals("01")){if ("A,B".contains(productNo)){//按日计算}}else if(calculateType.equals("02")){if ("A,C".contains(productNo)){//按月计算}}else if(calculateType.equals("03")){if ("A,B,C".contains(productNo)){//按费率表计算}}
上面这种场景如果使用 if…else…处理的话,随着代码不断迭代,其可读性、调整成本会变得越来越大;
下面使用策略模式来演示:
定义处理器,继承策略处理器接口
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;import java.util.Arrays;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/11 20:14* @Wechat:DDOS12345H* 按日计算*/
@BComponent
public class Calculate01Handle extends AbstractBHandle<RequestDto,ResponseDto> {@Overridepublic boolean before(RequestDto requestDto) {return true;}@Overridepublic boolean after(RequestDto requestDto) {return true;}@Overridepublic ResponseDto doExecute(RequestDto requestDto) {System.out.println("按日计算");return null;}@Overridepublic CommonBName getName() {//定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器return new CommonBName<String>("01", Arrays.asList("A","B"));}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;import java.util.Arrays;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/11 20:14* @Wechat:DDOS12345H* 按日计算*/
@BComponent
public class Calculate02Handle extends AbstractBHandle<RequestDto,ResponseDto> {@Overridepublic boolean before(RequestDto requestDto) {return true;}@Overridepublic boolean after(RequestDto requestDto) {return true;}@Overridepublic ResponseDto doExecute(RequestDto requestDto) {System.out.println("按月计算");return null;}@Overridepublic CommonBName getName() {//定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器return new CommonBName<String>("02", Arrays.asList("A","C"));}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.strategy.AbstractBHandle;
import com.zdc.business.business.wrapper.CommonBName;import java.util.Arrays;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/11 20:14* @Wechat:DDOS12345H* 按日计算*/
@BComponent
public class Calculate03Handle extends AbstractBHandle<RequestDto,ResponseDto> {@Overridepublic boolean before(RequestDto requestDto) {return true;}@Overridepublic boolean after(RequestDto requestDto) {return true;}@Overridepublic ResponseDto doExecute(RequestDto requestDto) {System.out.println("按费率表计算");return null;}@Overridepublic CommonBName getName() {//定义该处理器的类型名称,以及支持的别名集;执行时按这两个维度匹配处理器return new CommonBName<String>("03", Arrays.asList("A","B","C"));}
}
定义入参类、出参类;
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {//...
}
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {//...
}
运行用例
import com.zdc.business.business.context.StrategyBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/10 19:21* @Wechat:DDOS12345H*/
public class StartApp {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");StrategyBContext strategyBContext = (StrategyBContext) applicationContext.getBean("strategyBContext");//计算类型String calculateType="01";//产品编号String productNo="A";RequestDto requestDto=new RequestDto();ResponseDto execute = strategyBContext.invoke(calculateType,productNo,requestDto,ResponseDto.class);}
}
通用适配器模式处理器
业务场景
现有公司A和公司B进行投保出单,出完单后需要通知相关人员。
公司A:需要邮件、短信通知投保人;
公司B:需要邮件、短信通知被保人,企信通知业务员;
代码演示
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
@Data
public class RequestDto {//定义请求参数String companyType;}
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {//定义相应参数
}
定义A公司适配器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import com.zdc.business.business.handle.adapter.AbstractHandlesAdapter;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:46* @Wechat:DDOS12345H*/
@BComponent
public class NotifyCompanyA extends AbstractHandlesAdapter<RequestDto, ResponseDto> {@Overridepublic boolean isSupport(RequestDto context) {//该方法用于编写适配条件if (context.getCompanyType().equals("A")){return true;}return false;}@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("发邮件通知投保人");System.out.println("发短信通知投保人");return null;}@Overridepublic IAdapterEnumBFactory getType() {//定义该适配器归属类型return ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY;}
}
定义枚举参数
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 22:30* @Wechat:DDOS12345H*/
@Getter
@AllArgsConstructorpublic enum ChannelIAdapterEnumBFactory implements IAdapterEnumBFactory {CHANNEL_NOTIFY("notify",10,"公司消息通知处理器"),;String type;int priorityOrder;String description;
}
定义B公司通知适配器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IAdapterEnumBFactory;
import com.zdc.business.business.handle.adapter.AbstractHandlesAdapter;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:46* @Wechat:DDOS12345H*/
@BComponent
public class NotifyCompanyB extends AbstractHandlesAdapter<RequestDto, ResponseDto> {@Overridepublic boolean isSupport(RequestDto context) {//该方法用于编写适配条件if (context.getCompanyType().equals("B")){return true;}return false;}@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("发邮件通知投保人");System.out.println("发短信通知投保人");System.out.println("企信通知业务员");return null;}@Overridepublic IAdapterEnumBFactory getType() {//定义该适配器归属类型return ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY;}
}
入口代码
import com.zdc.business.business.context.AdapterBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 21:15* @Wechat:DDOS12345H*/
public class StratApp {public static void main(String[] args) {//SpringBoot环境下可直接使用@AutowireAnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");AdapterBContext adapterBContext = (AdapterBContext) applicationContext.getBean("adapterBContext");//假设当前是A公司投保RequestDto requestDto=new RequestDto();requestDto.setCompanyType("A");ResponseDto execute = adapterBContext.execute(ChannelIAdapterEnumBFactory.CHANNEL_NOTIFY.type, requestDto, ResponseDto.class);}
}
通用责任链模式处理器
业务场景
在录单系统中,录单员填写完资料,通常下一步需要提交审核,而在正式提交审核之前,系统需要校验数据是否符合要求。某些场景下不想完全卡主流程,通常会以软提示的方式在前端进行提醒;现有以下4种软提示校验(从上到下校验顺序):
为了提高体验,当系统抛出资料A校验后,录单员点击“是”进行重新提交,此时由于前面已经点击了“是”了,此时后端不应该再对点击”是“的校验器进行校验。通常这种需要给每个校验器都设置一个标识,当为“是”时,后端跳过校验,但如果校验场景较多时,那代码将难以维护。
现使用责任链模式来处理以上场景
代码演示
定义好请求参数类和相应参数类
import lombok.AllArgsConstructor;
import lombok.Data;/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
@Data
@AllArgsConstructor
public class RequestDto {String data;
/*** @Author:猪大肠* @Package:com.example.btest.adapter* @Date:2023/5/10 20:48* @Wechat:DDOS12345H*/
public class ResponseDto {
}
import com.zdc.business.business.factory.IChainsEnumBFactory;
import lombok.AllArgsConstructor;
import lombok.Getter;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:04* @Wechat:DDOS12345H*/
@Getter
@AllArgsConstructor
public enum OrderCheckEnumBFactory implements IChainsEnumBFactory {ORDER_CHECK_SOFT_A("order","checkA",0,"资料A校验器"),ORDER_CHECK_SOFT_B("order","checkB",1,"资料B校验器"),ORDER_CHECK_SOFT_C("order","checkC",2,"资料C校验器"),;//处理器类型,标记所属链String type;//处理器名称String name;//优先级顺序int priorityOrder;//描述String description;
}
自定义异常类
import lombok.AllArgsConstructor;
import lombok.Data;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:12* @Wechat:DDOS12345H*/
@AllArgsConstructor
@Data
public class SoftTipException extends RuntimeException{private String code;private String desc;}
定义校验器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:02* @Wechat:DDOS12345H*/
@BComponent
public class CheckAHandle extends AbstractChainHandle<RequestDto,ResponseDto> {@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("校验器A");if (context.equals("A")){//抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料A可能存在风险,是否继续提交?");}else{//调用下个节点校验器executeNextNode(context);}return null;}@Overridepublic IChainsEnumBFactory getType() {return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_A;}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:02* @Wechat:DDOS12345H*/
@BComponent
public class CheckBHandle extends AbstractChainHandle<RequestDto,ResponseDto> {@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("校验器B");if (context.equals("B")){//抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料B可能存在风险,是否继续提交?");}else{//调用下个节点校验器executeNextNode(context);}return null;}@Overridepublic IChainsEnumBFactory getType() {return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_B;}
}
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.factory.IChainsEnumBFactory;
import com.zdc.business.business.handle.chains.AbstractChainHandle;/*** @Author:猪大肠* @Package:com.example.btest.chain* @Date:2023/5/11 21:02* @Wechat:DDOS12345H*/
@BComponent
public class CheckCHandle extends AbstractChainHandle<RequestDto,ResponseDto> {@Overridepublic ResponseDto execute(RequestDto context) {System.out.println("校验器C");if (context.equals("C")){//抛出异常,返回下个处理器名称;下次携带这个名称来找到当前节点throw new SoftTipException(getNextNode()==null?"succeed":getNextNode().getHandleName(),"资料C可能存在风险,是否继续提交?");}else{//调用下个节点校验器executeNextNode(context);}return null;}@Overridepublic IChainsEnumBFactory getType() {return OrderCheckEnumBFactory.ORDER_CHECK_SOFT_C;}
}
运行用例
import com.zdc.business.business.context.ChainsBContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author:猪大肠* @Package:com.example.btest.strategy* @Date:2023/5/10 19:21* @Wechat:DDOS12345H*/
public class StartApp {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext=new AnnotationConfigApplicationContext("com.example.btest");ChainsBContext chainsBContext = (ChainsBContext) applicationContext.getBean("chainsBContext");//校验标识String checkFlag="checkB";if (!"succeed".equals(checkFlag)){if ("start".equals(checkFlag)){chainsBContext.start("order",new RequestDto(checkFlag),null);}chainsBContext.execute("order",checkFlag,new RequestDto(checkFlag),null);}}
}
通用代理模式处理器
业务场景
与其它周边系统进行交互时,需要将请求报文和响应报文记录到ES中,方便后续排查,并对请求报文加密加签名,响应报文解密验签;
考虑到复用性等方面,所以这里使用代理模式来增强方法最合适不过了。
代码演示
定义ES日志记录增强器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.proxy.AbstractBEnhanceIntecepter;
import com.zdc.business.business.wrapper.IntecepterProceedWrapper;/*** @Author:猪大肠* @Package:com.example.btest.aop* @Date:2023/5/11 22:58* @Wechat:DDOS12345H*/
@BComponent
public class EnhanceEsHandle extends AbstractBEnhanceIntecepter {@Overridepublic Object execute(IntecepterProceedWrapper ipw) {//方法参数Object[] args = ipw.getArgs();System.out.println("请求参数:"+args[0].toString());//调用真正的执行方法Object result = ipw.proceed();System.out.println("响应参数:"+args[0].toString());return result;}
}
加解密增强器
import com.zdc.business.business.annotation.BComponent;
import com.zdc.business.business.handle.proxy.AbstractBEnhanceIntecepter;
import com.zdc.business.business.wrapper.IntecepterProceedWrapper;/*** @Author:猪大肠* @Package:com.example.btest.aop* @Date:2023/5/11 22:58* @Wechat:DDOS12345H*/
@BComponent
public class EnhanceEncryHandle extends AbstractBEnhanceIntecepter {@Overridepublic Object execute(IntecepterProceedWrapper ipw) {//方法参数Object[] args = ipw.getArgs();System.out.println("对请求报文加密:");System.out.println("对请求报文加签:");//调用真正的执行方法Object result = ipw.proceed();System.out.println("对请求报文解密:");System.out.println("对请求报文验签:");return result;}
}
被增强类
import com.zdc.business.business.annotation.InterceptorEnhance;
import org.springframework.stereotype.Component;/*** @Author:猪大肠* @Package:com.example.btest.aop* @Date:2023/5/11 23:06* @Wechat:DDOS12345H*/
@Component
public class HttpToCompanyA {//按顺利指定增强器@InterceptorEnhance(intecepter = {EnhanceEsHandle.class,EnhanceEncryHandle.class})public String sendInfo(String request){return "{code:\"0\",text:\"成功\"}";}}
运行用例
依赖
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>//打包到本地仓库后,引入使用<dependency><groupId>com.zdc.business</groupId><artifactId>business</artifactId><version>0.0.1</version></dependency></dependencies>
总结
本人3年多开发经验,对于各方面认识有限。欢迎老师们指出改进之处,有好的建议或者有想法大家可以交流探讨,一起完善。
相关文章:

基于常用设计模式的业务框架
前言 做开发也有好几年时间了,最近总结和梳理自己在工作中遇到的一些问题,工作中最容易写出BUG的需求就是改造需求了。一个成熟的业务系统是需要经过无数次迭代而成的,也意味着经过很多开发人员之手,最后到你这里,大部…...

ubuntu重启ssh服务
一、开启ssh服务首先需要安装打开ssh服务的库: sudo apt-get install openssh-server 二、检查当前的ssh开启情况: ps -e |grep ssh 三、如果有sshd,则ssh-server已经启动;若仅有agent,则尚未启动; 开启ssh…...

【19】SCI易中期刊推荐——计算机 | 人工智能领域(中科院2区)
💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉…...

Vue.js条件、循环语句
文章目录 条件语句v-ifv-elsev-else-ifv-show 循环语句v-for 指令v-for 迭代对象valuevalue ,keyvalue ,key,index v-for 迭代整数 条件语句 v-if 在元素 和 template 中使用 v-if 指令 <div id"app"><p v-if"seen">现在你看到我…...

Go语言学习查缺补漏ing Day4
Go语言学习查缺补漏ing Day4 一、掌握iota的使用 请看下面这段代码: package mainimport "fmt"const (a iota_bc "ReganYue"dd1e iotaf iota )func main() {fmt.Println(a, b, c, d, d1, e, f) }思考一下输出结果会是什么? …...

说服审稿人,只需牢记这 8 大返修套路!
本文作者:雁门飞雪 如果说科研是一场修炼,那么学术界就是江湖,投稿就是作者与审稿人或编辑之间的高手博弈。 在这一轮轮的对决中,有时靠的是实力,有时靠的是技巧,然而只有实力和技巧双加持的作者才能长久立…...

Java 责任链模式详解
责任链模式(Chain of Responsibility Pattern)是一种行为型设计模式,它用于将请求的发送者和接收者解耦,使得多个对象都有机会处理这个请求。在责任链模式中,有一个请求处理链条,每个处理请求的对象都是一个…...

使用MASA全家桶从零开始搭建IoT平台(三)管理设备的连接状态
文章目录 前言分析方案1:遗嘱消息演示遗嘱消息的使用实施流程 方案2:使用WebHook开启WebHook演示Webhook编写代码 前言 获取一个设备的在线和离线状态,是一个很关键的功能。我们对设备下发的控制指令,设备处于在线状态才能及时给我们反馈。这里的在线和…...

我的新书上架了!
talk is cheap,show you my book! 新书《从0开始学ARM》终于在各大平台上架了!! 一、关于本书 1. 本书主要内容 ARM体系架构是目前市面上的主流处理器体系架构,在手机芯片和嵌入式芯片领域,ARM体系架构…...

语言与专业的奇迹:如何利用ChatGPT优化跨国贸易
贸易公司,在进行跨国贸易时,往往需要面对不同国家的甲方或者乙方,在与之沟通的过程中,语言和专业是必须要过的一关,顺畅的交流,往往会带来更好的收益。 今天以“茶”为例,给大家介绍一“知否AI…...

云服务器安装宝塔Linux面板命令脚本大全
阿里云服务器安装宝塔Linux面板,操作系统不同安装命令脚本也不同,支持CentOS、Alibaba Cloud Linux、Ubuntu/Deepin等Linux系统,阿里云服务器网分享阿里云服务器安装宝塔Linux面板命令脚本大全: 云服务器安装宝塔Linux面板命令 …...

zed2i相机中imu内参的标定及外参标定
zed2i中imu内参的标定 参考: https://blog.csdn.net/weixin_42681311/article/details/126109617 https://blog.csdn.net/weixin_43135184/article/details/123444090 值得注意,imu内参的标定其实不是那么重要,大致上给一个值应该影响不大…...

Java中的JUnit是什么?如何使用JUnit进行单元测试
JUnit是Java中最流行的单元测试框架之一。它可以帮助开发人员在代码编写过程中检测出错误和异常,从而提高代码的质量和可靠性。 什么是JUnit? JUnit是一个由Kent Beck和Erich Gamma创建的开源Java单元测试框架,它已经成为Java开发中最常用的…...

【seata的部署和集成】
seata的部署和集成 seata的部署和集成一、部署Seata的tc-server1.下载2.解压3.修改配置4.在nacos添加配置5.创建数据库表6.启动TC服务 二、微服务集成seata1.引入依赖2.修改配置文件 三、TC服务的高可用和异地容灾1.模拟异地容灾的TC集群2.将事务组映射配置到nacos3.微服务读取…...

uniapp学习日记之request自定义请求头
uniapp学习日记之request自定义请求头 在学习uniapp的过程中,由于笔者是从Vue项目转来学习uniapp,在使用uni.request时,发现在浏览器调试时,无法在请求头header中添加token字段,愤而弃之,便开始使用axios组…...

【Rust】速度入门---打印个螃蟹先
参考: 菜鸟教程 1 输出到命令行 这不得打印个螃蟹 // 代码来自官方入门教程 // ferris_say需要另外安装 use ferris_says::say; use std::io::{stdout, BufWriter};fn main() {let stdout: std::io::Stdout stdout();let msg: String String::from("Hello fellow Rusta…...

《Linux 内核设计与实现》12. 内存管理
文章目录 页区获得页获得填充为 0 的页释放页 kmalloc()gfp_mask 标志kfree()vmalloc() slab 层slab 层的设计slab 分配器的接口 在栈上的静态分配单页内核栈 高端内存的映射永久映射临时映射 每个 CPU 的分配新的每个 CPU 接口 页 struct page 结构表示系统中的物理页&#x…...

公司新来个卷王,让人崩溃...
最近内卷严重,各种跳槽裁员,相信很多小伙伴也在准备今年的面试计划。 在此展示一套学习笔记 / 面试手册,年后跳槽的朋友可以好好刷一刷,还是挺有必要的,它几乎涵盖了所有的软件测试技术栈,非常珍贵&#x…...

Docker 安全及日志管理
Docker 安全及日志管理 Docker 容器与虚拟机的区别隔离与共享性能与损耗 Docker 存在的安全问题Docker 自身漏洞Docker 源码问题Docker 架构缺陷与安全机制Docker 安全基线标准 容器相关的常用安全配置方法容器最小化Docker 远程 API 访问控制重启 Docker在宿主机的 firewalld …...

大厂面试必备 - MAC 地址 和 IP 地址分别有什么作用?
数据链路层 1、MAC 地址 和 IP 地址分别有什么作用? MAC 地址是数据链路层和物理层使用的地址,是写在网卡上的物理地址。MAC 地址用来定义网络设备的位置。IP 地址是网络层和以上各层使用的地址,是一种逻辑地址。IP 地址用来区别网络上的计…...

【sqlite】联查Join更新
系列文章 C#底层库–MySQLBuilder脚本构建类(select、insert、update、in、带条件的SQL自动生成) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库操作辅助类(推荐阅读࿰…...

asp.net+C#德育课程分数统计管理系统
本中小学德育管理系统主要学校内部提供服务,系统分为管理员,教师和学生3个大模块。 本研究课题重点主要包括了下面几大模块:用户登录,管理员信息管理学生信息管理,教师信息管理,班级成绩管理,学…...

Figma中文网?比Figma更懂你的设计网站!
一个比 Figma 更懂你的设计网站的 Figma 中文网 —— 即时设计是一个非常有用的设计资源平台,它提供了大量的免费设计素材,包括来自各大厂商的 UI 组件库、精美的模板、插画设计和矢量图标素材等等。设计师可以从中学习到大师的设计技巧和规范࿰…...

Nacos-01-Nacos基本介绍
背景 服务发现是⼀个古老的话题,当应用开始脱离单机运行和访问时,服务发现就诞生了。目前的网络架构是每个主机都有⼀个独立的 IP 地址,那么服务发现基本上都是通过某种方式获取到服务所部署的 IP 地址。DNS 协议是最早将⼀个网络名称翻译…...

SpringBoot集成Dubbo启用gRPC协议
文章目录 前言项目结构代码示例父工程api moduleservice module 注意事项区别 本文记录下SpringBoot集成Dubbo启用gRPC协议,以及与原生 gRPC 在代码编写过程中的区别。 下面还有投票,帮忙投个票👍 前言 Dubbo 在 2.7.5 版本开始支持原生 gRP…...

Kali HTTrack演示-渗透测试察打一体(1)
HTTrack是一个免费并易于使用的线下浏览器工具,全称是HTTrack Website Copier for Windows,它能够让你从互联网上下载指定的网站进行线下浏览(离线浏览),也可以用来收集信息(甚至有网站使用隐藏的密码文件),一些仿真度极高的伪网站(为了骗取用户密码),也是使用类似工具做…...

ThreeJS进阶之使用后期处理
什么是后期处理? 很多three.js应用程序是直接将三维物体渲染到屏幕上的。 有时,你或许希望应用一个或多个图形效果,例如景深、发光、胶片微粒或是各种类型的抗锯齿。 后期处理是一种被广泛使用、用于来实现这些效果的方式。 首先,场景被渲染到一个渲染目标上,渲染目标表示…...

KubeEdge节点分组特性简介
01 边缘应用跨地域部署场景及问题 应用生命周期管理复杂导致运维成本提高 02 边缘节点分组管理 节点分组:将不同地区的边缘节点按照节点组的形式组织 边缘应用:将应用资源整体打包并满足不同节点组之间的差异化部署需求 流量闭环:将服务流量…...

论文笔记_2018_IEEE Access_评估地图用于车辆定位能力的因素
目录 基本情况 摘要 I. 引言 II. 相关工作 III. 地图评估标准的定义 A.地图的特...

YOLOv8 人体姿态估计(关键点检测) python推理 ONNX RUNTIME C++部署
目录 1、下载权重 2、python 推理 3、转ONNX格式 4、ONNX RUNTIME C 部署 1、下载权重 我这里之前在做实例分割的时候,项目已经下载到本地,环境也安装好了,只需要下载pose的权重就可以 2、python 推理 yolo taskpose modepredict model…...