适配器模式深度解析:Java设计模式实战指南与接口兼容性解决方案

适配器模式深度解析:Java设计模式实战指南与接口兼容性解决方案


🌟 嗨,我是IRpickstars!
🌌 总有一行代码,能点亮万千星辰。
🔍 在技术的宇宙中,我愿做永不停歇的探索者。
✨ 用代码丈量世界,用算法解码未来。我是摘星人,也是造梦者。
🚀 每一次编译都是新的征程,每一个bug都是未解的谜题。让我们携手,在0和1的星河中,书写属于开发者的浪漫诗篇。


目录

1. 技术背景

2. 概念定义

2.1 适配器模式定义

2.2 核心组成要素

2.3 适配器类型

3. 原理剖析

3.1 工作机制

3.2 对象适配器vs类适配器

4. 技术实现

4.1 基础适配器接口实现

4.2 具体被适配者实现

4.3 适配器类实现

4.4 通用适配器框架实现

5. 应用场景

5.1 主要应用场景分析

5.2 典型使用场景

6. 实际案例

6.1 支付系统适配器案例

6.2 数据源适配器案例

7. 优缺点分析

7.1 适配器模式优缺点对比

7.2 详细分析

8. 纵横对比

8.1 与其他结构型模式对比

8.2 模式选择指导

9. 实战思考

9.1 最佳实践建议

9.2 性能优化策略

9.3 常见问题与解决方案

10. 总结

10.1 核心价值

10.2 适用边界

10.3 发展趋势

10.4 实践建议


1. 技术背景

在现代软件开发中,系统集成和接口兼容性问题是开发者经常面临的挑战。随着软件系统的复杂性不断增加,我们经常需要将具有不同接口的类或组件进行协作。这些组件可能来自第三方库、遗留系统或者不同的开发团队,它们的接口设计往往不能直接兼容。

适配器模式(Adapter Pattern)作为GoF设计模式中的一种重要结构型模式,为解决接口不兼容问题提供了优雅的解决方案。就像现实生活中的电源适配器能够让不同规格的插头与插座配合使用一样,软件中的适配器模式能够让原本因接口不匹配而无法协作的类能够一起工作。

在企业级应用开发中,适配器模式被广泛应用于:

  • 第三方SDK集成
  • 遗留系统现代化改造
  • 数据格式转换
  • API接口统一
  • 框架间的桥接

2. 概念定义

2.1 适配器模式定义

适配器模式(Adapter Pattern)是一种结构型设计模式,它允许接口不兼容的类协同工作。适配器模式通过将一个类的接口转换成客户端所期望的另一个接口,使得原本由于接口不匹配而不能一起工作的类能够协同工作。

2.2 核心组成要素

适配器模式主要包含以下几个核心要素:

  1. 目标接口(Target):客户端所期望的接口
  2. 被适配者(Adaptee):需要被适配的现有类
  3. 适配器(Adapter):实现目标接口并包装被适配者的类
  4. 客户端(Client):使用目标接口的代码

2.3 适配器类型

适配器模式有两种主要实现方式:

  • 对象适配器:使用组合关系,适配器持有被适配者的实例
  • 类适配器:使用继承关系,适配器继承被适配者类(Java中较少使用)

3. 原理剖析

3.1 工作机制

适配器模式的核心思想是通过引入一个适配器类,将被适配者的接口转换为目标接口。客户端通过目标接口与适配器交互,适配器内部调用被适配者的方法来完成实际工作。

图1 适配器模式工作机制图

3.2 对象适配器vs类适配器

图2 适配器模式实现方式对比图

4. 技术实现

4.1 基础适配器接口实现

/*** 目标接口:媒体播放器* 客户端期望的统一接口*/
public interface MediaPlayer {/*** 播放媒体文件* @param audioType 音频类型* @param fileName 文件名*/void play(String audioType, String fileName);
}/*** 被适配者:高级媒体播放器* 现有的第三方播放器接口*/
public interface AdvancedMediaPlayer {void playVlc(String fileName);void playMp4(String fileName);void playMkv(String fileName);
}

4.2 具体被适配者实现

/*** VLC播放器实现* 被适配的具体实现类*/
public class VlcPlayer implements AdvancedMediaPlayer {@Overridepublic void playVlc(String fileName) {System.out.println("正在播放VLC格式文件: " + fileName);}@Overridepublic void playMp4(String fileName) {// VLC播放器不支持MP4格式throw new UnsupportedOperationException("VLC播放器不支持MP4格式");}@Overridepublic void playMkv(String fileName) {// VLC播放器不支持MKV格式throw new UnsupportedOperationException("VLC播放器不支持MKV格式");}
}/*** MP4播放器实现*/
public class Mp4Player implements AdvancedMediaPlayer {@Overridepublic void playVlc(String fileName) {throw new UnsupportedOperationException("MP4播放器不支持VLC格式");}@Overridepublic void playMp4(String fileName) {System.out.println("正在播放MP4格式文件: " + fileName);}@Overridepublic void playMkv(String fileName) {throw new UnsupportedOperationException("MP4播放器不支持MKV格式");}
}

4.3 适配器类实现

/*** 媒体适配器* 将AdvancedMediaPlayer适配为MediaPlayer接口*/
public class MediaAdapter implements MediaPlayer {private AdvancedMediaPlayer advancedMusicPlayer;/*** 构造函数:根据音频类型创建相应的播放器* @param audioType 音频类型*/public MediaAdapter(String audioType) {if (audioType.equalsIgnoreCase("vlc")) {advancedMusicPlayer = new VlcPlayer();} else if (audioType.equalsIgnoreCase("mp4")) {advancedMusicPlayer = new Mp4Player();} else {throw new IllegalArgumentException("不支持的音频格式: " + audioType);}}@Overridepublic void play(String audioType, String fileName) {// 将统一的play方法适配为具体的播放方法if (audioType.equalsIgnoreCase("vlc")) {advancedMusicPlayer.playVlc(fileName);} else if (audioType.equalsIgnoreCase("mp4")) {advancedMusicPlayer.playMp4(fileName);} else {System.out.println("不支持的格式: " + audioType);}}
}/*** 音频播放器:主要的客户端类* 支持内置格式和通过适配器支持的格式*/
public class AudioPlayer implements MediaPlayer {private MediaAdapter mediaAdapter;@Overridepublic void play(String audioType, String fileName) {// 内置支持mp3格式if (audioType.equalsIgnoreCase("mp3")) {System.out.println("正在播放MP3格式文件: " + fileName);}// 通过适配器支持其他格式else if (audioType.equalsIgnoreCase("vlc") || audioType.equalsIgnoreCase("mp4")) {mediaAdapter = new MediaAdapter(audioType);mediaAdapter.play(audioType, fileName);} else {System.out.println("不支持的音频格式: " + audioType + "。仅支持mp3, vlc, mp4格式。");}}
}

4.4 通用适配器框架实现

/*** 通用适配器接口* 提供类型安全的适配器基础*/
public interface Adapter<T, R> {/*** 适配方法* @param source 源对象* @return 适配后的对象*/R adapt(T source);/*** 检查是否支持适配* @param source 源对象* @return 是否支持*/boolean supports(T source);
}/*** 抽象适配器基类* 提供通用的适配器实现模板*/
public abstract class AbstractAdapter<T, R> implements Adapter<T, R> {@Overridepublic final R adapt(T source) {if (!supports(source)) {throw new IllegalArgumentException("不支持的源对象类型");}return doAdapt(source);}/*** 具体的适配逻辑由子类实现*/protected abstract R doAdapt(T source);
}

5. 应用场景

5.1 主要应用场景分析

适配器模式在软件开发中有着广泛的应用场景:

图3 适配器模式应用场景分析图

5.2 典型使用场景

系统集成场景:

  • 整合不同厂商的API接口
  • 微服务架构中的接口适配
  • 数据库访问层的统一封装

接口标准化场景:

  • 多种支付方式的统一接口
  • 不同消息队列的统一访问
  • 多种缓存系统的统一操作

遗留系统改造场景:

  • 新旧系统的接口桥接
  • 数据格式的转换适配
  • 通信协议的转换

6. 实际案例

6.1 支付系统适配器案例

/*** 统一支付接口* 客户端期望的支付接口*/
public interface PaymentProcessor {/*** 处理支付* @param amount 金额* @param currency 货币类型* @return 支付结果*/PaymentResult processPayment(double amount, String currency);
}/*** 支付结果统一返回格式*/
public class PaymentResult {private boolean success;private String transactionId;private String message;// 构造函数和getter/setter方法省略public PaymentResult(boolean success, String transactionId, String message) {this.success = success;this.transactionId = transactionId;this.message = message;}// getter方法省略public boolean isSuccess() { return success; }public String getTransactionId() { return transactionId; }public String getMessage() { return message; }
}/*** 第三方支付SDK - 支付宝* 被适配的支付宝支付接口*/
public class AlipaySDK {public String alipayQuickPay(String amount, String currency) {// 模拟支付宝支付逻辑System.out.println("支付宝支付: ¥" + amount + " " + currency);return "ALIPAY_" + System.currentTimeMillis();}public boolean checkPaymentStatus(String orderId) {// 模拟状态检查return true;}
}/*** 第三方支付SDK - 微信支付* 被适配的微信支付接口*/
public class WechatPaySDK {public Map<String, Object> wechatUnifiedOrder(BigDecimal totalFee, String currencyType) {// 模拟微信支付逻辑System.out.println("微信支付: ¥" + totalFee + " " + currencyType);Map<String, Object> result = new HashMap<>();result.put("return_code", "SUCCESS");result.put("transaction_id", "WX_" + System.currentTimeMillis());return result;}
}/*** 支付宝适配器*/
public class AlipayAdapter implements PaymentProcessor {private AlipaySDK alipaySDK;public AlipayAdapter() {this.alipaySDK = new AlipaySDK();}@Overridepublic PaymentResult processPayment(double amount, String currency) {try {// 调用支付宝SDK进行支付String transactionId = alipaySDK.alipayQuickPay(String.valueOf(amount), currency);// 检查支付状态boolean success = alipaySDK.checkPaymentStatus(transactionId);return new PaymentResult(success, transactionId, "支付宝支付完成");} catch (Exception e) {return new PaymentResult(false, null, "支付宝支付失败: " + e.getMessage());}}
}/*** 微信支付适配器*/
public class WechatPayAdapter implements PaymentProcessor {private WechatPaySDK wechatPaySDK;public WechatPayAdapter() {this.wechatPaySDK = new WechatPaySDK();}@Overridepublic PaymentResult processPayment(double amount, String currency) {try {// 调用微信支付SDKMap<String, Object> result = wechatPaySDK.wechatUnifiedOrder(BigDecimal.valueOf(amount), currency);String returnCode = (String) result.get("return_code");boolean success = "SUCCESS".equals(returnCode);String transactionId = (String) result.get("transaction_id");return new PaymentResult(success, transactionId, "微信支付完成");} catch (Exception e) {return new PaymentResult(false, null, "微信支付失败: " + e.getMessage());}}
}

6.2 数据源适配器案例

/*** 统一数据源接口*/
public interface DataSource {/*** 获取数据* @param query 查询条件* @return 数据列表*/List<Map<String, Object>> getData(String query);/*** 获取数据源类型* @return 数据源类型*/String getDataSourceType();
}/*** REST API数据源适配器*/
public class RestApiAdapter implements DataSource {private String apiBaseUrl;private HttpClient httpClient;public RestApiAdapter(String apiBaseUrl) {this.apiBaseUrl = apiBaseUrl;this.httpClient = HttpClient.newHttpClient();}@Overridepublic List<Map<String, Object>> getData(String query) {try {// 构建REST API请求String url = apiBaseUrl + "/data?query=" + URLEncoder.encode(query, "UTF-8");HttpRequest request = HttpRequest.newBuilder().uri(URI.create(url)).GET().build();// 发送请求并解析响应HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());// 模拟JSON解析System.out.println("从REST API获取数据: " + query);return parseJsonResponse(response.body());} catch (Exception e) {throw new RuntimeException("REST API数据获取失败", e);}}@Overridepublic String getDataSourceType() {return "REST_API";}private List<Map<String, Object>> parseJsonResponse(String jsonResponse) {// 简化的JSON解析逻辑List<Map<String, Object>> result = new ArrayList<>();Map<String, Object> data = new HashMap<>();data.put("source", "REST_API");data.put("data", jsonResponse);result.add(data);return result;}
}/*** 数据源管理器* 统一管理不同类型的数据源*/
public class DataSourceManager {private List<DataSource> dataSources;public DataSourceManager() {this.dataSources = new ArrayList<>();}public void addDataSource(DataSource dataSource) {dataSources.add(dataSource);}/*** 从所有数据源获取数据并合并*/public List<Map<String, Object>> aggregateData(String query) {List<Map<String, Object>> aggregatedData = new ArrayList<>();for (DataSource dataSource : dataSources) {try {List<Map<String, Object>> data = dataSource.getData(query);aggregatedData.addAll(data);} catch (Exception e) {System.err.println("数据源 " + dataSource.getDataSourceType() + " 获取数据失败: " + e.getMessage());}}return aggregatedData;}
}

7. 优缺点分析

7.1 适配器模式优缺点对比

图4 适配器模式优缺点分析图

7.2 详细分析

主要优点:

  1. 接口兼容性:使得接口不兼容的类能够协同工作
  2. 代码复用:可以复用现有类的功能,无需重新开发
  3. 开闭原则:对扩展开放,对修改封闭
  4. 职责分离:将接口转换逻辑与业务逻辑分离

主要缺点:

  1. 系统复杂性:增加了系统的复杂性,类的数量增加
  2. 性能开销:增加了额外的方法调用层次
  3. 维护成本:需要维护适配器代码,接口变更可能影响适配器

8. 纵横对比

8.1 与其他结构型模式对比

对比维度

适配器模式

装饰器模式

外观模式

代理模式

主要目的

接口转换适配

功能增强扩展

简化复杂接口

控制访问代理

结构关系

适配不兼容接口

装饰原有对象

封装子系统

代理目标对象

使用时机

接口不匹配时

需要扩展功能时

接口过于复杂时

需要控制访问时

对象关系

组合或继承

组合关系

组合关系

组合关系

接口一致性

转换为目标接口

保持原接口

提供新接口

保持原接口

8.2 模式选择指导

图5 结构型模式选择指导图

9. 实战思考

9.1 最佳实践建议

1. 合理设计适配器接口

/*** 良好的适配器接口设计* 提供清晰的适配边界和异常处理*/
public abstract class BaseAdapter<Source, Target> {/*** 适配方法模板*/public final Target adapt(Source source) {// 前置检查validateSource(source);try {// 执行适配return doAdapt(source);} catch (Exception e) {// 统一异常处理handleAdaptException(e, source);throw new AdapterException("适配失败", e);}}/*** 源对象验证*/protected void validateSource(Source source) {if (source == null) {throw new IllegalArgumentException("源对象不能为null");}}/*** 具体适配逻辑由子类实现*/protected abstract Target doAdapt(Source source);/*** 异常处理*/protected void handleAdaptException(Exception e, Source source) {// 记录日志、监控等System.err.println("适配异常: " + e.getMessage());}
}

2. 适配器缓存优化

/*** 带缓存的适配器管理器* 优化适配器创建和使用性能*/
public class CachedAdapterManager {private final Map<Class<?>, Adapter<?, ?>> adapterCache = new ConcurrentHashMap<>();@SuppressWarnings("unchecked")public <S, T> T adapt(S source, Class<T> targetType) {Class<?> sourceType = source.getClass();String cacheKey = sourceType.getName() + "->" + targetType.getName();Adapter<S, T> adapter = (Adapter<S, T>) adapterCache.computeIfAbsent(sourceType, k -> createAdapter(sourceType, targetType));return adapter.adapt(source);}private <S, T> Adapter<S, T> createAdapter(Class<?> sourceType, Class<T> targetType) {// 根据类型创建相应的适配器// 可以使用工厂模式或反射机制return AdapterFactory.createAdapter(sourceType, targetType);}
}

9.2 性能优化策略

适配器池化技术:

/*** 适配器对象池* 减少适配器对象创建开销*/
public class AdapterPool<T extends Adapter<?, ?>> {private final Queue<T> pool = new ConcurrentLinkedQueue<>();private final Supplier<T> adapterFactory;private final int maxPoolSize;public AdapterPool(Supplier<T> adapterFactory, int maxPoolSize) {this.adapterFactory = adapterFactory;this.maxPoolSize = maxPoolSize;}public T borrowAdapter() {T adapter = pool.poll();return adapter != null ? adapter : adapterFactory.get();}public void returnAdapter(T adapter) {if (pool.size() < maxPoolSize) {// 重置适配器状态resetAdapter(adapter);pool.offer(adapter);}}private void resetAdapter(T adapter) {// 重置适配器内部状态if (adapter instanceof Resettable) {((Resettable) adapter).reset();}}
}

9.3 常见问题与解决方案

1. 适配器链问题
当需要多个适配器串联时,要注意避免过长的适配器链,影响性能和可维护性。

2. 双向适配
如果需要双向适配,建议创建两个独立的适配器而不是一个双向适配器。

3. 适配器测试
适配器的单元测试应该重点关注接口转换的正确性和异常处理。

/*** 适配器单元测试示例*/
@Test
public class PaymentAdapterTest {@Testpublic void testAlipayAdapter() {// 准备测试数据AlipayAdapter adapter = new AlipayAdapter();double amount = 100.0;String currency = "CNY";// 执行适配操作PaymentResult result = adapter.processPayment(amount, currency);// 验证结果assertNotNull(result);assertTrue(result.isSuccess());assertNotNull(result.getTransactionId());assertTrue(result.getTransactionId().startsWith("ALIPAY_"));}@Testpublic void testAdapterException() {// 测试异常情况AlipayAdapter adapter = new AlipayAdapter();// 验证异常处理assertThrows(IllegalArgumentException.class, () -> {adapter.processPayment(-100, "CNY");});}
}

10. 总结

适配器模式作为一种重要的结构型设计模式,在现代软件开发中发挥着关键作用。通过本文的深度解析,我们可以得出以下关键要点:

10.1 核心价值

接口兼容性价值: 适配器模式完美解决了接口不匹配的问题,使得原本无法协作的组件能够无缝集成,这在系统集成和第三方库整合中价值巨大。

代码复用价值: 通过适配器模式,我们可以充分复用现有的代码资源,避免重复开发,提高开发效率和代码质量。

系统扩展价值: 适配器模式提供了良好的扩展机制,新的适配器可以在不影响现有代码的情况下轻松添加,体现了开闭原则的精髓。

10.2 适用边界

最佳适用场景:

  • 需要整合不同厂商或第三方的API接口
  • 遗留系统的现代化改造和接口升级
  • 多种数据源或服务的统一访问接口
  • 系统间的协议转换和数据格式适配

不建议使用场景:

  • 接口本身设计合理且匹配的情况
  • 系统架构简单,没有复杂集成需求
  • 性能要求极高,不能容忍额外调用层次的场景

10.3 发展趋势

随着微服务架构和云原生技术的普及,适配器模式在API网关、服务网格、以及多云环境中的应用越来越广泛。未来的适配器模式将更多地与自动化工具、代码生成技术结合,减少手动编写适配器代码的工作量。

10.4 实践建议

在实际项目中应用适配器模式时,需要注意以下几点:

  1. 合理设计适配器层次:避免过深的适配器嵌套,保持简洁的调用链
  2. 重视性能优化:在高并发场景下考虑适配器的缓存和池化策略
  3. 完善异常处理:建立统一的异常处理机制,提高系统的健壮性
  4. 加强测试覆盖:重点测试接口转换的正确性和边界情况

适配器模式体现了软件设计中"适配"的智慧,它教会我们在面对不兼容的接口时,不是强行修改现有代码,而是通过引入适配层来优雅地解决问题。这种思想在软件架构设计、系统集成、以及日常开发中都有重要的指导意义。

通过深入理解和合理应用适配器模式,我们能够构建更加灵活、可扩展、易维护的软件系统,为企业的数字化转型和技术架构升级提供有力支撑。


参考资料:

  1. Design Patterns: Elements of Reusable Object-Oriented Software - GoF设计模式经典著作
  2. Oracle Java Documentation - Interface - Java官方接口文档
  3. Spring Framework Reference - Integration - Spring框架集成文档
  4. Effective Java Third Edition - Java最佳实践指南
  5. GitHub - Java Design Patterns - 适配器模式Java实现示例

关键词标签: #适配器模式 #设计模式 #Java #接口适配 #结构型模式 #系统集成 #软件架构 #编程实践

🌟 嗨,我是IRpickstars!如果你觉得这篇技术分享对你有启发:

🛠️ 点击【点赞】让更多开发者看到这篇干货
🔔 【关注】解锁更多架构设计&性能优化秘籍
💡 【评论】留下你的技术见解或实战困惑

作为常年奋战在一线的技术博主,我特别期待与你进行深度技术对话。每一个问题都是新的思考维度,每一次讨论都能碰撞出创新的火花。

🌟 点击这里👉 IRpickstars的主页 ,获取最新技术解析与实战干货!

⚡️ 我的更新节奏:

  • 每周三晚8点:深度技术长文
  • 每周日早10点:高效开发技巧
  • 突发技术热点:48小时内专题解析

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/83326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

类复制.省略 class.copy.elision

class类 复制/移动省略class.copy.elision 类复制省略 (copy elision) 当满足特定条件时&#xff0c;即使所选对象的构造函数和/或析构函数有副作用&#xff0c;实现也被允许省略从相同类型&#xff08;忽略 cv 限定符&#xff09;的源对象创建类对象。 在这种情况下&#…

goreplay

1.github地址 https://github.com/buger/goreplay 2.简单介绍 GoReplay 是一个开源的网络监控工具&#xff0c;可以记录用户的实时流量并将其用于镜像、负载测试、监控和详细分析。 3.出现背景 随着应用程序的增长&#xff0c;测试它所需的工作量也会呈指数级增长。GoRepl…

TensorZero:开源 LLM 应用优化与可观测性平台

TensorZero 是一个开源的 LLM&#xff08;大语言模型&#xff09;应用全链路优化平台&#xff0c;聚焦于“数据—评估—优化—实验”自动化闭环&#xff0c;极大提升 LLM 产品的可观测性、可优化性和可扩展性。无论你是 GPT 应用开发者&#xff0c;还是需要管理和提升 LLM 服务…

postgreSql数据迁移到openGauss的方案

从postgresql 导出sql 脚本 工具-备份 选择格式为Plain 得到脚本用vscode 打开并编辑 首先使用查找替换功能 语法适配修改‌&#xff1a; 替换不支持的参数如lock_timeout为lockwait_timeout 移除row_security等openGauss不支持的配置 检查并修改物化视图的刷新语法 …

网络爬虫学习心得

一、引言​ 在大数据时代&#xff0c;数据成为了驱动决策、洞察趋势的核心资源。出于对数据分析的浓厚兴趣&#xff0c;以及希望能更高效获取网络信息的目的&#xff0c;我踏上了网络爬虫的学习之旅。通过这段时间的学习&#xff0c;我不仅掌握了从网页中提取数据的技术&#…

计算机视觉与深度学习 | 基于Matlab的低照度图像增强算法原理,公式及实现

基于Matlab的低照度图像增强是一个重要的图像处理领域。这里我们重点介绍一种经典且效果较好的算法:多尺度Retinex算法(Multi-Scale Retinex with Color Restoration, MSRCR),包括其原理、公式及Matlab实现。 一、核心原理:Retinex理论 Retinex理论由Edwin Land提出,其…

【Linux跬步积累】—— 网络编程套接字(二)

&#x1f30f;博客主页&#xff1a;PH_modest的博客主页 &#x1f6a9;当前专栏&#xff1a;Linux跬步积累 &#x1f48c;其他专栏&#xff1a; &#x1f534; 每日一题 &#x1f7e1; C跬步积累 &#x1f7e2; C语言跬步积累 &#x1f308;座右铭&#xff1a;广积粮&#xff0…

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…

pikachu靶场通关笔记24 SQL注入07-http header注入

目录 一、SQL注入 二、http header注入 1、User - Agent 头注入 2、Referer 头注入 3、Cookie 头注入 4、Host 头注入 三、extractvalue函数 四、源码分析 1、代码审计 2、渗透思路 五、渗透实战 1、渗透探测 2、获取数据库名database 3、获取表名table 4、获取列…

LabVIEW振动时效处理系统

LabVIEW 开发大功率振动时效处理系统&#xff0c;实现工件残余应力检测与消除。聚焦工业场景中金属加工件的应力处理需求&#xff0c;展现 LabVIEW 在跨硬件集成、实时数据处理及复杂流程控制中的技术优势。 ​ 应用场景 针对航空航天、轨道交通、重型机械等领域中钢性焊接件…

数据定义以及数据类型

toc 数据定义以及数据类型 1. 数据创建 数据库创建除了指定数据库名字&#xff0c;还可以选择指定数据库字符集类型以及校对规则&#xff0c;mysql中utf8mb3就是utf8。 -- 使用指令创建数据库 CREATE DATABASE hsp_db01; -- 删除数据库指令 DROP DATABASE hsp_db01 -- 创建…

中国汽车启动电池市场深度剖析:现状、趋势与展望

一、市场规模与增长前景​ QYResearch 调研团队发布的市场报告显示&#xff0c;中国汽车启动电池市场展现出强劲的增长势头。预计到 2031 年&#xff0c;市场规模将攀升至 74.6 亿美元&#xff0c;在未来几年内&#xff0c;年复合增长率&#xff08;CAGR&#xff09;将稳定保持…

通过RedisCacheManager自定义缓存序列化(适用通过注解缓存数据)

1.Redis 注解默认序列化机制 1.Spring Boot整合Redis组件提供的缓存自动配置类RedisCacheConfiguration&#xff08;org.springframework.boot.autoconfigure.cache&#xff09;, 其内部是通过Redis连接工厂RedisConnectionFactory定义了一个缓存管理器RedisCacheManager&am…

jupyter中的checkpoints为空/打不开解决办法

jupyter中的checkpoints为空/打不开不要以为你是代码有问题或者服务器有问题了&#xff0c;浪费我好几天时间&#xff0c;我说怎么电脑上跑的好好的服务器上模型不见了 新建文件check 然后把checkpoints里的东西全部移动到check文件中就能看见了 checkpoints是Notebook的关键…

基于 Spring AI 的 MCP 客户端/服务端实现

模型上下文协议&#xff08;MCP&#xff09;由Anthropic开源的开放协议&#xff0c;为AI模型与外部数据/工具提供了“标准化桥梁”&#xff0c;通过统一的接口规范&#xff0c;使模型能够动态调用本地文件、数据库、API等资源&#xff0c;实现“上下文感知”的智能交互。MCP的核…

python学习打卡day50

DAY 50 预训练模型CBAM模块 知识点回顾&#xff1a; resnet结构解析CBAM放置位置的思考针对预训练模型的训练策略 差异化学习率三阶段微调 ps&#xff1a;今日的代码训练时长较长&#xff0c;3080ti大概需要40min的训练时长 作业&#xff1a; 好好理解下resnet18的模型结构尝试…

54、错误处理-【源码流程】异常处理流程

54、错误处理-【源码流程】异常处理流程 #### 异常处理流程概述 1. **执行目标方法**&#xff1a; - 程序执行目标方法&#xff0c;期间若发生异常&#xff0c;会被捕获并记录&#xff0c;标志当前请求结束。 - 将异常信息赋值给 dispatchException 变量。 2. **进入视图解析…

使用 VSCode 开发 FastAPI 项目(1)

一、引言 FastAPI 是一款现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;使用 Python 3.7 及更高版本。它基于标准 Python 类型提示&#xff0c;具有自动生成文档等出色功能。而 VSCode 凭借其轻量、强大的特性&#xff0c;为开发者…

Bash 脚本中的特殊变量

在 Bash 脚本和命令行中&#xff0c;​特殊变量​&#xff08;Special Variables&#xff09;主要用于获取脚本或命令的上下文信息&#xff0c;如参数、进程状态、返回值等。以下是常见的特殊变量及其典型应用场景&#xff1a; ​1. 脚本参数处理​ $0、$1、$2 ... $9、${10}.…