整合swagger,以及Knife4j优化界面
因为是前后端项目,需要前端的参与,所以一个好看的接口文档非常的重要
1、引入依赖
美化插件其中自带swagger的依赖了
<dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-openapi3-spring-boot-starter</artifactId><version>4.3.0</version></dependency>
2、添加配置类
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 配置 ==========@Beanpublic 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 处理器*/@Beanpublic 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);}}
属性类
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;}
配置类中添加
study:api-docs:enable: truetitle: 在线API文档description: 在线API文档version: 1.0url: http://www.szh.comemail: adminly@dingtalk.comlicense: MITlicense-url: https://gitee.com/zhijiantianya/ruoyi-vue-pro/blob/master/LICENSEauthor: SYD
3、展示效果
地址访问:http://localhost:8080/doc.html
4、swagger使用
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;}
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文件加上一个配置。
spring:mvc:pathmatch:matching-strategy: ANT_PATH_MATCHER
配置类SwaggerConfig
加上
@Beanpublic 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.如果有鉴权请注意排除路径
- /doc*/**- /v3*/*/**- /swagger-ui*/**