2、微服务整合Swagger3.0 - 抽取为公共模块

1、SpringBoot快速整合Swagger3.0

2、微服务整合Swagger3.0 - 抽取为公共模块

3、微服务整合Swagger3.0 - 网关Gateway聚合接口

4、微服务整合Swagger3.0 - 使用方法

5、微服务Swagger3.0升级为Knife4j

背景:快速整合Swagger的方式,需要每个微服务都创建一个SwaggerConfig类,当微服务特别多的时候,这样就不合适了;我们可以将swagger这个配置,抽取成一个公共模块。

一、实现的效果

目录

二、整合步骤

1、创建xxx-common-swagger模块

2、引入依赖

<!-- SpringBoot Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Swagger -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>${swagger.fox.version}</version>
</dependency>
<!-- Swagger UI -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>${swagger.fox.version}</version>
</dependency>

3、编写配置类

(1)自定义注解

/**
 * EnableCustomSwagger2 自定义注解,哪个服务需要swagger2,就添加在哪个的启动类上
 * @author cch
 * @create 2024-01-25 17:56
 */
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import({ SwaggerAutoConfiguration.class })
public @interface EnableCustomSwagger2 {
}

(2)swagger的配置类一


package com.cch.swagger.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.context.annotation.Import;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.ApiSelectorBuilder;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
 * @author cch
 * @create 2024-01-25 17:57
 */
@Configuration
@EnableSwagger2
@EnableConfigurationProperties(SwaggerProperties.class)
@ConditionalOnProperty(name = "swagger.enabled", matchIfMissing = true)
//@Import({SwaggerBeanPostProcessor.class, SwaggerWebConfiguration.class})
@Import({SwaggerWebConfiguration.class})
public class SwaggerAutoConfiguration {
    /**
     * 默认的排除路径,排除Spring Boot默认的错误处理路径和端点
     */
    private static final List<String> DEFAULT_EXCLUDE_PATH = Arrays.asList("/error", "/actuator/**");
    private static final String BASE_PATH = "/**";
    @Bean
    @ConditionalOnMissingBean
    public SwaggerProperties swaggerProperties()
    {
        return new SwaggerProperties();
    }
    @Bean
    public Docket api(SwaggerProperties swaggerProperties)
    {
        // base-path处理
        if (swaggerProperties.getBasePath().isEmpty())
        {
            swaggerProperties.getBasePath().add(BASE_PATH);
        }
        // noinspection unchecked 未检查
        List<Predicate<String>> basePath = new ArrayList<Predicate<String>>();
        swaggerProperties.getBasePath().forEach(path -> basePath.add(PathSelectors.ant(path)));
        // exclude-path处理
        if (swaggerProperties.getExcludePath().isEmpty())
        {
            swaggerProperties.getExcludePath().addAll(DEFAULT_EXCLUDE_PATH);
        }
        List<Predicate<String>> excludePath = new ArrayList<>();
        swaggerProperties.getExcludePath().forEach(path -> excludePath.add(PathSelectors.ant(path)));

        ApiSelectorBuilder builder = new Docket(DocumentationType.SWAGGER_2)// DocumentationType.SWAGGER_2 固定的,代表swagger2
                .host(swaggerProperties.getHost())
                .apiInfo(apiInfo(swaggerProperties)) // 用于生成API信息
                .select() // select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档,select()方法配置怎么扫描接口
                .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getBasePackage())); // RequestHandlerSelectors配置如何扫描接口,用于指定扫描哪个包下的接口
        // 配置如何通过 path过滤 即这里只扫描 请求以 /user开头的接口
        //                                                  .paths(PathSelectors.ant("/user/**"))
        swaggerProperties.getBasePath().forEach(p -> builder.paths(PathSelectors.ant(p))); //选择所有的API,如果你想只为部分的API生成文档,可以配置这里
        //在basePath基础上需要排除的url规则
        swaggerProperties.getExcludePath().forEach(p -> builder.paths(PathSelectors.ant(p).negate()));
        return builder.build().securitySchemes(securitySchemes()).securityContexts(securityContexts()).pathMapping("/");
    }
    /**
     * 安全模式,这里指定token通过Authorization头请求头传递
     */
    private List<SecurityScheme> securitySchemes()
    {
        List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
        apiKeyList.add(new ApiKey("Authorization", "Authorization", "header"));
        return apiKeyList;
    }
    /**
     * 安全上下文
     */
    private List<SecurityContext> securityContexts()
    {
        List<SecurityContext> securityContexts = new ArrayList<>();
        securityContexts.add(
                SecurityContext.builder()
                        .securityReferences(defaultAuth())
                        .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
                        .build());
        return securityContexts;
    }
    /**
     * 默认的全局鉴权策略
     *
     * @return
     */
    private List<SecurityReference> defaultAuth()
    {
        AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        List<SecurityReference> securityReferences = new ArrayList<>();
        securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
        return securityReferences;
    }
    //配置swagger-ui的api信息
    private ApiInfo apiInfo(SwaggerProperties swaggerProperties)
    {
        return new ApiInfoBuilder()
                .title(swaggerProperties.getTitle())
                .description(swaggerProperties.getDescription())
                .license(swaggerProperties.getLicense())
                .licenseUrl(swaggerProperties.getLicenseUrl())
                .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl())
                .contact(new Contact(swaggerProperties.getContact().getName(), swaggerProperties.getContact().getUrl(), swaggerProperties.getContact().getEmail()))
                .version(swaggerProperties.getVersion())
                .build();
    }
}

(3)swagger的配置类二


package com.cch.swagger.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
/**
 * @author cch
 * @create 2024-01-25 18:05
 */
@Component
@ConfigurationProperties("swagger")
public class SwaggerProperties {
    /**
     * 是否开启swagger
     */
    private Boolean enabled;
    /**
     * swagger会解析的包路径
     **/
    private String basePackage = "";
    /**
     * swagger会解析的url规则
     **/
    private List<String> basePath = new ArrayList<>();
    /**
     * 在basePath基础上需要排除的url规则
     **/
    private List<String> excludePath = new ArrayList<>();
    /**
     * 标题
     **/
    private String title = "";
    /**
     * 描述
     **/
    private String description = "";
    /**
     * 版本
     **/
    private String version = "";
    /**
     * 许可证
     **/
    private String license = "";
    /**
     * 许可证URL
     **/
    private String licenseUrl = "";
    /**
     * 服务条款URL
     **/
    private String termsOfServiceUrl = "";
    /**
     * host信息
     **/
    private String host = "";
    /**
     * 联系人信息
     */
    private Contact contact = new Contact();
    /**
     * 全局统一鉴权配置
     **/
    private Authorization authorization = new Authorization();
    public Boolean getEnabled()
    {
        return enabled;
    }
    public void setEnabled(Boolean enabled)
    {
        this.enabled = enabled;
    }
    public String getBasePackage()
    {
        return basePackage;
    }
    public void setBasePackage(String basePackage)
    {
        this.basePackage = basePackage;
    }
    public List<String> getBasePath()
    {
        return basePath;
    }
    public void setBasePath(List<String> basePath)
    {
        this.basePath = basePath;
    }
    public List<String> getExcludePath()
    {
        return excludePath;
    }
    public void setExcludePath(List<String> excludePath)
    {
        this.excludePath = excludePath;
    }
    public String getTitle()
    {
        return title;
    }
    public void setTitle(String title)
    {
        this.title = title;
    }
    public String getDescription()
    {
        return description;
    }
    public void setDescription(String description)
    {
        this.description = description;
    }
    public String getVersion()
    {
        return version;
    }
    public void setVersion(String version)
    {
        this.version = version;
    }
    public String getLicense()
    {
        return license;
    }
    public void setLicense(String license)
    {
        this.license = license;
    }
    public String getLicenseUrl()
    {
        return licenseUrl;
    }
    public void setLicenseUrl(String licenseUrl)
    {
        this.licenseUrl = licenseUrl;
    }
    public String getTermsOfServiceUrl()
    {
        return termsOfServiceUrl;
    }
    public void setTermsOfServiceUrl(String termsOfServiceUrl)
    {
        this.termsOfServiceUrl = termsOfServiceUrl;
    }
    public String getHost()
    {
        return host;
    }
    public void setHost(String host)
    {
        this.host = host;
    }
    public Contact getContact()
    {
        return contact;
    }
    public void setContact(Contact contact)
    {
        this.contact = contact;
    }
    public Authorization getAuthorization()
    {
        return authorization;
    }
    public void setAuthorization(Authorization authorization)
    {
        this.authorization = authorization;
    }
//    作者信息
    public static class Contact
    {
        /**
         * 联系人
         **/
        private String name = "";
        /**
         * 联系人url
         **/
        private String url = "";
        /**
         * 联系人email
         **/
        private String email = "";
        public String getName()
        {
            return name;
        }
        public void setName(String name)
        {
            this.name = name;
        }
        public String getUrl()
        {
            return url;
        }
        public void setUrl(String url)
        {
            this.url = url;
        }
        public String getEmail()
        {
            return email;
        }
        public void setEmail(String email)
        {
            this.email = email;
        }
    }
    public static class Authorization
    {
        /**
         * 鉴权策略ID,需要和SecurityReferences ID保持一致
         */
        private String name = "";
        /**
         * 需要开启鉴权URL的正则
         */
        private String authRegex = "^.*$";
        /**
         * 鉴权作用域列表
         */
        private List<AuthorizationScope> authorizationScopeList = new ArrayList<>();
        private List<String> tokenUrlList = new ArrayList<>();
        public String getName()
        {
            return name;
        }
        public void setName(String name)
        {
            this.name = name;
        }
        public String getAuthRegex()
        {
            return authRegex;
        }
        public void setAuthRegex(String authRegex)
        {
            this.authRegex = authRegex;
        }
        public List<AuthorizationScope> getAuthorizationScopeList()
        {
            return authorizationScopeList;
        }
        public void setAuthorizationScopeList(List<AuthorizationScope> authorizationScopeList)
        {
            this.authorizationScopeList = authorizationScopeList;
        }
        public List<String> getTokenUrlList()
        {
            return tokenUrlList;
        }
        public void setTokenUrlList(List<String> tokenUrlList)
        {
            this.tokenUrlList = tokenUrlList;
        }
    }
    public static class AuthorizationScope
    {
        /**
         * 作用域名称
         */
        private String scope = "";
        /**
         * 作用域描述
         */
        private String description = "";
        public String getScope()
        {
            return scope;
        }
        public void setScope(String scope)
        {
            this.scope = scope;
        }
        public String getDescription()
        {
            return description;
        }
        public void setDescription(String description)
        {
            this.description = description;
        }
    }
}

(4)swagger 资源映射路径

注意:3.0.0版本访问是: /swagger-ui/index.html


package com.cch.swagger.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
 * swagger 资源映射路径
 * @author cch
 * @create 2024-01-25 21:27
 */
@Configuration
public class SwaggerWebConfiguration implements WebMvcConfigurer {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry)
    {
        /** swagger-ui 地址 */
        //3.0.0版本访问是: /swagger-ui/index.html
        registry.addResourceHandler("/swagger-ui/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
    }
}

(5)在 META-INF 添加spring配置

因为cch-common-swagger模块是一个公共模块,并不是一个web工程,想要让模块内的配置类生效并且加入ioc容器中,必须在resources目录下先建文件夹 META-INF,再创建 spring文件夹,然后创建org.springframework.boot.autoconfigure.AutoConfiguration.imports,内容如下:

com.cch.swagger.config.SwaggerAutoConfiguration
com.cch.swagger.config.SwaggerWebConfiguration
#com.cch.swagger.config.SwaggerBeanPostProcessor

======如果SpringBoot 版本在2.6以下,配置到此结束!!!======

三、其它

以下是Swagger3.0.0在SpringBoot2.6.x不兼容问题的处理方案:

如果SpringBoot 2.6.0开始,请求路径与SpringMVC处理映射匹配的默认策略已从AntPathMatcher更改为PathPatternParser。可以通过设置spring.mvc.pathmatch.matching-strategy为ant-path-matcher来改变。

除了basePackage包路径配错以外。以下方案可解决以上问题。


package com.cch.swagger.config;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping;
import springfox.documentation.spring.web.plugins.WebFluxRequestHandlerProvider;
import springfox.documentation.spring.web.plugins.WebMvcRequestHandlerProvider;
import java.lang.reflect.Field;
import java.util.List;
import java.util.stream.Collectors;
/**
 * swagger 在 springboot 2.6.x 不兼容问题的处理
 * @author cch
 * @create 2024-01-25 21:06
 */
public class SwaggerBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
    {
        if (bean instanceof WebMvcRequestHandlerProvider || bean instanceof WebFluxRequestHandlerProvider)
        {
            customizeSpringfoxHandlerMappings(getHandlerMappings(bean));
        }
        return bean;
    }
    private <T extends RequestMappingInfoHandlerMapping> void customizeSpringfoxHandlerMappings(List<T> mappings)
    {
        List<T> copy = mappings.stream().filter(mapping -> mapping.getPatternParser() == null)
                .collect(Collectors.toList());
        mappings.clear();
        mappings.addAll(copy);
    }
    @SuppressWarnings("unchecked")
    private List<RequestMappingInfoHandlerMapping> getHandlerMappings(Object bean)
    {
        try
        {
            Field field = ReflectionUtils.findField(bean.getClass(), "handlerMappings");
            field.setAccessible(true);
            return (List<RequestMappingInfoHandlerMapping>) field.get(bean);
        }
        catch (IllegalArgumentException | IllegalAccessException e)
        {
            throw new IllegalStateException(e);
        }
    }
}

并更改@Import,添加 SwaggerBeanPostProcessor.class

  • 27
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 首先,需要在 `pom.xml` 文件添加以下依赖: ```xml <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> ``` 接着,在 Spring Boot 的启动类上添加 `@EnableSwagger2WebFlux` 注解: ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import springfox.documentation.swagger2.annotations.EnableSwagger2WebFlux; @SpringBootApplication @EnableSwagger2WebFlux public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 最后,在你的控制器类上添加 `@Api` 和 `@ApiOperation` 注解进行 API 文档的描述: ```java import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/hello") @Api(tags = "HelloController", description = "示例控制器") public class HelloController { @GetMapping("/") @ApiOperation(value = "hello", notes = "示例接口") public String hello() { return "Hello, Swagger!"; } } ``` 然后,启动应用程序并访问 `http://localhost:<port>/swagger-ui/index.html` 即可查看生成的 API 文档。 ### 回答2: Spring Boot整合Springfox Swagger 3.0 Springfox Swagger是一个用于为Spring Boot应用程序生成文档的框架。在Spring Boot使用Springfox Swagger 3.0,可以方便地为API生成可视化的接口文档,并提供简化的API调试和测试功能。下面是整合Springfox Swagger 3.0的步骤: 首先,需要在Spring Boot项目的pom.xml文件添加Springfox Swagger 3.0的依赖: ```xml <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> ``` 然后,在Spring Boot应用程序的启动类上添加`@EnableOpenApi`注解,以启用Springfox Swagger 3.0的功能: ```java @SpringBootApplication @EnableOpenApi public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } } ``` 接下来,需要在项目添加一个配置类,其配置Swagger的相关信息: ```java @Configuration public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.OAS_30) .select() .apis(RequestHandlerSelectors.basePackage("com.example.controller")) .paths(PathSelectors.any()) .build(); } } ``` 上述配置,通过`apis`方法指定需要生成文档的Controller所在的包,通过`paths`方法指定需要生成文档的接口路径。可以根据需要进行自定义配置。 最后,在浏览器访问http://localhost:8080/swagger-ui/index.html,可以看到生成的接口文档页面。在该页面上,可以查看API的详细信息,进行测试和调试。 整合Springfox Swagger 3.0是一个方便快捷的方式来创建和管理API文档。它提供了友好的UI界面和强大的功能,可以大大简化API文档的维护工作,并提高团队合作效率。 ### 回答3: Spring Boot整合Springfox Swagger 3.0的步骤如下: 1. 添加相关依赖:在`pom.xml`文件添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency> ``` 2. 创建Swagger配置类:创建一个配置类,并使用`@Configuration`注解进行标记。在该类,可以配置Swagger的相关信息,如标题、描述、版本等。 ```java @Configuration @EnableSwagger2 //启用Swagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) .select() .apis(RequestHandlerSelectors.basePackage("com.example.demo.controller")) .paths(PathSelectors.any()) .build(); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title("API文档标题") .description("API文档描述") .version("1.0.0") .build(); } } ``` 3. 配置Swagger的URL路径:在`application.properties`或`application.yml`文件,添加以下配置项,指定Swagger的URL路径: ```yaml springfox.documentation.swagger-ui.path=/swagger-ui.html ``` 4. 启动项目:启动Spring Boot项目,访问http://localhost:8080/swagger-ui.html,即可查看生成的API文档。 以上是Spring Boot整合Springfox Swagger 3.0的基本步骤,通过配置Swagger相关信息,可以实现自动生成API文档,并提供可视化的界面。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值