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

Spring Boot - 在Spring Boot中实现灵活的API版本控制(下)_ 封装场景启动器Starter

文章目录

  • Pre
  • 设计思路
    • `@ApiVersion` 功能特性
    • 使用示例
    • 配置示例
  • Project
  • Starter Code
    • 自定义注解 ApiVersion
    • 配置属性类用于管理API版本
    • 自动配置基于Spring MVC的API版本控制
    • 实现WebMvcRegistrations接口,用于自定义WebMvc的注册逻辑
    • 扩展RequestMappingHandlerMapping的类,支持API版本路由
    • spring.factories
  • Test Code
    • 无版本控制
    • 多版本控制
    • v1
    • v2
    • Test

在这里插入图片描述

Pre

Spring Boot - 在Spring Boot中实现灵活的API版本控制(上)


设计思路

@ApiVersion 功能特性

  1. 支持类和方法上使用:

    • 优先级:方法上的注解优先于类上的注解。
    • 如果类和方法同时使用 @ApiVersion,则以方法上的版本为准。
  2. 支持多版本同时生效:

    • @ApiVersion 的参数是数组,可以配置多个版本。例如:@ApiVersion({1, 2}),此配置允许通过 v1v2 访问。
  3. 可配置前缀和后缀:

    • 默认前缀是 v,可以通过配置项 api-version.prefix 修改。
    • 默认没有后缀,但可以通过 api-version.suffix 配置。
  4. 使用简单:

    • 仅需一个注解即可完成版本控制。

使用示例

假设你有一个 UserController,需要支持 v1v2 的版本访问:

@RestController
@RequestMapping("/users")
public class UserController {@GetMapping@ApiVersion({1, 2})public List<User> getUsers() {// 获取用户列表的实现}@GetMapping("/{id}")@ApiVersion(2)public User getUserV2(@PathVariable Long id) {// 获取用户详细信息的实现,仅在 v2 版本中有效}
}

在这个示例中,getUsers 方法在 v1v2 版本都可访问,而 getUserV2 方法仅在 v2 版本可访问。

配置示例

application.properties 中配置版本前缀和后缀:

api-version.prefix=v
api-version.suffix=-api

这样,API 的 URL 可以是 /v1-api/users/v2-api/users

通过这种方式,@ApiVersion 注解简化了 API 版本控制的实现,提高了代码的可维护性和灵活性。


Project

在这里插入图片描述


Starter Code

自定义注解 ApiVersion

package com.github.artisan.annotation;import org.springframework.web.bind.annotation.Mapping;import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** 接口版本标识注解* @author artisan*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface ApiVersion {/*** 指定API的版本号。* 此方法返回一个整型数组,数组中的每个元素代表一个API版本号。** @return 代表API版本号的整数数组。*/int[] value();
}

配置属性类用于管理API版本

package com.github.artisan;import org.springframework.boot.context.properties.ConfigurationProperties;/*** 配置属性类用于管理API版本。* 通过前缀 "api-version" 绑定配置属性,以方便管理API版本。* @author Artisan*/@ConfigurationProperties(prefix = "api-version")
public class ApiVersionProperties {/*** API版本的前缀,用于定义版本的起始部分。*/private String prefix;/*** 获取API版本的前缀。** @return 返回API版本的前缀。*/public String getPrefix() {return prefix;}/*** 设置API版本的前缀。** @param prefix 设置API版本的前缀。*/public void setPrefix(String prefix) {this.prefix = prefix;}/*** API版本的后缀,用于定义版本的结束部分。*/private String suffix;/*** 获取API版本的后缀。** @return 返回API版本的后缀。*/public String getSuffix() {return suffix;}/*** 设置API版本的后缀。** @param suffix 设置API版本的后缀。*/public void setSuffix(String suffix) {this.suffix = suffix;}}

自动配置基于Spring MVC的API版本控制

package com.github.artisan;import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** ApiVersionAutoConfiguration类用于自动配置基于Spring MVC的API版本控制* 该类通过@EnableConfigurationProperties注解激活ApiVersionProperties配置类* 并且通过@Bean注解的方法创建和管理ApiVersionWebMvcRegistrations的单例对象* @author Artisan*/
@ConditionalOnWebApplication
@Configuration
@EnableConfigurationProperties(ApiVersionProperties.class)
public class ApiVersionAutoConfiguration {/*** 通过@Bean注解声明此方法将返回一个单例对象,由Spring容器管理* 该方法的目的是根据ApiVersionProperties配置生成ApiVersionWebMvcRegistrations实例* 这对于自动配置基于Spring MVC的API版本控制至关重要** @param apiVersionProperties 一个包含API版本控制相关配置的实体类*                             该参数用于初始化ApiVersionWebMvcRegistrations对象* @return 返回一个ApiVersionWebMvcRegistrations对象,用于注册和管理API版本控制相关的设置*/@Beanpublic ApiVersionWebMvcRegistrations apiVersionWebMvcRegistrations(ApiVersionProperties apiVersionProperties) {return new ApiVersionWebMvcRegistrations(apiVersionProperties);}
}

实现WebMvcRegistrations接口,用于自定义WebMvc的注册逻辑

package com.github.artisan;import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;/*** 实现WebMvcRegistrations接口,用于自定义WebMvc的注册逻辑* 主要用于API版本的请求映射配置**  @author Artisan*/
public class ApiVersionWebMvcRegistrations implements WebMvcRegistrations {/*** API版本配置属性* 用于获取API版本的前缀和后缀配置*/private ApiVersionProperties apiVersionProperties;/*** 构造函数,初始化API版本配置属性** @param apiVersionProperties API版本配置属性对象*/public ApiVersionWebMvcRegistrations(ApiVersionProperties apiVersionProperties) {this.apiVersionProperties = apiVersionProperties;}/*** 获取请求映射处理器映射对象* 此方法用于配置API版本的请求映射处理逻辑* 它根据配置决定映射路径的前缀和后缀** @return 返回一个初始化好的RequestMappingHandlerMapping对象,用于处理API版本的请求映射*/@Overridepublic RequestMappingHandlerMapping getRequestMappingHandlerMapping() {// 根据API版本配置的前缀情况决定使用默认前缀"v"还是用户配置的前缀// 如果未配置前缀,则默认使用"v",否则使用配置的前缀// 后缀直接使用配置的值return new ApiVersionRequestMappingHandlerMapping(StringUtils.isEmpty(apiVersionProperties.getPrefix()) ?"v" : apiVersionProperties.getPrefix(), apiVersionProperties.getSuffix());}}

扩展RequestMappingHandlerMapping的类,支持API版本路由

package com.github.artisan;import com.github.artisan.annotation.ApiVersion;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;import javax.validation.constraints.NotNull;
import java.lang.reflect.Method;/*** 一个扩展了RequestMappingHandlerMapping的类,支持API版本路由。* 它允许方法或类通过ApiVersion注解来支持版本控制。* @author Artisan*/
public class ApiVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {/*** API版本在URL中的前缀*/private final String prefix;/*** API版本在URL中的后缀,默认为空字符串,如果未提供则为空字符串*/private final String suffix;/*** 构造函数用于初始化API版本的前缀和后缀。** @param prefix API版本在URL中的前缀* @param suffix API版本在URL中的后缀,如果没有提供则默认为空字符串*/public ApiVersionRequestMappingHandlerMapping(String prefix, String suffix) {this.prefix = prefix;this.suffix = StringUtils.isEmpty(suffix) ? "" : suffix;}/*** 覆盖此方法以获取方法的路由信息,并支持基于ApiVersion注解的自定义条件。** @param method 需要获取路由信息的方法* @param handlerType 处理器类型* @return 方法的路由信息,包括基于API版本的自定义条件*/@Overrideprotected RequestMappingInfo getMappingForMethod(Method method, @NotNull Class<?> handlerType) {// 获取基本的路由信息RequestMappingInfo info = super.getMappingForMethod(method, handlerType);if (info == null) {return null;}// 检查方法是否使用了ApiVersion注解ApiVersion methodAnnotation = AnnotationUtils.findAnnotation(method, ApiVersion.class);if (methodAnnotation != null) {// 获取自定义方法条件RequestCondition<?> methodCondition = getCustomMethodCondition(method);// 创建基于API版本的信息并合并到基本信息中info = createApiVersionInfo(methodAnnotation, methodCondition).combine(info);} else {// 如果方法没有使用ApiVersion注解,则检查类是否使用了该注解ApiVersion typeAnnotation = AnnotationUtils.findAnnotation(handlerType, ApiVersion.class);if (typeAnnotation != null) {// 获取自定义类条件RequestCondition<?> typeCondition = getCustomTypeCondition(handlerType);// 创建基于API版本的信息并合并到基本信息中info = createApiVersionInfo(typeAnnotation, typeCondition).combine(info);}}return info;}/*** 根据ApiVersion注解创建路由信息。** 该方法解析ApiVersion注解的值,并根据这些值构建URL模式,* 然后结合自定义条件创建RequestMappingInfo对象,用于支持版本控制。** @param annotation ApiVersion注解实例,包含API版本信息。* @param customCondition 自定义条件,用于进一步细化请求映射。* @return 基于API版本的路由信息,用于将请求映射到特定版本的API处理方法上。*/private RequestMappingInfo createApiVersionInfo(ApiVersion annotation, RequestCondition<?> customCondition) {// 获取注解中指定的API版本数组int[] values = annotation.value();// 为每个API版本创建对应的URL模式String[] patterns = new String[values.length];for (int i = 0; i < values.length; i++) {// 构建URL前缀patterns[i] = prefix + values[i] + suffix;}// 使用构建的URL模式和其他请求条件创建并返回RequestMappingInfo对象return new RequestMappingInfo(new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),useSuffixPatternMatch(), useTrailingSlashMatch(), getFileExtensions()),new RequestMethodsRequestCondition(),new ParamsRequestCondition(),new HeadersRequestCondition(),new ConsumesRequestCondition(),new ProducesRequestCondition(),customCondition);}}

spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.github.artisan.ApiVersionAutoConfiguration

Test Code

无版本控制

package com.github.artisan.web;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author Artisan*/
@RestController
public class NoVersionController {@GetMapping("foo")public String foo() {return "不使用版本注解";}
}

多版本控制

package com.github.artisan.web;import com.github.artisan.annotation.ApiVersion;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author Artisan*/
@RestController
public class MultiVersionController {@GetMapping("foo3")@ApiVersion({1, 2})public String foo3() {return "注解支持多版本";}
}

v1

package com.github.artisan.web.v1;import com.github.artisan.annotation.ApiVersion;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author Artisan*/
@ApiVersion(1)
@RestController
public class TestController {@GetMapping("foo1")public String foo1() {return "方法没有注解, 使用类注解";}@GetMapping("foo2")@ApiVersion(1)public String foo2() {return "方法有注解, 使用方法注解";}}

v2

package com.github.artisan.web.v2;import com.github.artisan.annotation.ApiVersion;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @author Artisan*/
@ApiVersion(2)
@RestController
public class TestController {@GetMapping("foo1")public String foo1() {return "方法没有注解, 使用类注解";}@GetMapping("foo2")@ApiVersion(2)public String foo2() {return "方法有注解, 使用方法注解";}@GetMapping("foo4")@ApiVersion(1)public String foo4() {return "xxxx 方法有注解使用方法注解";}}

Test

整个swagger吧

 package com.github.artisan.swagger;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;@Configuration
@EnableSwagger2
public class SwaggerConfig {@Beanpublic Docket swaggerAll() {Docket docket = new Docket(DocumentationType.SWAGGER_2);return docket.apiInfo(apiInfo("all")).groupName("all").select().apis(RequestHandlerSelectors.basePackage("com.github.artisan.web")).paths(PathSelectors.any()).build().enable(true);}private ApiInfo apiInfo(String version) {return new ApiInfoBuilder().title("api-version-test doc").description("api-version-test").termsOfServiceUrl("").version(version).build();}@Beanpublic Docket swaggerV1() {return new Docket(DocumentationType.SWAGGER_2).groupName("v1").select().apis(RequestHandlerSelectors.basePackage("com.github.artisan.web")).paths(PathSelectors.regex("/v1.*")).build().apiInfo(apiInfo("v1"));}@Beanpublic Docket swaggerV2() {return new Docket(DocumentationType.SWAGGER_2).groupName("v2").select().apis(RequestHandlerSelectors.basePackage("com.github.artisan.web")).paths(PathSelectors.regex("/v2.*")).build().apiInfo(apiInfo("v2"));}}

访问: http://localhost:9090/swagger-ui.html

在这里插入图片描述

相关文章:

Spring Boot - 在Spring Boot中实现灵活的API版本控制(下)_ 封装场景启动器Starter

文章目录 Pre设计思路ApiVersion 功能特性使用示例配置示例 ProjectStarter Code自定义注解 ApiVersion配置属性类用于管理API版本自动配置基于Spring MVC的API版本控制实现WebMvcRegistrations接口&#xff0c;用于自定义WebMvc的注册逻辑扩展RequestMappingHandlerMapping的类…...

EasyCVR视频转码:T3视频平台不支持GB28181协议,应该如何实现与视频联网平台的对接与视频共享呢?

EasyCVR视频管理系统以其强大的拓展性、灵活的部署方式、高性能的视频能力和智能化的分析能力&#xff0c;为各行各业的视频监控需求提供了优秀的解决方案。 T3视频为公网HTTP-FLV或HLS格式的视频流&#xff0c;目前T3平台暂不支持国标GB28181协议&#xff0c;因此也无法直接接…...

Spring统一处理请求响应与异常

在web开发中&#xff0c;规范所有请求响应类型&#xff0c;不管是对前端数据处理&#xff0c;还是后端统一数据解析都是非常重要的。今天我们简单的方式实现如何实现这一效果 实现方式 定义响应类型 public class ResponseResult<T> {private static final String SUC…...

SqlServer公用表表达式 (CTE) WITH common_table_expression

SQL Server 中的公用表表达式&#xff08;Common Table Expressions&#xff0c;简称 CTE&#xff09;是一种临时命名的结果集&#xff0c;它在执行查询时存在&#xff0c;并且只在该查询执行期间有效。CTE 类似于一个临时的视图或者一个内嵌的查询&#xff0c;但它提供了更好的…...

常见中间件漏洞

Tomcat CVE-2017-12615 1.打开环境&#xff0c;抓包 2.切换请求头为 PUT&#xff0c;请求体添加木马&#xff0c;并在请求头添加木马文件名 1.jsp&#xff0c;后方需要以 / 分隔 3.连接 后台弱口令部署war包 1.打开环境,进入指点位置,账户密码均为 tomcat 2.在此处上传一句话…...

elasticsearch的学习(二):Java api操作elasticsearch

简介 使用Java api操作elasticsearch 创建maven项目 pom.xml文件 <?xml version"1.0" encoding"UTF-8"?><project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi…...

docker 部署 ElasticSearch;Kibana

ELasticSearch 创建网络 docker network create es-netES配合Kibana使用时需要组网&#xff0c;使两者运行在同一个网络下 命令 docker run -d \ --name es \ -e "discovery.typesingle-node" \ -v /usr/local/es/data:/usr/share/elasticsearch/data \ -v /usr/…...

k8s使用kustomize来部署应用

k8s使用kustomize来部署应用 本文主要是讲述kustomzie的基本用法。首先&#xff0c;我们说一下部署文件的目录结构。 ./ ├── base │ ├── deployment.yaml │ ├── kustomization.yaml │ └── service.yaml └── overlays└── dev├── kustomization.…...

基于开源FFmpeg和SDL2.0的音视频解码播放和存储系统的实现

目录 1、FFMPEG简介 2、SDL简介 3、视频播放器原理 4、FFMPEG多媒体编解码库 4.1、FFMPEG库 4.2、数据类型 4.3、解码 4.3.1、接口函数 4.3.2、解码流程 4.4、存储&#xff08;推送&#xff09; 4.4.1、接口函数 4.4.2、存储流程 5、SDL库介绍 5.1、数据结构 5.…...

保姆级教程,一文了解LVS

目录 一.什么是LVS tips: 二.优点&#xff08;为什么要用LVS&#xff1f;&#xff09; 三.作用 四.程序组成 五.LVS 负载均衡集群的类型 六.分布式内容 六.一.分布式存储 六.二.分布式计算 六.三.分布式常见应用 tips&#xff1a; 七.LVS 涉及相关的术语 八.LVS 负…...

【STM32】DMA数据转运(存储器到存储器)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 DMA简介 DMA时钟使能 DMA初始化 转运起始和终止的地址 转运方向 数据宽度 传输次数 转运触发方式 转运模式 通道优先级 开启DMA通道 DMA初始化框架 更改转运次数 DMA应用实例-…...

【Android】通过代码打开输入法

获取焦点 binding.editText.requestFocus()打开键盘 val imm getSystemService(InputMethodManager::class.java) imm.showSoftInput(binding.editText, InputMethodManager.SHOW_IMPLICIT)...

爬虫集群部署:Scrapyd 框架深度解析

&#x1f575;️‍♂️ 爬虫集群部署&#xff1a;Scrapyd 框架深度解析 &#x1f6e0;️ Scrapyd 环境部署 Scrapyd 是一个开源的 Python 爬虫框架&#xff0c;专为分布式爬虫设计。它允许用户在集群中调度和管理爬虫任务&#xff0c;并提供了简洁的 API 进行控制。以下是 Scr…...

pytorch GPU操作事例

>>> import torch >>> if_cuda torch.cuda.is_available() >>> print("if_cuda",if_cuda) if_cuda True >>> gpu_count torch.cuda.device_count() >>> print("gpu_count",gpu_count) gpu_count 8...

linux常见性能监控工具

常用命令top、free 、vmsata、iostat 、sar命令 具体更详细命令可以查看手册&#xff0c;这里只是简述方便找工具 整体性能top,内存看free&#xff0c;磁盘cpu内存历史数据可以vmsata、iostat 、sar、iotop top命令 交互&#xff1a;按P按照CPU排序&#xff0c;按M按照内存…...

C++ | Leetcode C++题解之第331题验证二叉树的前序序列化

题目&#xff1a; 题解&#xff1a; class Solution { public:bool isValidSerialization(string preorder) {int n preorder.length();int i 0;int slots 1;while (i < n) {if (slots 0) {return false;}if (preorder[i] ,) {i;} else if (preorder[i] #){slots--;i…...

【多模态处理】利用GPT逐一读取本地图片并生成描述并保存,支持崩溃后从最新进度恢复

【多模态处理】利用GPT逐一读取本地图片并生成描述&#xff0c;支持崩溃后从最新进度恢复题 代码功能&#xff1a;核心功能最后碎碎念 代码&#xff08;使用中转平台url&#xff09;&#xff1a;代码&#xff08;直接使用openai的key&#xff09; 注意 代码功能&#xff1a; 读…...

【rk3588】获取相机画面

需求&#xff1a;获取相机画面&#xff0c;并在连接HDMI线&#xff0c;在显示器上显示 查找设备 v4l2-ctl --list-devices H65 USB CAMERA: H65 USB CAMERA (usb-0000:00:14.0-1):/dev/video2/dev/video3播放视频 gst-launch-1.0 v4l2src device/dev/video22 ! video/x-ra…...

数据结构的基本概念

数据结构的基本概念 数据是什么&#xff1f; 数据 &#xff1a; 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所有能输入到计算机中并被计算机程序识别&#xff08;二进制0|1&#xff09;和处理的符号的集合。数据是计算机程序加工的原料。 早期计算机处理的…...

AI人工智能机器学习

AI人工智能 机器学习的类型(ML) 学习意味着通过学习或经验获得知识或技能。 基于此&#xff0c;我们可以定义机器学习(ML) 它被定义为计算机科学领域&#xff0c;更具体地说是人工智能的应用&#xff0c;它提供计算机系统学习数据和改进经验而不被明确编程的能力。 基本上&…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

DBAPI如何优雅的获取单条数据

API如何优雅的获取单条数据 案例一 对于查询类API&#xff0c;查询的是单条数据&#xff0c;比如根据主键ID查询用户信息&#xff0c;sql如下&#xff1a; select id, name, age from user where id #{id}API默认返回的数据格式是多条的&#xff0c;如下&#xff1a; {&qu…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

算法岗面试经验分享-大模型篇

文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer &#xff08;1&#xff09;资源 论文&a…...

Windows安装Miniconda

一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...