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

SpringBoot源码解析(六):打印Banner

SpringBoot源码系列文章

SpringBoot源码解析(一):SpringApplication构造方法

SpringBoot源码解析(二):引导上下文DefaultBootstrapContext

SpringBoot源码解析(三):启动开始阶段

SpringBoot源码解析(四):解析应用参数args

SpringBoot源码解析(五):准备应用环境

SpringBoot源码解析(六):打印Banner


目录

  • 前言
  • 一、入口
  • 二、Banner接口类
    • 1、打印Banner开关
  • 三、打印Banner过程
    • 1、console和log模式
    • 2、四种Banner对象
      • 2.1、图片Banner
      • 2.2、文字Banner
      • 2.2、备用Banner
      • 2.3、默认Banner
  • 总结

前言

  在前文中,我们深入解析了SpringBoot启动时应用环境的准备过程。接下来将深入介绍启动Banner打印的具体实现及流程。

SpringBoot版本2.7.18SpringApplication的run方法的执行逻辑如下,本文将详细介绍第5小节:打印启动Banner

// SpringApplication类方法
public ConfigurableApplicationContext run(String... args) {// 记录应用启动的开始时间long startTime = System.nanoTime();// 1.创建引导上下文,用于管理应用启动时的依赖和资源DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;// 配置无头模式属性,以支持在无图形环境下运行// 将系统属性 java.awt.headless 设置为 trueconfigureHeadlessProperty();// 2.获取Spring应用启动监听器,用于在应用启动的各个阶段执行自定义逻辑SpringApplicationRunListeners listeners = getRunListeners(args);// 启动开始方法(发布开始事件、通知应用监听器ApplicationListener)listeners.starting(bootstrapContext, this.mainApplicationClass);try {// 3.解析应用参数ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 4.准备应用环境,包括读取配置文件和设置环境变量ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);// 配置是否忽略 BeanInfo,以加快启动速度configureIgnoreBeanInfo(environment);// 5.打印启动BannerBanner printedBanner = printBanner(environment);// 6.创建应用程序上下文context = createApplicationContext();// 设置应用启动的上下文,用于监控和管理启动过程context.setApplicationStartup(this.applicationStartup);// 7.准备应用上下文,包括加载配置、添加 Bean 等prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);// 8.刷新上下文,完成 Bean 的加载和依赖注入refreshContext(context);// 9.刷新后的一些操作,如事件发布等afterRefresh(context, applicationArguments);// 计算启动应用程序的时间,并记录日志Duration timeTakenToStartup = Duration.ofNanos(System.nanoTime() - startTime);if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), timeTakenToStartup);}// 10.通知监听器应用启动完成listeners.started(context, timeTakenToStartup);// 11.调用应用程序中的 `CommandLineRunner` 或 `ApplicationRunner`,以便执行自定义的启动逻辑callRunners(context, applicationArguments);}catch (Throwable ex) {// 12.处理启动过程中发生的异常,并通知监听器handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {// 13.计算应用启动完成至准备就绪的时间,并通知监听器Duration timeTakenToReady = Duration.ofNanos(System.nanoTime() - startTime);listeners.ready(context, timeTakenToReady);}catch (Throwable ex) {// 处理准备就绪过程中发生的异常handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}// 返回已启动并准备就绪的应用上下文return context;
}

一、入口

// 5.打印启动Banner
Banner printedBanner = printBanner(environment);// 打印启动 Banner 的方法,根据配置的 Banner 模式选择打印方式
private Banner printBanner(ConfigurableEnvironment environment) {// 如果 Banner 模式被设置为 OFF,则不打印 Banner,直接返回 nullif (this.bannerMode == Banner.Mode.OFF) {return null;}// 确定资源加载器。如果当前实例的 resourceLoader 不为空,则使用它;否则创建一个默认的资源加载器ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader: new DefaultResourceLoader(null);// 创建 Banner 打印器,负责加载和打印 BannerSpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);// 根据 Banner 模式决定打印到日志还是控制台if (this.bannerMode == Mode.LOG) {// 如果 Banner 模式为 LOG,则将 Banner 打印到日志中return bannerPrinter.print(environment, this.mainApplicationClass, logger);}// 默认情况下(CONSOLE 模式),将 Banner 打印到标准输出(控制台)return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}

二、Banner接口类

// 一个用于以编程方式输出 Banner 的接口类
@FunctionalInterface
public interface Banner {// 将 Banner 输出到指定的打印流void printBanner(Environment environment, Class<?> sourceClass, PrintStream out);// 用于配置 Banner 的模式枚举enum Mode {// 禁用 Banner 的打印OFF,// 将 Banner 输出到 System.outCONSOLE,// 将 Banner 输出到日志文件LOG}
}

1、打印Banner开关

  • 默认情况是打印到控制台

在这里插入图片描述

  • 可以通过properties或yml设置关闭打印Banner
spring.main.banner-mode=off

上一节有讲spring.main开头的属性会绑定到SpringApplication对象上,这样就可以通过配置文件的属性来决定Banner的打印模式。

三、打印Banner过程

1、console和log模式

  • console控制台模式,默认设置
// SpringApplicationBannerPrinter类方法
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {// 根据提供的环境信息获取横幅。Banner banner = getBanner(environment);// 将横幅打印到指定的输出流中。banner.printBanner(environment, sourceClass, out);// 返回一个 PrintedBanner 对象,包含打印的横幅和源类信息。return new PrintedBanner(banner, sourceClass);
}
  • log日志文件模式,通过在配置文件中设置spring.main.banner-mode=log,可以将应用启动Banner输出到日志文件中
// SpringApplicationBannerPrinter类方法
Banner print(Environment environment, Class<?> sourceClass, Log logger) {// 根据提供的环境信息获取横幅。Banner banner = getBanner(environment);try {logger.info(createStringFromBanner(banner, environment, sourceClass));}catch (UnsupportedEncodingException ex) {logger.warn("Failed to create String for banner", ex);}// 返回一个 PrintedBanner 对象,包含打印的横幅和源类信息。return new PrintedBanner(banner, sourceClass);
}
  • log模式就是获取打印流内容转换为字符串,然后由log日志打印罢了

在这里插入图片描述

  两种方式都会返回一个PrintedBanner对象,主要是为以后在应用上下文中注册为Bean或供其他组件使用做准备。

2、四种Banner对象

  1. 图片和文本横幅组合的Banners
  2. 备用Banner
  3. 默认Banner
// SpringApplicationBannerPrinter类方法// 默认Banner
private static final Banner DEFAULT_BANNER = new SpringBootBanner();// 根据当前环境获取适当的横幅(Banner)
private Banner getBanner(Environment environment) {// 创建一个 Banners 对象,用于存储图片和文本横幅Banners banners = new Banners();// 尝试获取图片横幅,并将其添加到 Banners 中(如果非空)banners.addIfNotNull(getImageBanner(environment));// 尝试获取文本横幅,并将其添加到 Banners 中(如果非空)banners.addIfNotNull(getTextBanner(environment));// 如果至少包含一个横幅,则返回组合的 Banners 对象if (banners.hasAtLeastOneBanner()) {return banners;}// 如果没有任何横幅但存在备用横幅,则返回备用横幅if (this.fallbackBanner != null) {return this.fallbackBanner;}// 如果没有任何横幅,则返回默认横幅// Banner DEFAULT_BANNER = new SpringBootBanner();return DEFAULT_BANNER;
}
  • Banners对象内部持有多个Banner实现类,遍历调用Banner的printBanner方法

在这里插入图片描述

2.1、图片Banner

  • 尝试根据环境信息获取图片横幅(Image Banner)
  • 环境变量spring.banner.image.location用于指定图片路径;如果未设置,则默认加载路径为banner.gifbanner.jpgbanner.png(按顺序查找)。
private Banner getImageBanner(Environment environment) {// 从环境变量中获取横幅图片的路径// String BANNER_IMAGE_LOCATION_PROPERTY = "spring.banner.image.location";String location = environment.getProperty(BANNER_IMAGE_LOCATION_PROPERTY);// 如果路径不为空,尝试加载对应的资源if (StringUtils.hasLength(location)) {Resource resource = this.resourceLoader.getResource(location);// 如果资源存在,返回对应的 ImageBanner 对象return resource.exists() ? new ImageBanner(resource) : null;}// 如果未指定路径,尝试加载默认图片横幅文件// String[] IMAGE_EXTENSION = { "gif", "jpg", "png" };for (String ext : IMAGE_EXTENSION) {Resource resource = this.resourceLoader.getResource("banner." + ext);// 如果找到存在的文件资源,返回对应的 ImageBanner 对象if (resource.exists()) {return new ImageBanner(resource);}}// 如果没有找到任何图片横幅资源,返回 nullreturn null;
}

控制台效果

在这里插入图片描述

2.2、文字Banner

  • 尝试根据环境信息获取文本横幅(Text Banner)
  • 环境变量spring.banner.location用于指定文本路径;如果未设置,则默认加载路径为banner.txt
private Banner getTextBanner(Environment environment) {// 获取横幅的路径,优先使用环境变量中的配置,如果没有配置则使用默认路径// String BANNER_LOCATION_PROPERTY = "spring.banner.location";// String DEFAULT_BANNER_LOCATION = "banner.txt";String location = environment.getProperty(BANNER_LOCATION_PROPERTY, DEFAULT_BANNER_LOCATION);// 使用 ResourceLoader 加载指定路径的资源Resource resource = this.resourceLoader.getResource(location);try {// 检查资源是否存在,且路径中不包含 "liquibase-core"(防止加载到不相关的资源)if (resource.exists() && !resource.getURL().toExternalForm().contains("liquibase-core")) {// 如果资源有效,返回对应的 ResourceBanner 对象return new ResourceBanner(resource);}} catch (IOException ex) {// 忽略异常,可能是资源加载时出错或路径无效// 在这里不抛出异常,而是返回 null,表示没有有效的横幅资源}// 如果资源无效或发生异常,返回 nullreturn null;
}

控制台效果

在这里插入图片描述

2.2、备用Banner

  SpringApplicationBannerPrinter对象的备用Banner属性fallbackBanner是由SpringApplication对象的私有属性banner传递而来的。

在这里插入图片描述

  • 可以在SpringBoot启动类中通过调用SpringApplicationsetBanner方法直接设置自定义的Banner对象
@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication app = new SpringApplication(Application.class);// 设置全局备用横幅app.setBanner((environment, sourceClass, out) -> {out.println("===== 全局备用横幅 =====");out.println(" 默认横幅已启用 ");out.println("=====================");});app.run(args);}
}

控制台效果

在这里插入图片描述

2.3、默认Banner

  如果未设置自定义文字图片Banner或备用Banner,SpringBoot将使用默认的启动横幅(SpringBootBanner)作为显示内容。

// 默认的 Banner 实现,用于打印 "Spring" 的启动横幅,和版本信息
class SpringBootBanner implements Banner {// 预定义的 ASCII 艺术横幅,每行为一个数组元素private static final String[] BANNER = { "", "  .   ____          _            __ _ _"," /\\\\ / ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\","( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\"," \\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )", "  '  |____| .__|_| |_|_| |_\\__, | / / / /"," =========|_|==============|___/=/_/_/_/" };// 固定的 Spring Boot 标识符,用于横幅输出private static final String SPRING_BOOT = " :: Spring Boot :: ";// 横幅固定宽度,用于计算 padding 的空格数private static final int STRAP_LINE_SIZE = 42;/*** 输出横幅到指定的 PrintStream(如控制台或日志)。*/@Overridepublic void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {// 遍历并打印每一行 ASCII 艺术横幅for (String line : BANNER) {printStream.println(line);}// 获取 Spring Boot 的版本信息String version = SpringBootVersion.getVersion();// 如果版本信息不为空,则格式化为 "(vX.X.X)"version = (version != null) ? " (v" + version + ")" : "";// 构造 padding 空格,使横幅版本号对齐StringBuilder padding = new StringBuilder();while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {padding.append(" ");}// 打印 Spring Boot 标识符和版本信息,使用 ANSI 输出样式printStream.println(AnsiOutput.toString(AnsiColor.GREEN,       // 绿色输出 Spring Boot 标识符SPRING_BOOT, AnsiColor.DEFAULT,     // 恢复默认颜色padding.toString(),    // 填充的空格AnsiStyle.FAINT,       // 微弱样式(淡化显示版本信息)version                // 版本号));// 添加空行用于分隔横幅和其他输出printStream.println();}
}

控制台效果

在这里插入图片描述

总结

  本文全面解析了SpringBoot启动横幅的实现原理、打印流程及自定义方法,介绍了文本横幅(默认路径为banner.txt,可通过spring.banner.location配置)、图片横幅(默认路径为banner.gifbanner.jpgbanner.png,可通过spring.banner.image.location配置)、备用横幅默认横幅的使用,帮助开发者灵活运用横幅机制提升项目启动体验。

相关文章:

SpringBoot源码解析(六):打印Banner

SpringBoot源码系列文章 SpringBoot源码解析(一)&#xff1a;SpringApplication构造方法 SpringBoot源码解析(二)&#xff1a;引导上下文DefaultBootstrapContext SpringBoot源码解析(三)&#xff1a;启动开始阶段 SpringBoot源码解析(四)&#xff1a;解析应用参数args Sp…...

【计算机网络】实验6:IPV4地址的构造超网及IP数据报

实验 6&#xff1a;IPV4地址的构造超网及IP数据报 一、 实验目的 加深对IPV4地址的构造超网&#xff08;无分类编制&#xff09;的了解。 加深对IP数据包的发送和转发流程的了解。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实验内容 1、了解IPV4地址的构造超网…...

easy excel 生成excel 文件

导包 <dependency><groupId>com.alibaba</groupId><artifactId>easyexcel</artifactId><version>3.3.3</version> </dependency> 内容 List<类> limspjreport 值; String fileName sdf.format(new Date()) "-…...

Ajax:回忆与节点

一点回忆 面对我的Ajax学习&#xff0c;实现前后端交互&#xff0c;最开始我采用的使用网络寻找intellij IDEA Ultimate破解方法&#xff0c;然后最终成功&#xff0c;然后按照相关教程配置java ee项目&#xff0c;然后中间又去配置了Tomcat服务器&#xff0c;然后又去学习了一…...

Python+OpenCV系列:Python和OpenCV的结合和发展

PythonOpenCV系列&#xff1a;Python和OpenCV的结合和发展 **引言****Python语言的发展****1.1 Python的诞生与发展****1.2 Python的核心特性与优势****1.3 Python的应用领域** **OpenCV的发展****2.1 OpenCV的起源与发展****2.2 OpenCV的功能特性****2.3 OpenCV的应用场景** *…...

Ubuntu20.04 由源码编译安装opencv3.2 OpenCV

Ubuntu20.04 由源码编译安装opencv3.2.0 获取 opencv 及opencv_contrib源代码 创建目录以存放opencv及opencv_contrib源代码 mkdir ~/opencv3.2.0 cd ~/opencv3.2.0获取opencv源代码并切换到对应tag git clone https://github.com/opencv/opencv.git cd opencv git checkou…...

A058-基于Spring Boot的餐饮管理系统的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看项目链接获取⬇️&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600个选题ex…...

RDIFramework.NET CS敏捷开发框架 SOA服务三种访问(直连、WCF、WebAPI)方式

1、介绍 在软件开发领域&#xff0c;尤其是企业级应用开发中&#xff0c;灵活性、开放性、可扩展性往往是项目成功的关键因素。对于C/S项目&#xff0c;如何高效地与后端数据库进行交互&#xff0c;以及如何提供多样化的服务访问方式&#xff0c;是开发者需要深入考虑的问题。…...

Linux——命名管道及日志

linux——进程间通信及管道的应用场景-CSDN博客 文章目录 目录 文章目录 前言 一、命名管道是什么&#xff1f; 理解&#xff1a; 2、编写代码 makefile 管道封装成类&#xff0c;想用中管道时只需要调用实例化 读端 写端 日志 1、日志是什么&#xff1f; 2、日志有什么&#x…...

Flink 常见面试题

1、Flink 的四大特征&#xff08;基石&#xff09; checkpoin基于Chandy-Lamport算法实现了分布式一致性快照提供了一致性的语义 state丰富的StateAPI time实现了Watermark机制&#xff0c;乱序数据处理&#xff0c;迟到数据容忍 window开箱即用的滚动&#xff0c;滑动会话窗口…...

rtc-pcf8563 0-0051: low voltage detected, date/time is not reliable

解决方法&#xff1a; 1、先测量pcf8563电源电压&#xff0c;是否满足要求。 2、pcf8563首次操作。第一次读取pcf8563的时间&#xff0c;未初始化&#xff0c;非法&#xff0c;芯片门槛电压检测配置不合理。使用hwclock命令写入一次&#xff0c;即可解决。 hwclock -f /dev/…...

(简单5步实现)部署本地AI大语言模型聊天系统:Chatbox AI + grok2.0大模型

摘要&#xff1a; 本文将指导您如何部署一个本地AI大语言模型聊天系统&#xff0c;使用Chatbox AI客户端应用和grok-beta大模型&#xff0c;以实现高效、智能的聊天体验。 引言&#xff1a; 由马斯克X-AI发布的Grok 2大模型以其卓越的性能超越了GPT4.0。Grok模型支持超长文本…...

MAUI APP开发蓝牙协议的经验分享:与跳绳设备对接

在开发MAUI应用程序时&#xff0c;蓝牙协议的应用是一个重要的环节&#xff0c;尤其是在需要与外部设备如智能跳绳进行数据交换的场景中。以下是我在开发过程中的一些经验和心得&#xff0c;希望能为你的项目提供帮助。 1. 蓝牙协议基础 蓝牙协议是无线通信的一种标准&#x…...

最新版Node.js下载安装及环境配置教程

目录 初识&#xff1a;Node.js 一、下载&#xff1a;Node.js 二、安装&#xff1a;Node.js 1.下载【node.js】压缩包安装文件 2.解压下载的安装包 3.打开解压的【node-v22.11.0-x64】文件夹 4.双击启动安装程序 5.点击【Next】 6.勾选【I accept the terms in the Lic…...

51c自动驾驶~合集39

我自己的原文哦~ https://blog.51cto.com/whaosoft/12707676 #DiffusionDrive 大幅超越所有SOTA&#xff01;地平线DiffusionDrive&#xff1a;生成式方案或将重塑端到端格局&#xff1f; 近年来&#xff0c;由于感知模型的性能持续进步&#xff0c;端到端自动驾驶受到了来…...

单链表基础操作

文章目录 abstract定义结点结构初始化链表遍历链表求表长查找结点根据序号查找结点根据值查找结点 插入结点首尾位置插入一般位置插入(通用插入)找到尾元素|尾指针相关操作 删除结点 abstract 单链表是一种简单的动态数据结构&#xff0c;它由一系列结点组成&#xff0c;每个结…...

Asp.net MVC在VSCore中的页面的增删改查(以Blog项目为例),用命令代码

在VSCore中的页面的增删改查(以Blog项目为例) 1.创建项目&#xff08;无解决方案&#xff09;复杂项目才需要 dotnet new mvc -o Blog2.控制器 BlogsController.cs 控制器&#xff08;Controller&#xff09;名字和视图&#xff08;View&#xff09;中的文件名要一模一样 u…...

【Leecode】Leecode刷题之路第66天之加一

题目出处 66-加一-题目出处 题目描述 个人解法 思路&#xff1a; todo代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo官方解法 66-加一-官方解法 方法1&#xff1a;找出最长的后缀9 思路&#xff1a; 代码示例&#xff1a;&#xff08;Java&#…...

使用 VLC 在本地搭建流媒体服务器 (详细版)

提示&#xff1a;详细流程 避坑指南 Hi~&#xff01;欢迎来到碧波空间&#xff0c;平时喜欢用博客记录学习的点滴&#xff0c;欢迎大家前来指正&#xff0c;欢迎欢迎~~ ✨✨ 主页&#xff1a;碧波 &#x1f4da; &#x1f4da; 专栏&#xff1a;音视频 目录 借助VLC media pl…...

Ubuntu 常用解压与压缩命令

.zip文件 unzip FileName.zip # 解压 zip DirName.zip DirName # 将DirName本身压缩 zip -r DirName.zip DirName # 压缩&#xff0c;递归处理&#xff0c;将指定目录下的所有文件和子目录一起压缩 zip DirName.zip DirName 行为&#xff1a; 只压缩 DirName 目录本身&#xff…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)

一、数据处理与分析实战 &#xff08;一&#xff09;实时滤波与参数调整 基础滤波操作 60Hz 工频滤波&#xff1a;勾选界面右侧 “60Hz” 复选框&#xff0c;可有效抑制电网干扰&#xff08;适用于北美地区&#xff0c;欧洲用户可调整为 50Hz&#xff09;。 平滑处理&…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

视频字幕质量评估的大规模细粒度基准

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 摘要 视频字幕在文本到视频生成任务中起着至关重要的作用&#xff0c;因为它们的质量直接影响所生成视频的语义连贯性和视觉保真度。尽管大型视觉-语言模型&#xff08;VLMs&#xff09;在字幕生成方面…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

10-Oracle 23 ai Vector Search 概述和参数

一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI&#xff0c;使用客户端或是内部自己搭建集成大模型的终端&#xff0c;加速与大型语言模型&#xff08;LLM&#xff09;的结合&#xff0c;同时使用检索增强生成&#xff08;Retrieval Augmented Generation &#…...

Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)

Aspose.PDF 限制绕过方案&#xff1a;Java 字节码技术实战分享&#xff08;仅供学习&#xff09; 一、Aspose.PDF 简介二、说明&#xff08;⚠️仅供学习与研究使用&#xff09;三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...