1. pom文件引用
```yml
<dependency> <groupId>com.github.xiaoymin</groupId> <artifactId>knife4j-spring-boot-starter</artifactId> <version>2.0.9</version> </dependency>
```
2. 初始化后对应的配置类
```java
import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; /** * Knife4jConfig <br> * * @date: 2021/11/26 <br> * @author: llxiao <br> * @since: 1.0 <br> * @version: 1.0 <br> */ @Data @Configuration @ConfigurationProperties(prefix = "xxx.knife.swagger") public class Knife4jConfig { private String version; private String basePackage; private String title; private String description; private String contactName; private Boolean enabled; private String termsOfServiceUrl = "www.baidu.co"; }
```
对应的配置
```yml
xxx: knife: swagger: version: 1.0 basePackage: xxx.xxx.controller title: xxxAPI文档 description: 我是描述 contactName: 我是作者 enabled: false
```
3. 初始化
```java
import java.util.ArrayList; import java.util.List; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.bind.annotation.RequestMethod; import springfox.documentation.builders.ApiInfoBuilder; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.builders.ResponseMessageBuilder; import springfox.documentation.schema.ModelRef; import springfox.documentation.service.Parameter; import springfox.documentation.service.ResponseMessage; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; /** * Knife4jConfiguration <br> * * @date: 2021/11/26 <br> * @author: llxiao <br> * @since: 1.0 <br> * @version: 1.0 <br> */ @Configuration @EnableSwagger2WebMvc public class Knife4jConfiguration { @Bean(value = "defaultApi2") public Docket defaultApi2(Knife4jConfig knife4jConfig) { // 自定义异常定义,可以从枚举类获取 List<ResponseMessage> responseMessageList = new ArrayList<>(); for (MchMpExceptionCode value : MchMpExceptionCode.values()) { ResponseMessage build = new ResponseMessageBuilder().code(value.getCode()).message(value.getMsg()).responseModel( new ModelRef(value.getMsg())).build(); responseMessageList.add(build); } // 自定义header List<Parameter> parameters = new ArrayList<>(); parameters.add(new ParameterBuilder() .name("Auth-Token") .description("认证token,仅作用于/auth/api开头的接口") .modelRef(new ModelRef("string")) .parameterType("header") .required(false) .build()); return new Docket(DocumentationType.SWAGGER_2) // 自定义错误码 .globalResponseMessage(RequestMethod.GET, responseMessageList) .globalResponseMessage(RequestMethod.POST, responseMessageList) .globalResponseMessage(RequestMethod.PUT, responseMessageList) .globalResponseMessage(RequestMethod.DELETE, responseMessageList) // header参数定义 .globalOperationParameters(parameters) .apiInfo(new ApiInfoBuilder() .title(knife4jConfig.getTitle()) .description(knife4jConfig.getDescription()) .termsOfServiceUrl(knife4jConfig.getTermsOfServiceUrl()) .contact(knife4jConfig.getContactName()) .version(knife4jConfig.getVersion()) .build()) //分组名称 .groupName(knife4jConfig.getVersion()) .select() //这里指定Controller扫描包路径 .apis(RequestHandlerSelectors.basePackage(knife4jConfig.getBasePackage())) .paths(PathSelectors.any()) .build(); } }
```
4. 展示效果
访问:https://localhost:8080/doc.html
5. 相关注解使用
5.1 controller 类注解 ``@Api(tags = "用户服务")``
5.2 对应rest api 注解 ``@Api(tags = "用户服务")``
5.3 参数model注解 ``@ApiModel(value = "用户注册", description = "用户登录注册传入对象")``
5.4 参数model属性注解 `` @ApiModelProperty(value = "收费管家公众号的用户openId", required = true)``
6. 网关聚合
6.1 聚合各个服务的swagger接口
```java
import cn.hutool.core.collection.CollectionUtil; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.route.RouteDefinition; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.stereotype.Component; import reactor.core.publisher.Flux; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.SwaggerResourcesProvider; /** * 聚合各个服务的swagger接口 <br> * * TODO 由于网关路由有配置/**转pcs,所以访问时直接会访问pcs的 doc.html * * @date: 2021/7/17 <br> * @author: llxiao <br> * @since: 1.0 <br> * @version: 1.0 <br> */ @Component public class GatewaySwaggerResourceProvider implements SwaggerResourcesProvider { /** * swagger2默认的url后缀 */ private static final String SWAGGER2URL = "/v2/api-docs"; /** * 网关路由 */ private final RouteLocator routeLocator; /** * 网关应用名称 */ @Value("${spring.application.name}") private String self; /** * */ ///@Autowired private RouteDefinitionRepository routeDefinitionRepository; @Autowired public PaySwaggerResourceProvider(RouteLocator routeLocator) { this.routeLocator = routeLocator; } @Override public List<SwaggerResource> get() { return getSwaggerResourcesByFilter(); ///return getSwaggerResourcesKnife4j(); } /** * 网关动态路由获取方式 * * @return java.util.List<springfox.documentation.swagger.web.SwaggerResource> * @author llxiao * @date 2021/9/23 11:06 **/ private List<SwaggerResource> getSwaggerResourcesKnife4j() { List<SwaggerResource> resourceList = new ArrayList<>(); // 动态网关方式获取路由 nacos动态网关 Flux<RouteDefinition> routeDefinitions = routeDefinitionRepository.getRouteDefinitions(); routeDefinitions.subscribe(routeDefinition -> { List<PredicateDefinition> predicates = routeDefinition.getPredicates(); if (CollectionUtil.isNotEmpty(predicates)) { Map<String, String> args = predicates.get(0).getArgs(); String urlPath = args.get(NameUtils.GENERATED_NAME_PREFIX + "0"); if (StringUtils.isNotBlank(urlPath)) { urlPath = urlPath.replace("/**", SWAGGER2URL); } else { urlPath = args.get("pattern").replace("/**", SWAGGER2URL); } resourceList.add(swaggerResource(routeDefinition.getId(), urlPath)); } }); return resourceList; } private SwaggerResource swaggerResource(String name, String location) { SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setName(name); swaggerResource.setLocation(location); swaggerResource.setSwaggerVersion("2.0"); return swaggerResource; } /** * 从注册中心中获取所有服务接口文档 * * @return java.util.List<springfox.documentation.swagger.web.SwaggerResource> * @author llxiao * @date 2021/9/23 11:04 **/ private List<SwaggerResource> getSwaggerResourcesByFilter() { List<SwaggerResource> resources = new ArrayList<>(); List<String> routeHosts = new ArrayList<>(); // 由于我的网关采用的是负载均衡的方式,因此我需要拿到所有应用的serviceId // 获取所有可用的host:serviceId routeLocator.getRoutes().filter(route -> route.getUri().getHost() != null) .filter(route -> !self.equals(route.getUri().getHost())) .subscribe(route -> routeHosts.add(route.getUri().getHost())); // 记录已经添加过的server,存在同一个应用注册了多个服务在nacos上 Set<String> dealed = new HashSet<>(); routeHosts.forEach(instance -> { // 拼接url,样式为/serviceId/v2/api-info,当网关调用这个接口时,会自动通过负载均衡寻找对应的主机 String pcsServer = "指定路由ID,如:xxx-server"; if (pcsServer.equals(instance)) { String url = "/" + instance + SWAGGER2URL; if (!dealed.contains(url)) { dealed.add(url); SwaggerResource swaggerResource = new SwaggerResource(); swaggerResource.setUrl(url); swaggerResource.setName(instance); resources.add(swaggerResource); } } }); return resources; } }
```
6.2 swagger聚合接口
```java
import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import springfox.documentation.swagger.web.SecurityConfigurationBuilder; import springfox.documentation.swagger.web.SwaggerResource; import springfox.documentation.swagger.web.UiConfiguration; import springfox.documentation.swagger.web.UiConfigurationBuilder; /** * swagger聚合接口,三个接口都是swagger-ui.html需要访问的接口 <br> * * @date: 2021/7/17 <br> * @author: llxiao <br> * @since: 1.0 <br> * @version: 1.0 <br> */ @RestController @RequestMapping("/swagger-resources") public class SwaggerResourceController { private final PaySwaggerResourceProvider swaggerResourceProvider; @Autowired public SwaggerResourceController(PaySwaggerResourceProvider swaggerResourceProvider) { this.swaggerResourceProvider = swaggerResourceProvider; } @RequestMapping(value = "/configuration/security") public ResponseEntity securityConfiguration() { return new ResponseEntity(SecurityConfigurationBuilder.builder().build(), HttpStatus.OK); } @RequestMapping(value = "/configuration/ui") public ResponseEntity<UiConfiguration> uiConfiguration() { return new ResponseEntity<>(UiConfigurationBuilder.builder().build(), HttpStatus.OK); } @RequestMapping public ResponseEntity<List<SwaggerResource>> swaggerResources() { return new ResponseEntity<>(swaggerResourceProvider.get(), HttpStatus.OK); }
```