Java常见设计模式(中):结构型模式
🌈 引言:设计模式就像乐高积木
- 适配器:让不同形状的积木完美拼接
- 装饰器:给积木添加炫酷灯光效果
- 代理:遥控积木完成复杂动作
- 组合:将小积木搭建成宏伟城堡
结构型模式
主要用于描述对象之间的关系,包括类和对象的组合、接口和继承等方面。这些模式可以帮助我们更好地组织和管理代码,提高代码的可重用性和可维护性。
🧩 七大结构性模式速览
模式名称 | 核心思想 | 生活类比 |
---|---|---|
适配器模式 | 转换接口,让不兼容的类协同工作 | 电源转换器 |
桥接模式 | 分离抽象与实现,独立变化 | 遥控器和电视的分离 |
组合模式 | 树形结构管理部分-整体关系 | 公司组织架构 |
装饰器模式 | 动态添加功能,不修改原有代码 | 给手机加装保护壳 |
外观模式 | 简化复杂子系统接口 | 酒店前台一站式服务 |
享元模式 | 共享细粒度对象,节省资源 | 共享单车 |
代理模式 | 控制对象访问,增强功能 | 明星经纪人 |
适配器模式 Adapter Pattern-让不兼容的接口协同工作
将一个类的接口转化成客户希望的另一个接口,使得原本由于接口不兼容而无法一起工作的类可以一起工作。
适配器模式包括以下几个组成部分:
- 目标接口(Target Interface):客户端期望的接口,类似于目标插座。
- 适配器(Adapter):充当两个不兼容接口之间的桥梁,使得它们可以互相通信,类似于转换插头。
- 适配者(Adaptee):需要被适配的对象,它的接口与目标接口不兼容,类似于英标插头。
- 客户端(Client):使用目标接口的对象。
应用场景
- 当需要将一个已有的类或接口与另一个不兼容的类或接口进行协同工作时。
- 当需要对一个已有的类或接口进行修改,以满足客户端的需求时,但是不希望修改该类或接口的源代码。
- 当需要重新使用一个已有的类或接口,但是不能直接使用该类或接口的方法时。
代码实战:让旧设备支持新接口
// 旧设备(Adaptee)
class OldPrinter {void printDocument(String doc) {System.out.println("Old Printer: " + doc);}
}// 新接口(Target)
interface NewPrinter {void print(String content);
}// 适配器(Adapter)
class PrinterAdapter implements NewPrinter {private OldPrinter oldPrinter;public PrinterAdapter(OldPrinter oldPrinter) {this.oldPrinter = oldPrinter;}@Overridepublic void print(String content) {oldPrinter.printDocument(content);}
}// 客户端
public class Client {public static void main(String[] args) {OldPrinter oldPrinter = new OldPrinter();NewPrinter printer = new PrinterAdapter(oldPrinter);printer.print("Hello, Adapter Pattern!");}
}
输出:
Old Printer: Hello, Adapter Pattern!
使用小结
适配器模式是一种非常有用的设计模式,在JDK中被广泛应用,可以提供一致的接口,比如:
1.Java IO 流是一个常见的适配器模式的例子。它提供了一组标准的接口来访问各种类型的数据源,包括文件、网络连接、内存等等。每个数据源都有自己的接口,但是 Java IO 流可以将这些不同的接口转换为标准的接口,从而提供一致的访问方式。
2.Java Servlet API 也是一个常见的适配器模式的例子。它定义了一组接口来处理 HTTP 请求和响应,包括 doGet()、doPost()、doPut() 等等。每个 Servlet 都必须实现这些接口,但是用户只需要实现其中的一部分即可。这些 Servlet 之间的适配工作由 Servlet 容器完成。
桥接模式
将抽象部分与实现部分分离,以便它们可以独立地变化
**使用场景:**当你希望在不同的维度上变化(如图形的形状和颜色)时。
类比: 就像遥控器和电视之间的桥接。
代码示例:
// 实现接口
interface Color {void applyColor();
}// 抽象类
abstract class Shape {protected Color color;public Shape(Color color) { this.color = color; }abstract void draw();
}// 具体实现
class Red implements Color {public void applyColor() { System.out.print("红色的"); }
}class Circle extends Shape {public Circle(Color c) { super(c); }void draw() {color.applyColor();System.out.println("圆形");}
}
组合模式
将对象组合成树形结构以表示 部分-整体 的层次结构,使得客户端使用单个对象或者组合对象具有一致性。
使用场景:当你希望以统一的方式处理单个对象和组合对象时。
类比: 公司组织架构(部门包含子部门)
interface Component {void show();
}class Leaf implements Component {private String name;public Leaf(String name) { this.name = name; }public void show() { System.out.println("叶子:" + name); }
}class Composite implements Component {private List<Component> children = new ArrayList<>();public void add(Component c) { children.add(c); }public void show() {for(Component c : children) {c.show();}}
}
装饰器模式-动态添加功能
在不修改现有对象的情况下,动态地给一个对象添加一些额外的职责(通过将一个对象包装在另一个对象中来扩展它的行为),就增加功能而言,装饰器模式比生成子类方法更加灵活。
应用场景
1.当需要在不修改现有对象结构的前提下增加新的功能或特性时,可以使用装饰器模式。这样可以保持原有代码的稳定性和兼容性,同时也可以增加代码的灵活性和可扩展性。
2.当需要动态地向对象添加或删除功能时,可以使用装饰器模式。这样可以在运行时动态地添加或删除功能,而不需要修改现有的代码。
3.当需要为多个对象添加相同的功能时,可以使用装饰器模式。这样可以将相同的功能封装在装饰器中,以便于复用和管理。
代码实现
该示例代码中,Shape 是一个接口,定义了一个 draw 方法,表示绘制图形的操作。Circle 是一个实现 Shape 接口的类,表示一个圆形。
ShapeDecorator 是一个装饰器抽象类,实现了 Shape 接口,并包含一个 Shape 类型的变量 decoratedShape,表示要装饰的对象。RedShapeDecorator 是一个具体的装饰器类,继承了 ShapeDecorator 类,并实现了 draw 方法,在绘制图形时添加了一个红色的边框。
在 main 方法中,我们创建了原始对象 Circle,以及两个装饰器对象 RedShapeDecorator,分别装饰了 Circle 和 Rectangle 对象。通过调用 draw 方法,我们可以看到对象被动态地添加了一个红色的边框,而不需要修改原有的代码。
// 定义接口
interface Shape {void draw();
}// 实现接口
class Circle implements Shape {@Overridepublic void draw() {System.out.println("Shape: Circle");}
}class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Shape: Rectangle");}
}// 装饰器抽象类
abstract class ShapeDecorator implements Shape {protected Shape decoratedShape;public ShapeDecorator(Shape decoratedShape){this.decoratedShape = decoratedShape;}public void draw(){decoratedShape.draw();}
}// 具体装饰器类
class RedShapeDecorator extends ShapeDecorator {public RedShapeDecorator(Shape decoratedShape) {super(decoratedShape);}@Overridepublic void draw() {decoratedShape.draw();setRedBorder(decoratedShape);}private void setRedBorder(Shape decoratedShape){System.out.println("Border Color: Red");}
}// 测试代码
public class DecoratorPatternDemo {public static void main(String[] args) {// 创建原始对象Shape circle = new Circle();// 创建装饰器对象Shape redCircle = new RedShapeDecorator(new Circle());Shape redRectangle = new RedShapeDecorator(new Rectangle());// 调用方法System.out.println("Circle with normal border");circle.draw();System.out.println("\nCircle of red border");redCircle.draw();System.out.println("\nRectangle of red border");redRectangle.draw();}
}
使用小结
在实际应用中,装饰器模式经常用于图形界面(GUI)开发、输入/输出流处理、缓存机制、日志记录等领域,可以有效地提高程序的可扩展性和可维护性。比如
1.装饰器模式被广泛应用于Java IO流中,以提供各种不同的功能,如缓存、压缩、加密等等。例如,可以使用 BufferedReader 来缓存读取文件的数据,使用 GZIPOutputStream 来压缩数据,使用 CipherOutputStream 来加密数据等等。
2.Java Swing 组件是一个经典的装饰器模式的例子。它允许在运行时动态地向组件添加功能,如边框、背景、文本等等。例如,可以使用 BorderFactory 来向组件添加边框,使用 Color 来设置组件的背景颜色,使用 Font 来设置组件的字体等等。
3.在 Spring 框架中,装饰器模式被广泛应用于实现 AOP。AOP通过代理模式和装饰器模式实现。JDK 动态代理和 CGLIB 动态代理两种方式实现代理模式,使用装饰器模式对目标对象进行包装,从而实现通知 (Advice) 的织入。例如,可以使用 @Transactional 来添加事务处理的功能,使用 @Cacheable 来添加缓存处理的功能,等等。
外观模式
为子系统中的一组接口提供一个一致的接口,使得子系统更容易使用
- 特点:提供统一入口,简化复杂系统
- 场景:一键操作(如电脑开机)、API网关
- 类比:餐厅服务员(隐藏厨房复杂流程)
class CPU { void start() {} }
class Memory { void load() {} }class ComputerFacade {private CPU cpu = new CPU();private Memory memory = new Memory();public void start() {cpu.start();memory.load();System.out.println("电脑启动完成");}
}
享元模式
运用共享技术来有效地支持大量细粒度对象的复用
- 特点:共享细粒度对象,节省内存
- 场景:文字编辑器字符对象、棋子游戏
- 类比:棋盘共享棋子样式(颜色/形状)
class TreeType {private String name;private String color;// 构造函数...
}class TreeFactory {static Map<String, TreeType> cache = new HashMap<>();static TreeType getTreeType(String name, String color) {String key = name + color;if(!cache.containsKey(key)) {cache.put(key, new TreeType(name, color));}return cache.get(key);}
}
代理模式:控制对象访问
解决的问题
代理模式是Java开发中使用较多的一种设计模式。代理设计就是为其他对象提供一种代理以控制对这个真实对象的访问,起到对代理对象已有功能的增强。
分类
➢静态代理(静态定义代理类,就是在程序运行前就已经存在代理类的字节码文件)
➢动态代理(动态生成代理类,在程序运行期间,由JVM根据反射等机制动态生成,在运行前并不存在代理类的字节码文件)
1. 静态代理:专属经纪人模式
角色分工:
- Subject:抽象主体角色(明星接口):定义核心业务(唱歌、演戏)
- RealSubject:真实主体角色(真实明星):周杰伦(专注艺术创作)
- ProxySubject:代理主体角色(经纪人代理):处理商务对接、安保等杂务
代码实战:明星经纪人系统
// 明星接口
interface Star {void sing(String song);void act(String movie);
}// 真实明星
class JayChou implements Star {public void sing(String song) {System.out.println("周杰伦演唱: " + song);}public void act(String movie) {System.out.println("周杰伦出演: " + movie);}
}// 经纪人代理(静态)
class StarAgent implements Star {private Star target; // 被代理的明星public StarAgent(Star target) {this.target = target;}public void sing(String song) {System.out.println("【经纪人】对接演唱会场地");target.sing(song);System.out.println("【经纪人】处理粉丝互动");}public void act(String movie) {System.out.println("【经纪人】审核剧本");target.act(movie);System.out.println("【经纪人】安排媒体采访");}
}// 客户端调用
public class Client {public static void main(String[] args) {Star jay = new JayChou();Star agent = new StarAgent(jay);agent.sing("七里香"); // 经纪人全权代理}
}
输出
【经纪人】对接演唱会场地
周杰伦演唱: 七里香
【经纪人】处理粉丝互动
静态代理特点
- ⚙️ 手动编写代理类,且个明星需专属经纪人。当需要代理多个明星,需要编写多个代理类
- 🛡️ 代理逻辑硬编码(商务流程固定)
- ➕ 代理类与真实主体类耦合度太高,接口增加方法时,需修改所有代理类
相比与于静态代理,动态代理则不存在上述的诸多问题,下面我们进入 JDK 的动态代理。
2.动态代理:万能代购模式
DK原生动态代理的组成分为三个部分: 抽象主题角色 、 真实主题角色 、 增强主题角色 。
- 抽象主题角色和代理模式的抽象主题角色是一样的,都是抽象出来的接口或类,对于JDK原生动态代理而言,抽象主题角色就是接口。
- 真实主题角色和代理模式的真实主题角色一样,都是被代理类。
- 增强主题角色在JDK原生代理中值的是实现了 InvocationHandler 接口的类,其目的是对真实主题角色的方法的增强。 InvocationHandler 接口中只有一个方法 invoke 方法,所有的动态代理对象中的映射方法在执行时都是调用的 InvocationHandler 接口中的 invoke 方法,在调用 invoke 方法时,动态代理对象会将 被代理对象的方法 和 动态代理对象映射的方法的参数 传递给 InvocationHandler 的 invoke 方法, invoke 方法的实现是由程序员编写的,这样程序员就可以在 被代理对象的方法 执行 前后 进行增强。
🔧 核心功能拆解
组件 | 作用 | 生活比喻 |
---|---|---|
接口(Interface) | 定义核心功能规范 | 明星的工作合同 |
真实对象(Target) | 实现接口的核心业务类 | 明星本人 |
InvocationHandler | 代理逻辑处理器(处理额外操作) | 经纪人的工作手册 |
Proxy.newProxyInstance | 动态生成代理对象 | 经纪公司生成经纪人 |
-- 定义抽象主题接口
public interface Star {void act(); // 拍戏void sing(); // 唱歌
}-- 定义真实主体角色类
public class RealStar implements Star {public void act() {System.out.println("周董在拍戏...");}public void sing() {System.out.println("周董在唱《青花瓷》...");}
}-- 经纪人,动态代理
public class StarProxy implements InvocationHandler {private Object target; // 被代理的明星public Object createProxy(Object target) {this.target = target;// 动态生成代理对象return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("【经纪人】签合同");System.out.println("【经纪人】安排化妆");Object result = method.invoke(target, args); // 调用真实对象的方法System.out.println("【经纪人】收尾款");return result;}
}// 客户端动态生成代理
public class Client {public static void main(String[] args) {Star realStar = new RealStar();Star proxy = (Star) new StarProxy().createProxy(realStar);proxy.act(); // 输出:// 【经纪人】签合同// 【经纪人】安排化妆// 周董在拍戏...// 【经纪人】收尾款proxy.sing();// 输出同上流程}
}
动态代理特点
- 🌀 运行时动态生成代理类(无需提前编写)
- 🎯 可代理任意接口类型
- 🔄 新增接口方法自动适配
📊 静态代理 vs 动态代理 核心对比
模式名称 | 静态代理 | 动态代理 |
---|---|---|
实现方式 | 手动编写代理类 | 运行时动态生成代理类 |
灵活性 | 一个代理类对应一个接口 | 一个处理器可处理多个接口 |
代码冗杂度 | 接口方法变化需修改代理类 | 接口扩展无需修改代理逻辑 |
典型应用 | 简单业务场景 | Spring AOP、RPC框架等 |
性能开销 | 无额外运行时开销 | 反射调用带来微小性能损耗 |
实现复杂度 | 简单直观 | 需理解反射机制和InvocationHandler |
🔧 技术原理拆解
静态代理实现要点
- 代理类与真实类实现相同接口
- 代理类持有真实对象的引用
- 在调用前后添加增强逻辑
动态代理底层机制
sequenceDiagramClient->>Proxy: 调用代理方法Proxy->>InvocationHandler: 转发调用InvocationHandler->>RealObject: 反射调用真实方法RealObject-->>InvocationHandler: 返回结果InvocationHandler-->>Proxy: 返回增强结果Proxy-->>Client: 最终响应
- Proxy类:动态生成代理类的工厂
- InvocationHandler:所有代理方法的统一入口
- 反射机制:实现方法调用的动态转发
🛠 实战场景选择指南
- 选静态代理:当代理逻辑简单、接口稳定时(如日志记录)
- 选动态代理:当需要代理多个不同接口、或代理逻辑需要统一管理时(如事务管理)
比如你要开发一个大文档查看软件,大文档中有大的图片,有可能一个图片有100MB,在打开文件时,不可能将所有的图片都显示出来,这样就可以使用代理模式,当需要查看图片时,用proxy来进行大图片的打开。
掌握代理模式的核心,就像从雇佣专属管家升级为拥有AI智能助手!静态代理是精通的开始,动态代理才是企业级开发的常态。理解这一模式,将为学习Spring AOP、MyBatis插件等框架打下坚实基础! 🚀
💡 高频面试三连
装饰器模式与继承的区别?
- 装饰器:运行时动态扩展,更灵活
- 继承:编译时静态扩展,耦合度高
代理模式的应用场景?
- 远程代理(RMI)
- 虚拟代理(延迟加载)
- 保护代理(权限控制)
适配器模式的两种实现方式?
- 类适配器:通过继承实现
- 对象适配器:通过组合实现
相关文章:
Java常见设计模式(中):结构型模式
🌈 引言:设计模式就像乐高积木 适配器:让不同形状的积木完美拼接装饰器:给积木添加炫酷灯光效果代理:遥控积木完成复杂动作组合:将小积木搭建成宏伟城堡 结构型模式 主要用于描述对象之间的关系ÿ…...
【Python修仙编程】(二) Python3灵源初探(3)
第一部分:乾坤袋的秘密与修炼之路 在修仙界,有一个古老的传承,名为《Python无极心法》,它蕴含着强大的力量,能够助修仙者突破重重境界,领悟宇宙天地的奥秘。而要修炼此心法,必须先从基础的“乾…...
Mac本地部署Deep Seek R1
Mac本地部署Deep Seek R1 1.安装本地部署大型语言模型的工具 ollama 官网:https://ollama.com/ 2.下载Deepseek R1模型 网址:https://ollama.com/library/deepseek-r1 根据电脑配置,选择模型。 我的电脑:Mac M3 24G内存。 这…...
可以免费无限次下载PPT的网站
前言 最近发现了一个超实用的网站,想分享给大家。 在学习和工作的过程中,想必做PPT是一件让大家都很头疼的一件事。 想下载一些PPT模板减少做PPT的工作量,但网上大多精美的PPT都是需要付费才能下载使用。 即使免费也有次数限制࿰…...
c++作业
练习题: #include <iostream> #include <cstring> using namespace std;class mystring {char* p;int len; public:mystring();mystring(const char* p);~mystring();void copy(const mystring& str);void append(const mystring& str);void sh…...
补题蓝桥杯14届JavaB组第4题
算法:动态规划 需要两个一维数组来进行dp 一个用来记录到当前位置的最短时间,另一个用来记录到达当前位置传送门的最短时间 到达传送门的时间需要进行判断,如果上一次传送到达传送门,需要判断上一次传送到这的位置在当前传送门…...
DeepSeek 15天指导手册——从入门到精通 PDF(附下载)
DeepSeek使用教程系列--DeepSeek 15天指导手册——从入门到精通pdf下载: https://pan.baidu.com/s/1PrIo0Xo0h5s6Plcc_smS8w?pwd1234 提取码: 1234 或 https://pan.quark.cn/s/2e8de75027d3 《DeepSeek 15天指导手册——从入门到精通》以系统化学习路径为核心&…...
【北京迅为】itop-3568 开发板openharmony鸿蒙烧写及测试-第1章 体验OpenHarmony—烧写镜像
瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…...
C#开发——时间间隔类TimSpan
TimeSpan 是 C# 中的一个结构( struct ),用于表示时间间隔或持续时间。它位于 System 命名空间中,是处理时间相关操作时非常重要的工具,尤其是在计算两个日期或时间之间的差值、表示时间段或执行时间相关的运算…...
第002文-kali虚拟机安全与网络配置
1、kali系统介绍 kali是一个基于Linux kernel的操作系统,由BackTrack(简称BT)发展而来。BackTrack是2006年推出的一个用于渗透测试及黑客攻防的专用平台,基于Knoppix(linux的一个发行版)开发。BackTrack版本周期:2006年的起始版本BackTrack …...
【HarmonyOS Next】鸿蒙应用折叠屏设备适配方案
【HarmonyOS Next】鸿蒙应用折叠屏设备适配方案 一、前言 目前应用上架华为AGC平台,都会被要求适配折叠屏设备。目前华为系列的折叠屏手机,有华为 Mate系列(左右折叠,华为 Mate XT三折叠),华为Pocket 系列…...
关于“你对 Spring Cloud 的理解”
Spring Cloud 是一个基于 Spring Boot 的微服务框架,旨在简化分布式系统的开发、部署和管理。它提供了一系列工具和组件,帮助开发者构建和管理微服务架构。以下是对 Spring Cloud 的核心理解: 1. 微服务架构的支持 Spring Cloud 提供了对微…...
微信小程序-二维码绘制
wxml <view bindlongtap"saveQrcode"><!-- 二维码 --><view style"position: absolute;background-color: #FFFAEC;width: 100%;height: 100vh;"><canvas canvas-id"myQrcode" style"width: 200px; height: 200px;ba…...
c++中如何打印未知类型对象的类型
在 C 中要打印未知类型对象的类型名称,可以通过以下方法实现: 目录 方法一:使用 typeid 和 name()(需包含 ) 使用示例: 问题与改进: 方法二:编译时类型名称(C17 起&…...
SpringBoot集成easy-captcha图片验证码框架
SpringBoot集成easy-captcha图片验证码框架 此项目已经很久未维护,如有更好的选择,建议使用更好的选择!!! 一、引言 验证码(CAPTCHA)是现代应用中防止机器人攻击、保护接口安全的核心手段之一。然而,从零开发验证码…...
Materials Studio MS2020在linux系统上的安装包下载地址 支持centos Ubuntu rocky等系统
下载地址:MS2020-linux官方版下载丨最新版下载丨绿色版下载丨APP下载-123云盘 Materials Studio 2020是一款功能强大的材料科学计算模拟软件,以下是其详细介绍: 核心模块功能 CASTEP模块:采用平面波赝势方法,适用于周…...
DeepSeek 开源狂欢周(二)DeepEP深度技术解析 | 解锁 MoE 模型并行加速
在大模型时代,Mixture-of-Experts (MoE) 模型凭借其强大的容量和高效的计算能力,成为研究和应用的热点。然而,MoE 模型的训练和推理面临着巨大的专家并行通信挑战。近日,DeepSeek 开源了 DeepEP 项目,为解决这一难题提…...
Kylin麒麟操作系统 | 系统监控
以下所使用的环境为: 虚拟化软件:VMware Workstation 17 Pro 麒麟系统版本:Kylin-Server-V10-SP3-2403-Release-20240426-x86_64 一、系统状态查询工具 1. 静态显示系统进程信息ps ps命令会生成一个静态列表,列表中显示的进程其…...
mysql怎样优化where like ‘%字符串%‘这种模糊匹配的慢sql
一 问题描述 工作中经常遇到这种模糊匹配的慢sql: select * from 表名 where 字段 like %字符串%; 由于前面有%,导致无法走该字段上的索引。 二 解决办法 ① 给该字段创建一个全文索引 CREATE FULLTEXT INDEX 索引名 ON 表名 (字段名); ② 改写sq…...
基于 C++ Qt 的 Fluent Design 组件库 QFluentWidgets
简介 QFluentWidgets 是一个基于 Qt 的 Fluent Designer 组件库,内置超过 150 个开箱即用的 Fluent Designer 组件,支持亮暗主题无缝切换和自定义主题色。 编译示例 以 Qt5 为例(Qt6 也支持),将 libQFluentWidgets.d…...
事件【Qt】
文章目录 事件 事件 event label.cpp #include "label.h" #include<QDebug> Label::Label( QWidget * parent):QLabel(parent) {}void Label::enterEvent(QEvent *event) {//显式地忽略 event 参数,表示函数内部不会使用 event 参数,也不会对其进…...
若依vue plus环境搭建
继前面文章若依系统环境搭建记录-CSDN博客 把ruoyi vue plus也摸索了下。 作者是疯狂的狮子,dromara/RuoYi-Vue-Plus 初始化文档:项目初始化,环境搭建的视频:RuoYi-Vue-Plus 5.0 搭建与运行_哔哩哔哩_bilibili 上来就列出了一…...
算法题(80):环形链表II
审题: 需要我们判断链表是否带环,若带环,需要我们返回进入环的第一个节点地址 思路: 方法一:set 每个节点的地址都是唯一的,所以我们的set存的是节点地址。 当我们遍历链表时, 若节点地址没有存…...
Spring Boot集成Jetty、Tomcat或Undertow及支持HTTP/2协议
目录 一、常用Web服务器 1、Tomcat 2、Jetty 3、Undertow 二、什么是HTTP/2协议 1、定义 2、特性 3、优点 4、与HTTP/1.1的区别 三、集成Web服务器并开启HTTP/2协议 1、生成证书 2、新建springboot项目 3、集成Web服务器 3.1 集成Tomcat 3.2 集成Jetty 3.3 集成…...
ISO 15118,最新版,汽车充电桩相关标准,1~22子标准
ISO 15118 是一项国际标准,主要规定了电动汽车(EV)与充电桩(EVSE)之间的通信协议,涵盖了充电过程中的信息交换、安全认证、充电控制等内容。以下是其主要内容: 1. 通信协议 V2G通信:…...
信息系统项目管理师考试介绍和学习资料分享
信息系统项目管理师考试是评估考生在信息系统项目管理领域的专业知识和技能的重要考试。以下是对信息系统项目管理师考试的详细介绍: 拥有软考信息系统项目管理师高级证的作用: 提高求职竞争力: 信息系统项目管理师证书是国家级证书&#…...
基于 Spring AI 的 HIS 系统智能化改造
【Spring AI 的背景与现状】 Spring AI 是 Spring 生态里整的一个新活儿,专门给开发者提供搞 AI 驱动的应用的工具和框架。虽然 Spring AI 已经鼓捣了挺长时间,但截至现在(2025年2月),它还没正式发布。不过࿰…...
visual studio 2022安装教程及下载(附安装包)visual studio 2022下载安装教程图文详情
文章目录 前言一、visual studio 2022下载二、visual studio 2022安装教程三、软件设置四、安装完成 前言 Visual Studio 2022 作为强大的集成开发环境,深受开发者青睐。但初次安装,其复杂步骤易让人摸不着头脑。为帮大家顺利安装,本文将详细…...
Nginx+PHP+MYSQL-Ubuntu在线安装
在 Ubuntu 上配置 Nginx、PHP 和 MySQL 的步骤如下: 1. 更新系统包 首先,确保系统包是最新的: sudo apt update sudo apt upgrade2. 安装 Nginx 安装 Nginx: sudo apt install nginx启动并启用 Nginx 服务: sudo…...
【Excel】 Power Query抓取多页数据导入到Excel
抓取多页数据想必大多数人都会,只要会点编程技项的人都不会是难事儿。那么,如果只是单纯的利用Excel软件,我还真的没弄过。昨天,我就因为这个在网上找了好久发好久。 1、在数据-》新建查询-》从其他源-》自网站 ,如图 …...
spring boot 2.7 + seata +微服务 降级失败问题修复
文章引流 一个简单而使用的API管理工具 版本号 spring boot 2.7.17 spring-cloud-dependencies 2021.0.8 spring-cloud-circuitbreaker-resilience4j 2.1.7 spring-cloud-starter-alibaba-seata 2021.1 jdk 1.8原因分析 未配置属性 feign.circuitbreaker.enabledtrue # 未…...
Ubuntu 22.04 安装Nvidia驱动加速deepseek
一键安装22.04 nvidia 驱动 nvidia 官网下载驱动我的环境是NVIDIA RTX A5000nvidia 文档参考没有安装驱动之前确认自己的型号 lspci | grep -i vga (如数字2231) 参考docker 支持nvidia ,注释了需要的取消注释即可 42行-92行一定要重启服务器…...
【Java项目】基于Spring Boot的校园博客系统
【Java项目】基于Spring Boot的校园博客系统 技术简介:采用Java技术、Spring Boot框架、MySQL数据库等实现。 系统简介:校园博客系统是一个典型的管理系统,主要功能包括管理员:首页、个人中心、博主管理、文章分类管理、文章信息…...
centos7 离线安装docker
1.下载docker Index of linux/static/stable/x86_64/ 2.安装docker tar -zxvf docker-19.03.9.tgz cp -p docker/* /usr/bin 创建docker服务配置文件docker.servicevim /etc/systemd/system/docker.service [Unit] DescriptionDocker Application Container Engine Docume…...
基于Rook的Ceph云原生存储部署与实践指南(上)
#作者:任少近 文章目录 1 Ceph环境准备2 rook部署ceph群集2.1 Rook 帮助地址2.2 安装ceph2.3 获取csi镜像2.4 Master参加到osd2.5 设置默认存储 3 Rook部署云原生RBD块存储3.1 部署storageclass资源3.2 部署WordPress使用RBD3.3 WordPress访问 4 Rook部署云原生RGW…...
微服务合并
有的团队为了节约机器成本、有的团队为了提升研发效率、有的团队为了降低人均服务数 微服务合并,可以从多个角度入手 代码重构融合:人工拷贝代码、解决冲突,然后分阶段实施迁移重构。代码合并打包:将多个代码仓库,拉取…...
Linux中子线程会继承父线程对相关变量的可见性
在 Linux 的 POSIX 线程模型中,当父线程修改全局变量后创建子线程,子线程一定会看到修改后的最新值。这是由线程的内存共享机制和线程创建时序保证的,具体原理如下: 关键机制解析 内存共享本质: 所有线程共享相同的全局数据段修改操作直接作用于物理内存,无副本存在cint …...
道可云人工智能每日资讯|深圳将设立人工智能和机器人产业基金
道可云元宇宙每日简报(2025年2月26日)讯,今日元宇宙新鲜事有: 上海青浦发布国际产业协作元宇宙平台 近日,“2025出海企业与跨境专业服务论坛”在上海青浦区徐泾镇举行。论坛上重磅发布三大全球化服务平台,…...
5.11 PEFT重参数化方法:低秩分解的微调革命
PEFT重参数化方法:低秩分解的微调革命 一、重参数化技术全景图 mindmap root((重参数化方法)) LoRA "低秩矩阵分解" "参数冻结策略" AdaLoRA "动态秩调整" "重要性采样" QLoRA "量化低秩分解" "NF4量化策…...
vscode 版本
vscode官网 Visual Studio Code - Code Editing. Redefined 但是官网只提供最新 在之前的版本就要去github找了 https://github.com/microsoft/vscode/releases 获取旧版本vscode安装包的方法_vscode 老版本-CSDN博客...
自然语言处理NLP深探
1. NLP 的定义、特点、具体工作、历史和流派 定义:自然语言处理(Natural Language Processing,NLP)是计算机科学与人工智能领域的一个重要分支,旨在让计算机理解、处理和生成人类自然语言,实现人与计算机之间用自然语言进行有效通信。特点 交叉性:涉及计算机科学、语言学…...
【leetcode hot 100 15】三数之和
一、两数之和的扩展 class Solution {public List<List<Integer>> threeSum(int[] nums) {// 将得到的结果存入Set中,保证不重复Set<List<Integer>> set new HashSet<>();// 模拟两数之和,作为第一个循环中的内容for(in…...
提示学习(Prompting)
提示学习(Prompting)是一种利用预训练语言模型(Pre-trained Language Models, PLMs)来完成特定任务的方法。它的核心思想是通过设计特定的提示(Prompt),将任务转化为预训练模型能够理解的形式&a…...
wav格式的音频压缩,WAV 转 MP3 VBR 体积缩减比为 13.5%、多个 MP3 格式音频合并为一个、文件夹存在则删除重建,不存在则直接建立
🥇 版权: 本文由【墨理学AI】原创首发、各位读者大大、敬请查阅、感谢三连 🎉 声明: 作为全网 AI 领域 干货最多的博主之一,❤️ 不负光阴不负卿 ❤️ 文章目录 问题一:wav格式的音频压缩为哪些格式,网络传输给用户播放…...
TDengine 中的数据库
数据库概念 时序数据库 TDengine 中数据库概念,等同于关系型数据库 MYSQL PostgreSQL 中的数据库,都是对资源进行分割管理的单位。 TDengine 数据库与关系型数据库最大区别是跨库操作,TDengine 数据库跨库操作除了少量几个SQL 能支持外&…...
react覆盖组件样式,不影响其他地方相同类名的组件
less module 配合 :global(){} less文件 /* ButtonComponent.less */ .customButton {// 覆盖第三方按钮库的类名(如 .ant-btn):global(.ant-btn) {background: #1890ff;// 通过父选择器限定作用域&:hover {background: #40a9ff;}} } tsx文件 //…...
ProtoBuf
protobuf 序列化 序列化:本质就是将结构化的数据转成为字符串(在网络HTTP中遇到过)protobuf:就是将结构化的数据进行序列化的一种方式。 特点 • 语⾔⽆关、平台⽆关:即 ProtoBuf ⽀持 Java、C、Python 等多种语⾔…...
算法day2 dfs搜索2题
一 PERKET 当我们拿到这个题目的时候,确实郁闷到底该怎么做,首先我们看这个题目 题目中给我们提供了这么多个调料,这个调料有酸度和苦度,这些都是它的属性,但是我们是选择这个调料,那么就是对于一个调料有…...
【数据分析】通过拟水平法,实现混合正交表
拟水平法是一种将高水平正交表转换为低水平正交表的方法,适用于实验中某些因素的水平数少于正交表水平数的情况。通过拟水平法,可以充分利用现有的正交表资源,减少实验次数。 1. 拟水平法的基本思想 拟水平法的核心是将高水平正交表中的某些水平“合并”或“拆分”,使其适…...
利用node.js搭配express框架写后端接口(一)
Node.js 凭借其高效的非阻塞 I/O 操作、事件驱动架构以及轻量级的特点,成为了开发高性能服务器应用的热门选择。Express 框架作为 Node.js 上最流行的 Web 应用框架之一,以其简洁的 API 和丰富的中间件生态系统,极大地简化了 Web 后端开发流程…...