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.hqwc.cn/news/563196.html

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

相关文章

网络安全实训Day9

写在前面 访问控制和防火墙桌面端安全检测与防御 网络安全实训-网络安全技术 网络安全概述 访问控制 定义&#xff1a;通过定义策略和规则来限制哪些流量能经过防火墙&#xff0c;哪些流量不能通过。本质是包过滤 可以匹配的元素 IP协议版本 源区域和目的区域 源IP地址和目…

Nature:“量子龙卷风”首次模拟黑洞

科学家们在超流体氦气中首次创造出了一个巨大的“量子漩涡”&#xff08;quantum vortex&#xff09;&#xff0c;用以模拟黑洞。这一成就不仅使他们能够更加细致地观察模拟黑洞的行为&#xff0c;还能探究其与周围环境的交互作用。 诺丁汉大学的研究团队与伦敦国王学院和纽卡斯…

生产力工具|安装更新R软件(R、studio)

内容介绍&#xff1a; 安装R软件&#xff1a; 下载 R X64 3.5.1: 访问官方R网站 https://cran.r-project.org/。选择适合Windows版本的安装包。将安装包下载到您的计算机。 本地安装: 运行下载的“R-3.5.1-win.exe”文件。按照安装向导&#xff0c;选择安装路径&#xff0c;取消…

适配器模式与桥接模式-灵活应对变化的两种设计策略大比拼

​&#x1f308; 个人主页&#xff1a;danci_ &#x1f525; 系列专栏&#xff1a;《设计模式》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自&#xff1a;设计模式深度解析&#xff1a;适配器模式与桥接模式-灵活应对变…

Uibot6.0 (RPA财务机器人师资培训第1天 )RPA+AI、RPA基础语法

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981(本博客中会有部分课程ppt截屏,如有侵权请及请及时与小北我取得联系~&#xff09; 紧接着小北之前的几篇博客&#xff0c;友友们我们即将开展新课的学习~…

JVM快速入门(1)JVM体系结构、运行时数据区、类加载器、线程共享和独享、分区、Java对象实例化

5.1 JVM体系结构 线程独占区-程序计数器&#xff08;Program Counter Register&#xff09; 程序计数器是一块较小的内存空间&#xff0c;它可以看做是当前线程所执行的字节码的行号指示器&#xff1b;在虚拟机的概念模型里&#xff0c;字节码解释器工作时就是通过改变这个计数…

C语言——字符函数

前言 字符函数是C语言中专门用来处理字符的函数&#xff0c;再C语言中&#xff0c;我们有时需要大量的处理有关字符的问题&#xff0c;所以字符函数就由此应运而生&#xff0c;接下来我来为大家简单介绍一下字符函数。 一.字符分类函数 函数如果它的参数满足下列条件就返回真…

Unity 中 苹果眼镜开发入口

1. 文档介绍了Unity对Apple新操作系统visionOS的支持。 2. Unity提供了完善的文档、模板和支持,帮助开发者快速为visionOS开发应用。 3. Unity的跨平台框架AR Foundation和XR Interaction Toolkit可以帮助现有移动和XR应用无缝迁移到visionOS。 4. 在visionOS上,可以利用Uni…

数据库之MongoDB应用与开发

MongoDB应用与开发 1. MongoDB安装 l 官网下载安装介质&#xff1a; Try MongoDB Atlas Products | MongoDB 选择对应版本 修改环境变量 vi /etc/profile export MONGODB_HOME/home/lijin/mongodb export PATH P A T H : PATH: PATH:MONGODB_HOME/bin source /etc/profile …

行政工作常用表格

企业管制制度大全https://www.chuandao100.com/279.html

深度学习 (正则化 权重衰减解决过拟合 欠拟合)

权重衰减&#xff1a; 深度学习中的权重衰减&#xff08;weight decay&#xff09;是一种正则化技术&#xff0c;用于防止过拟合。它通过对模型的损失函数添加一个正则化项&#xff0c;来惩罚模型的权重参数。 在权重衰减中&#xff0c;模型的损失函数会由原来的仅考虑预测误差…

CSS3 中的盒模型:标准与IE盒模型的差异

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…