因为是前后端项目,需要前端的参与,所以一个好看的接口文档非常的重要
1、引入依赖
美化插件其中自带swagger的依赖了
XML
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-openapi3-spring-boot-starter</artifactId>
<version>4.3.0</version>
</dependency>
2、添加配置类
java
package com.study.question.config;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
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.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@ConditionalOnClass({OpenAPI.class})
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(prefix = "springdoc.api-docs", name = "enabled", havingValue = "true", matchIfMissing = false) // 设置为 false 时,禁用
public class SwaggerConfig implements Serializable {
// ========== 全局 OpenAPI 配置 ==========
@Bean
public OpenAPI createApi(SwaggerProperties properties) {
Map<String, SecurityScheme> securitySchemas = buildSecuritySchemes();
OpenAPI openAPI = new OpenAPI()
// 接口信息
.info(buildInfo(properties))
// 接口安全配置
.components(new Components().securitySchemes(securitySchemas));
securitySchemas.keySet().forEach(key -> openAPI.addSecurityItem(new SecurityRequirement().addList(key)));
return openAPI;
}
/**
* API 摘要信息
*/
private Info buildInfo(SwaggerProperties properties) {
return new Info()
.termsOfService("有问题请及时联系申智核微服务架构组:HeliosLy")
.title(properties.getTitle())
.description(properties.getDescription())
.version(properties.getVersion())
.contact(new Contact().name(properties.getAuthor()).url(properties.getUrl()).email(properties.getEmail()))
.license(new License().name(properties.getLicense()).url(properties.getLicenseUrl()));
}
/**
* 安全模式,这里配置通过请求头 Authorization 传递 token 参数
*/
private Map<String, SecurityScheme> buildSecuritySchemes() {
Map<String, SecurityScheme> securitySchemes = new HashMap<>();
SecurityScheme securityScheme = new SecurityScheme()
.type(SecurityScheme.Type.APIKEY) // 类型
.name(HttpHeaders.AUTHORIZATION) // 请求头的 name
.in(SecurityScheme.In.HEADER); // token 所在位置
securitySchemes.put(HttpHeaders.AUTHORIZATION, securityScheme);
return securitySchemes;
}
/**
* 自定义 OpenAPI 处理器
*/
@Bean
public OpenAPIService openApiBuilder(Optional<OpenAPI> openAPI,
SecurityService securityParser,
SpringDocConfigProperties springDocConfigProperties,
PropertyResolverUtils propertyResolverUtils,
Optional<List<OpenApiBuilderCustomizer>> openApiBuilderCustomizers,
Optional<List<ServerBaseUrlCustomizer>> serverBaseUrlCustomizers,
Optional<JavadocProvider> javadocProvider) {
return new OpenAPIService(openAPI, securityParser, springDocConfigProperties,
propertyResolverUtils, openApiBuilderCustomizers, serverBaseUrlCustomizers, javadocProvider);
}
}
属性类
java
package com.study.question.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import javax.validation.constraints.NotEmpty;
import java.io.Serializable;
scription:
*/
@Data
@EnableConfigurationProperties
@ConfigurationProperties("study.api-docs")
public class SwaggerProperties implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 是否启用
*/
@NotEmpty(message = "是否启用,不能为空")
private boolean enable=false;
/**
* 标题
*/
@NotEmpty(message = "标题不能为空")
private String title="在线API文档";
/**
* 描述
*/
@NotEmpty(message = "描述不能为空")
private String description="申智核在线API文档 http://www.shenzhihe.com.cn";
/**
* 作者
*/
@NotEmpty(message = "作者不能为空")
private String author="HeliosLy";
/**
* 版本
*/
@NotEmpty(message = "版本不能为空")
private String version="v1.0";
/**
* url
*/
@NotEmpty(message = "扫描的 package 不能为空")
private String url;
/**
* email
*/
@NotEmpty(message = "扫描的 email 不能为空")
private String email;
/**
* license
*/
private String license;
/**
* license-url
*/
private String licenseUrl;
}
配置类中添加
XML
study:
api-docs:
enable: true
title: 在线API文档
description: 在线API文档
version: 1.0
url: http://www.szh.com
email: adminly@dingtalk.com
license: MIT
license-url: https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSE
author: SYD
3、展示效果
地址访问:http://localhost:8080/doc.html


4、swagger使用
java
package com.study.question.model.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
/**
* @author: SYD
* @since: 2024-12-08
* @description:
*/
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_test_1")
@Schema(title="TTest1对象")
public class TTest1 implements Serializable {
private static final long serialVersionUID=1L;
@TableField("id")
private Long id;
@TableField("name")
@Schema(description="名称")
private String name;
}
java
package com.study.question.controller;
import com.study.question.model.entity.TTest1;
import com.study.question.model.pojo.R;
import com.study.question.service.QueueService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotNull;
@RequiredArgsConstructor
@Slf4j
@RestController
public class QueueController {
private final QueueService queueService;
@GetMapping("/testQueue")
@Operation(summary = "查询")
private void test(String name){
queueService.test(name);
}
@GetMapping("/add")
@Operation(summary = "添加/更新")
private TTest1 test(TTest1 tTest1){
return new TTest1();
}
@GetMapping("/get/{id}")
@Operation(summary = "查询详情")
public TTest1 getById(@NotNull(message = "id不能为null") @Schema(description = "唯一标志") @PathVariable("id") Integer id) {
return new TTest1();
}
}
5、bug解决
如果运行报错。Failed to start bean 'documentationPluginsBootstrapper
是因为springboot2.6.x后会有兼容问题,Springboot2.6以后将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser,导致出错。
所以要么降springboot的版本,要么yml文件加上一个配置。
XML
spring:
mvc:
pathmatch:
matching-strategy: ANT_PATH_MATCHER
配置类SwaggerConfig
加上
java
@Bean
public WebMvcEndpointHandlerMapping webEndpointServletHandlerMapping(WebEndpointsSupplier webEndpointsSupplier, ServletEndpointsSupplier servletEndpointsSupplier, ControllerEndpointsSupplier controllerEndpointsSupplier, EndpointMediaTypes endpointMediaTypes, CorsEndpointProperties corsProperties, WebEndpointProperties webEndpointProperties, Environment environment) {
List<ExposableEndpoint<?>> allEndpoints = new ArrayList();
Collection<ExposableWebEndpoint> webEndpoints = webEndpointsSupplier.getEndpoints();
allEndpoints.addAll(webEndpoints);
allEndpoints.addAll(servletEndpointsSupplier.getEndpoints());
allEndpoints.addAll(controllerEndpointsSupplier.getEndpoints());
String basePath = webEndpointProperties.getBasePath();
EndpointMapping endpointMapping = new EndpointMapping(basePath);
boolean shouldRegisterLinksMapping = this.shouldRegisterLinksMapping(webEndpointProperties, environment, basePath);
return new WebMvcEndpointHandlerMapping(endpointMapping, webEndpoints, endpointMediaTypes, corsProperties.toCorsConfiguration(), new EndpointLinksResolver(allEndpoints, basePath), shouldRegisterLinksMapping, null);
}
private boolean shouldRegisterLinksMapping(WebEndpointProperties webEndpointProperties, Environment environment, String basePath) {
return webEndpointProperties.getDiscovery().isEnabled() && (StringUtils.hasText(basePath) || ManagementPortType.get(environment).equals(ManagementPortType.DIFFERENT));
}
6.如果有鉴权请注意排除路径
XML
- /doc*/**
- /v3*/*/**
- /swagger-ui*/**