SpringBoot2.x 整合SpringDocJavadocknife4j实现无注解零入侵式接口文档

说明

基于 javadoc 无注解零入侵生成规范的 openapi 结构体。


文档工具使用

由于框架采用 openapi 行业规范 故市面上大部分的框架均支持 可自行选择
例如: apifox apipost postman torna knife4j 等 根据对应工具的文档接入即可


Swagger升级SpringDoc指南

常见功能如下 其他功能自行挖掘
注意: javadoc 只能替换基础功能 特殊功能还需要使用注解实现

swaggerspringdocjavadoc
@Api(name = “xxx”)@Tag(name = “xxx”)java类注释第一行
@Api(description= “xxx”)@Tag(description= “xxx”)java类注释
@ApiOperation@Operationjava方法注释
@ApiIgnore@Hidden
@ApiParam@Parameterjava方法@param参数注释
@ApiImplicitParam@Parameterjava方法@param参数注释
@ApiImplicitParams@Parameters多个@param参数注释
@ApiModel@Schemajava实体类注释
@ApiModelProperty@Schemajava属性注释
@ApiModelProperty(hidden = true)@Schema(accessMode = READ_ONLY)
@ApiResponse@ApiResponsejava方法@return返回值注释

Maven依赖

<dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-webmvc-core</artifactId><version>1.6.14</version>
</dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-javadoc</artifactId><version>1.6.14</version>
</dependency>

swagger 配置属性

package com.ruoyi.framework.config.properties;import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.ExternalDocumentation;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.tags.Tag;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.stereotype.Component;import java.util.List;/*** swagger 配置属性** @author Lion Li*/
@Data
@Component
@ConfigurationProperties(prefix = "springdoc")
public class SpringDocProperties {/*** 文档基本信息*/@NestedConfigurationPropertyprivate InfoProperties info = new InfoProperties();/*** 扩展文档地址*/@NestedConfigurationPropertyprivate ExternalDocumentation externalDocs;/*** 标签*/private List<Tag> tags = null;/*** 路径*/@NestedConfigurationPropertyprivate Paths paths = null;/*** 组件*/@NestedConfigurationPropertyprivate Components components = null;/*** <p>* 文档的基础属性信息* </p>** @see io.swagger.v3.oas.models.info.Info** 为了 springboot 自动生产配置提示信息,所以这里复制一个类出来*/@Datapublic static class InfoProperties {/*** 标题*/private String title = null;/*** 描述*/private String description = null;/*** 联系人信息*/@NestedConfigurationPropertyprivate Contact contact = null;/*** 许可证*/@NestedConfigurationPropertyprivate License license = null;/*** 版本*/private String version = null;}}

Swagger 文档配置

package com.ruoyi.framework.config;import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.config.properties.SpringDocProperties;
import com.ruoyi.framework.handler.OpenApiHandler;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import lombok.RequiredArgsConstructor;
import org.springdoc.core.*;
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
import org.springdoc.core.customizers.OpenApiCustomiser;
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springdoc.core.providers.JavadocProvider;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;/*** Swagger 文档配置** @author Lion Li*/
@RequiredArgsConstructor
@Configuration
@AutoConfigureBefore(SpringDocConfiguration.class)
@ConditionalOnProperty(name = "springdoc.api-docs.enabled", havingValue = "true", matchIfMissing = true)
public class SpringDocConfig {private final ServerProperties serverProperties;@Bean@ConditionalOnMissingBean(OpenAPI.class)public OpenAPI openApi(SpringDocProperties properties) {OpenAPI openApi = new OpenAPI();// 文档基本信息SpringDocProperties.InfoProperties infoProperties = properties.getInfo();Info info = convertInfo(infoProperties);openApi.info(info);// 扩展文档信息openApi.externalDocs(properties.getExternalDocs());openApi.tags(properties.getTags());openApi.paths(properties.getPaths());openApi.components(properties.getComponents());Set<String> keySet = properties.getComponents().getSecuritySchemes().keySet();List<SecurityRequirement> list = new ArrayList<>();SecurityRequirement securityRequirement = new SecurityRequirement();keySet.forEach(securityRequirement::addList);list.add(securityRequirement);openApi.security(list);return openApi;}private Info convertInfo(SpringDocProperties.InfoProperties infoProperties) {Info info = new Info();info.setTitle(infoProperties.getTitle());info.setDescription(infoProperties.getDescription());info.setContact(infoProperties.getContact());info.setLicense(infoProperties.getLicense());info.setVersion(infoProperties.getVersion());return info;}/*** 自定义 openapi 处理器*/@Beanpublic OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,SecurityService securityParser,SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers,Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomisers, Optional<JavadocProvider> javadocProvider) {return new OpenApiHandler(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomisers, serverBaseUrlCustomisers, javadocProvider);}/*** 对已经生成好的 OpenApi 进行自定义操作*/@Beanpublic OpenApiCustomiser openApiCustomiser() {String contextPath = serverProperties.getServlet().getContextPath();String finalContextPath;if (StringUtils.isBlank(contextPath) || "/".equals(contextPath)) {finalContextPath = "";} else {finalContextPath = contextPath;}// 对所有路径增加前置上下文路径return openApi -> {Paths oldPaths = openApi.getPaths();if (oldPaths instanceof PlusPaths) {return;}PlusPaths newPaths = new PlusPaths();oldPaths.forEach((k,v) -> newPaths.addPathItem(finalContextPath + k, v));openApi.setPaths(newPaths);};}/*** 单独使用一个类便于判断 解决springdoc路径拼接重复问题** @author Lion Li*/static class PlusPaths extends Paths {public PlusPaths() {super();}}}

自定义 openapi 处理器

package com.ruoyi.framework.handler;import cn.hutool.core.io.IoUtil;
import io.swagger.v3.core.jackson.TypeNameResolver;
import io.swagger.v3.core.util.AnnotationsUtils;
import io.swagger.v3.oas.annotations.tags.Tags;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springdoc.core.OpenAPIService;
import org.springdoc.core.PropertyResolverUtils;
import org.springdoc.core.SecurityService;
import org.springdoc.core.SpringDocConfigProperties;
import org.springdoc.core.customizers.OpenApiBuilderCustomizer;
import org.springdoc.core.customizers.ServerBaseUrlCustomizer;
import org.springdoc.core.providers.JavadocProvider;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;import java.io.StringReader;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;/*** 自定义 openapi 处理器* 对源码功能进行修改 增强使用*/
@SuppressWarnings("all")
public class OpenApiHandler extends OpenAPIService {/*** The constant LOGGER.*/private static final Logger LOGGER = LoggerFactory.getLogger(OpenAPIService.class);/*** The Context.*/private ApplicationContext context;/*** The Security parser.*/private final SecurityService securityParser;/*** The Mappings map.*/private final Map<String, Object> mappingsMap = new HashMap<>();/*** The Springdoc tags.*/private final Map<HandlerMethod, io.swagger.v3.oas.models.tags.Tag> springdocTags = new HashMap<>();/*** The Open api builder customisers.*/private final Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomisers;/*** The server base URL customisers.*/private final Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers;/*** The Spring doc config properties.*/private final SpringDocConfigProperties springDocConfigProperties;/*** The Open api.*/private OpenAPI openAPI;/*** The Cached open api map.*/private final Map<String, OpenAPI> cachedOpenAPI = new HashMap<>();/*** The Is servers present.*/private boolean isServersPresent;/*** The Server base url.*/private String serverBaseUrl;/*** The Property resolver utils.*/private final PropertyResolverUtils propertyResolverUtils;/*** The javadoc provider.*/private final Optional<JavadocProvider> javadocProvider;/*** The Basic error controller.*/private static Class<?> basicErrorController;static {try {//spring-boot 2basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController");} catch (ClassNotFoundException e) {//spring-boot 1try {basicErrorController = Class.forName("org.springframework.boot.autoconfigure.web.BasicErrorController");} catch (ClassNotFoundException classNotFoundException) {//Basic error controller class not foundLOGGER.trace(classNotFoundException.getMessage());}}}/*** Instantiates a new Open api builder.** @param openAPI                   the open api* @param securityParser            the security parser* @param springDocConfigProperties the spring doc config properties* @param propertyResolverUtils     the property resolver utils* @param openApiBuilderCustomizers the open api builder customisers* @param serverBaseUrlCustomizers  the server base url customizers* @param javadocProvider           the javadoc provider*/public OpenApiHandler(Optional<OpenAPI> openAPI, SecurityService securityParser,SpringDocConfigProperties springDocConfigProperties, PropertyResolverUtils propertyResolverUtils,Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,Optional<JavadocProvider> javadocProvider) {super(openAPI, securityParser, springDocConfigProperties, propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);if (openAPI.isPresent()) {this.openAPI = openAPI.get();if (this.openAPI.getComponents() == null)this.openAPI.setComponents(new Components());if (this.openAPI.getPaths() == null)this.openAPI.setPaths(new Paths());if (!CollectionUtils.isEmpty(this.openAPI.getServers()))this.isServersPresent = true;}this.propertyResolverUtils = propertyResolverUtils;this.securityParser = securityParser;this.springDocConfigProperties = springDocConfigProperties;this.openApiBuilderCustomisers = openApiBuilderCustomizers;this.serverBaseUrlCustomizers = serverBaseUrlCustomizers;this.javadocProvider = javadocProvider;if (springDocConfigProperties.isUseFqn())TypeNameResolver.std.setUseFqn(true);}@Overridepublic Operation buildTags(HandlerMethod handlerMethod, Operation operation, OpenAPI openAPI, Locale locale) {Set<Tag> tags = new HashSet<>();Set<String> tagsStr = new HashSet<>();buildTagsFromMethod(handlerMethod.getMethod(), tags, tagsStr, locale);buildTagsFromClass(handlerMethod.getBeanType(), tags, tagsStr, locale);if (!CollectionUtils.isEmpty(tagsStr))tagsStr = tagsStr.stream().map(str -> propertyResolverUtils.resolve(str, locale)).collect(Collectors.toSet());if (springdocTags.containsKey(handlerMethod)) {io.swagger.v3.oas.models.tags.Tag tag = springdocTags.get(handlerMethod);tagsStr.add(tag.getName());if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {openAPI.addTagsItem(tag);}}if (!CollectionUtils.isEmpty(tagsStr)) {if (CollectionUtils.isEmpty(operation.getTags()))operation.setTags(new ArrayList<>(tagsStr));else {Set<String> operationTagsSet = new HashSet<>(operation.getTags());operationTagsSet.addAll(tagsStr);operation.getTags().clear();operation.getTags().addAll(operationTagsSet);}}if (isAutoTagClasses(operation)) {if (javadocProvider.isPresent()) {String description = javadocProvider.get().getClassJavadoc(handlerMethod.getBeanType());if (StringUtils.isNotBlank(description)) {io.swagger.v3.oas.models.tags.Tag tag = new io.swagger.v3.oas.models.tags.Tag();// 自定义部分 修改使用java注释当tag名List<String> list = IoUtil.readLines(new StringReader(description), new ArrayList<>());// tag.setName(tagAutoName);tag.setName(list.get(0));operation.addTagsItem(list.get(0));tag.setDescription(description);if (openAPI.getTags() == null || !openAPI.getTags().contains(tag)) {openAPI.addTagsItem(tag);}}} else {String tagAutoName = splitCamelCase(handlerMethod.getBeanType().getSimpleName());operation.addTagsItem(tagAutoName);}}if (!CollectionUtils.isEmpty(tags)) {// Existing tagsList<io.swagger.v3.oas.models.tags.Tag> openApiTags = openAPI.getTags();if (!CollectionUtils.isEmpty(openApiTags))tags.addAll(openApiTags);openAPI.setTags(new ArrayList<>(tags));}// Handle SecurityRequirement at operation levelio.swagger.v3.oas.annotations.security.SecurityRequirement[] securityRequirements = securityParser.getSecurityRequirements(handlerMethod);if (securityRequirements != null) {if (securityRequirements.length == 0)operation.setSecurity(Collections.emptyList());elsesecurityParser.buildSecurityRequirement(securityRequirements, operation);}return operation;}private void buildTagsFromMethod(Method method, Set<io.swagger.v3.oas.models.tags.Tag> tags, Set<String> tagsStr, Locale locale) {// method tagsSet<Tags> tagsSet = AnnotatedElementUtils.findAllMergedAnnotations(method, Tags.class);Set<io.swagger.v3.oas.annotations.tags.Tag> methodTags = tagsSet.stream().flatMap(x -> Stream.of(x.value())).collect(Collectors.toSet());methodTags.addAll(AnnotatedElementUtils.findAllMergedAnnotations(method, io.swagger.v3.oas.annotations.tags.Tag.class));if (!CollectionUtils.isEmpty(methodTags)) {tagsStr.addAll(methodTags.stream().map(tag -> propertyResolverUtils.resolve(tag.name(), locale)).collect(Collectors.toSet()));List<io.swagger.v3.oas.annotations.tags.Tag> allTags = new ArrayList<>(methodTags);addTags(allTags, tags, locale);}}private void addTags(List<io.swagger.v3.oas.annotations.tags.Tag> sourceTags, Set<io.swagger.v3.oas.models.tags.Tag> tags, Locale locale) {Optional<Set<io.swagger.v3.oas.models.tags.Tag>> optionalTagSet = AnnotationsUtils.getTags(sourceTags.toArray(new io.swagger.v3.oas.annotations.tags.Tag[0]), true);optionalTagSet.ifPresent(tagsSet -> {tagsSet.forEach(tag -> {tag.name(propertyResolverUtils.resolve(tag.getName(), locale));tag.description(propertyResolverUtils.resolve(tag.getDescription(), locale));if (tags.stream().noneMatch(t -> t.getName().equals(tag.getName())))tags.add(tag);});});}}

配置application.yml 属性

springdoc-openai 配置:

# springdoc-openai 配置
springdoc:api-docs:# 是否开启接口文档enabled: true# OpenAPI文档的路径path: /v3/api-docsswagger-ui:# swagger-ui路径path: /swagger-ui.html# 持久化认证数据persistAuthorization: trueinfo:# 标题title: '标题:SpringDoc后台管理系统_接口文档'# 描述description: '描述:用于管理集团旗下公司的人员信息,具体包括XXX,XXX模块...'# 版本version: '版本号: 1.0.0'# 作者信息contact:name: lczemail: 1926585708@qq.comurl: https://gitee.com/hsqyzcomponents:# 鉴权方式配置security-schemes:apiKey:type: APIKEYin: HEADERname: Authorization# 分组配置group-configs:- group: SpringDoc项目模块接口文档packages-to-scan: com.hsqyz.spring_doc

配置Java编译器插件

主要看configuration配置这块内容:

			<plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.9.0</version><configuration><source>${java.version}</source><target>${java.version}</target><encoding>${project.build.sourceEncoding}</encoding><annotationProcessorPaths><path><groupId>com.github.therapi</groupId><artifactId>therapi-runtime-javadoc-scribe</artifactId><version>0.15.0</version></path><path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></path><path><groupId>org.springframework.boot</groupId><artifactId>spring-boot-configuration-processor</artifactId><version>${springboot.version}</version></path></annotationProcessorPaths></configuration></plugin>

详细解释如下:

  1. <source>${java.version}</source> 和 <target>${java.version}</target>:设置Java源代码和目标字节码的版本。${java.version} 是一个占位符,表示从项目的属性中读取Java版本号。这意味着项目源代码使用的语言特性和编译后的class文件所对应的JVM版本是一致的。
  2. <encoding>${project.build.sourceEncoding}</encoding>:设置源代码文件的编码格式,${project.build.sourceEncoding} 表示从项目全局配置中读取编码格式。
  3. <annotationProcessorPaths>:这部分配置了注解处理器的路径,注解处理器是一种在编译阶段运行的工具,能够处理源代码中的特定注解,生成额外的类、资源文件或者其他辅助信息。
    • <path> 内的 、 和 分别指定了注解处理器的Maven坐标,即在Maven仓库中该注解处理器的组织ID、项目ID和版本号。
    • com.github.therapi:therapi-runtime-javadoc-scribe:这是一个用于提取Java方法上的Javadoc注解并在运行时使用的注解处理器。
    • org.projectlombok:lombok:Lombok是一个简化Java开发的工具,提供了众多注解如@Data@NoArgsConstructor等,注解处理器会在编译时自动插入getter/setter、equals/hashCode/toString等方法。
    • org.springframework.boot:spring-boot-configuration-processor:Spring Boot的配置处理器,用于在编译时生成关于@ConfigurationProperties注解类的元数据,使得IDE能提供更好的代码提示和验证。

总之,这段配置确保了Java源代码按指定的版本和编码进行编译,并在编译过程中利用指定的注解处理器生成额外有用的代码和元数据,提升开发效率和应用的功能性。


JavaDoc 元数据

配置好之后再次运行项目,查看target目录下会生成了JavaDoc的元数据


示例接口

/*** 用户*/
@Slf4j
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class TestController {/*** 添加用户** @param user 用户信息对象* @return 结果集*/@PostMapping("/insert")public R insert(@RequestBody User user) {System.out.println("添加用户:" + user);return R.ok();}/*** 更新用户** @param user 用户信息对象* @return 结果集*/@PostMapping("/update")public R update(@RequestBody User user) {System.out.println("更新用户:" + user);return R.ok();}}

准备好接口之后就可以开始准备启动了。

查看 OpenApi 接口

根据项目内所有文档组完成所有数据源创建(拉取后端openapi结构体)
数据源URL格式 http://后端ip:端口/v3/api-docs/组名
项目内所需:

  • http://localhost:8080/v3/api-docs/1.演示模块
  • http://localhost:8080/v3/api-docs/2.通用模块
  • http://localhost:8080/v3/api-docs/3.系统模块
  • http://localhost:8080/v3/api-docs/4.代码生成模块

也可不分组统一导入: http://localhost:8080/v3/api-docs

导入Apifox

打开Apifox选择导入项目,粘贴接口文档地址

点击提交,设置项目名称

导入成功

点击确定导入

查看接口


整合 knife4j

如果想让项目自带可视化接口调试界面,可以选择引入 knife4j 基于openapi3的依赖

<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</artifactId><version>4.4.0</version>
</dependency>

然后刷新依赖重启项目,访问:http://127.0.0.1:8080/doc.html

查看接口列表

查看数据模型

参考资料

  • 本教程参考自疯狂的狮子大佬开发的若依Plus版教程

教程结束!

散会!

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

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

相关文章

颠覆传统:Web3如何塑造未来的数字经济

引言 近年来&#xff0c;随着数字化时代的到来&#xff0c;互联网已经成为人们生活中不可或缺的一部分。然而&#xff0c;随着技术的不断发展和社会的不断变迁&#xff0c;传统的Web2模式逐渐显露出一些弊端&#xff0c;如数据垄断、隐私泄露等问题&#xff0c;这促使人们寻求…

ArmSoM-Sige RK3588开发板产品简介

让我们在 5 分钟内了解 Sige7。 简介​ ArmSoM-Sige7采用Rockchip RK3588新一代旗舰级八核64位处理器&#xff0c;主频高达2.4GHz&#xff0c;6 TOPS算力NPU&#xff0c;最大可配32GB大内存。支持8K视频编解码&#xff0c;拥有丰富的接口&#xff0c;支持双2.5G网口、WiFi6 &…

仿《Egouz国外网址大全》源码 SEO网站大全 外国网址导航网站模板 手机版+采集

(购买本专栏可免费下载栏目内所有资源不受限制,持续发布中,需要注意的是,本专栏为批量下载专用,并无法保证某款源码或者插件绝对可用,介意不要购买!购买本专栏住如有什么源码需要,可向博主私信,第二天即可发布!博主有几万资源) 源码介绍: 基于帝国CMS7.5核心开发仿…

K8S--SpringCloud应用整合Nacos实战

原文网址&#xff1a;K8S--SpringCloud应用整合Nacos实战-CSDN博客 简介 本文介绍K8S部署SpringCloud应用整合Nacos实战。 本文是将原来的SpringCloud项目&#xff08;闪速优选&#xff09;迁移到K8S上&#xff0c;一行代码都不需要改动。用K8S运行Nacos、Gateway、SpringCl…

每日一题 --- 设计链表[力扣][Go]

设计链表 题目&#xff1a;707. 设计链表 你可以选择使用单链表或者双链表&#xff0c;设计并实现自己的链表。 单链表中的节点应该具备两个属性&#xff1a;val 和 next 。val 是当前节点的值&#xff0c;next 是指向下一个节点的指针/引用。 如果是双向链表&#xff0c;则…

Codeforces Round 930 (Div. 2)(A,B,C,D)

比赛链接 C是个交互&#xff0c;D是个前缀和加二分。D还是很难写的。 A. Shuffle Party 题意&#xff1a; 您将得到一个数组 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1​,a2​,…,an​ 。最初&#xff0c;每个 1 ≤ i ≤ n 1 \le i \le n 1≤i≤n 对应 a i i a_ii…

【Linux】从零认识进程 — 中下篇

送给大家一句话&#xff1a; 人一切的痛苦&#xff0c;本质上都是对自己无能的愤怒。而自律&#xff0c;恰恰是解决人生痛苦的根本途径。—— 王小波 从零认识进程 1 进程优先级1.1 什么是优先级1.2 为什么要有优先级1.3 Linux优先级的特点 && 查看方式1.4 其他概念 2…

目标检测的指标评估

目标检测模型的评价指标主要用于衡量模型的性能&#xff0c;特别是它在定位和识别目标方面的准确性。以下是一些常见的评价指标&#xff1a; 1. 精确度 (Precision): 表示检测到的目标中&#xff0c;正确检测到的目标所占的比例。精确度高意味着模型产生的误报&#xff08;错误…

通过jsDelivr实现Github的图床CDN加速

最近小伙伴们是否发现访问我的个人博客http://xiejava.ishareread.com/图片显示特别快了&#xff1f; 我的博客的图片是放在github上的&#xff0c;众所周知的原因&#xff0c;github访问不是很快&#xff0c;尤其是hexo博客用github做图床经常图片刷不出来。一直想换图床&…

Oracle 使用OGG(Oracle GoldenGate) 实现19c PDB与MySQL5.7 数据同步

OGG 是一种基于日志的结构化数据复制软件&#xff0c;它通过解析源数据库在线日志或归档日志获得数据的增删改变化。 OracleMysqlIP address192.168.80.100192.168.80.16DB version19.2.05.7host nametempmysql OS version&#xff1a; CentOS 7.9 一&#xff0c;Oracle 服务…

机器学习基础知识面经(个人记录)

朴素贝叶斯 特征为理想状态下的独立同分布&#xff0c;作为机器学习的重要基石和工具 由贝叶斯公式推导而来 是后验概率&#xff1a;在B发生的条件下A发生的概率。 是似然概率: 在 发生的条件下 发生的概率。 是先验概率: 发生的概率&#xff0c;而不考虑 的影响。 是…

静态综合实验

一.搭建拓扑结构 1.根据拓扑结构可以把网段分成14个网段&#xff0c;根据192.168.1.0/24可以划分出ip地址和环回地址 其中环回r1分别是 192.168.1.32/27 192.168.1.32/28 192.168.1.48/28 2.划分完后如图&#xff1a; 二.配置IP地址 注意&#xff1a;为了避免错误&#…

vulnhub prime1通关

目录 环境安装 1.信息收集 收集IP 端口扫描 目录扫描 目录文件扫描 查找参数 打Boss 远程文件读取 木马文件写入 权限提升 方法一 解锁密钥 方法二&#xff1a; linux内核漏洞提权 总结 环境安装 Kali2021.4及其prime靶机 靶机安装&#xff1a;Prime: 1 ~ Vul…

今天聊聊新零售

一、什么是新零售&#xff1f; 2016年&#xff0c;在杭州举行的“云栖大会”上&#xff0c;马云发表了讲话&#xff0c;首次提出了“新零售”这一概念。 1.1 新零售概念 新零售&#xff0c;英文是New Retailing&#xff0c;新零售是对人货场的重构。人是消费者、销售人员、…

Python 从0开始 一步步基于Django创建项目(3)使用Admin site管理数据模型

本文内容建立在《Python 从0开始 一步步基于Django创建项目&#xff08;2&#xff09;创建应用程序&数据模型》的基础上。 Django提供的admin site&#xff0c;使得网站管理员&#xff0c;能够轻松管理网站的数据模型。 本文首先创建‘管理员账户’&#xff0c;即超级用户…

Linux:Jenkins全自动持续集成持续部署(3)

在上一章部署好了之后&#xff0c;还需要点击一下才能进行部署&#xff0c;本章的效果是&#xff1a;当gitlab上的代码发生了变化后&#xff0c;我们不需要做任何事情不需要去点击构建按钮&#xff0c;Jenkins直接自动检测变化&#xff0c;然后自动去集成部署Linux&#xff1a;…

利用免费 GPU 部署体验大型语言模型推理框架 vLLM

vLLM简介 vLLM 是一个快速且易于使用的 LLM&#xff08;大型语言模型&#xff09;推理和服务库。 vLLM 之所以快速&#xff0c;是因为&#xff1a; 最先进的服务吞吐量 通过 PagedAttention 高效管理注意力键和值内存 连续批处理传入请求 使用 CUDA/HIP 图快速模型执行 量…

C#,图论与图算法,用于检查给定图是否为欧拉图(Eulerian Graph)的算法与源程序

1 欧拉图 欧拉图是指通过图(无向图或有向图)中所有边且每边仅通过一次通路, 相应的回路称为欧拉回路。具有欧拉回路的图称为欧拉图(Euler Graph), 具有欧拉通路而无欧拉回路的图称为半欧拉图。 对欧拉图的一个现代扩展是蜘蛛图,它向欧拉图增加了可以连接的存在点。 这给…

vue3对openlayers使用(加高德,天地图图层)

OpenLayers认识 WebGIS四大框架&#xff1a; Leaflet、OpenLayers、Mapbox、Cesium OpenLayers 是一个强大的开源 JavaScript 地图库&#xff0c;专注于提供可嵌入网页的交互式地图体验。作为一款地理信息系统&#xff08;GIS&#xff09;的前端开发工具&#xff0c;OpenLaye…

docker 和K8S知识分享

docker知识&#xff1a; 比如写了个项目&#xff0c;并且在本地调试没有任务问题&#xff0c;这时候你想在另外一台电脑或者服务器运行&#xff0c;那么你需要在另外一台电脑或者服务器配置相同的软件&#xff0c;比如数据库&#xff0c;web服务器&#xff0c;必要的插件和库等…