Spring GateWay 整合 Knife4j

1. 引入座標

<dependency>
	<groupId>com.github.xiaoymin</groupId>  
	<artifactId>knife4j-spring-boot-starter</artifactId>  
	<version>2.0.3</version>  
 </dependency> 

2. 在common模塊中創建共用類方便其他模塊引入

  1. BaseSwaggerConfig 功能模塊中提取出的公共內容
package cn.hsing.fat.swagger.config;

import cn.hsing.fat.swagger.properties.SwaggerProperties;
import org.springframework.context.annotation.Bean;
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.Docket;

import java.util.ArrayList;
import java.util.List;

public abstract class BaseSwaggerConfig {

   @Bean
   public Docket createRestApi() {
       SwaggerProperties swaggerProperties = swaggerProperties();
       Docket docket = new Docket(DocumentationType.SWAGGER_2)
               .apiInfo(apiInfo(swaggerProperties))
               .select()
               .apis(RequestHandlerSelectors.basePackage(swaggerProperties.getApiBasePackage()))
               .paths(PathSelectors.any())
               .build();
       if (swaggerProperties.isEnableSecurity()) {
           docket.securitySchemes(securitySchemes()).securityContexts(securityContexts());
       }
       return docket;
   }

   private ApiInfo apiInfo(SwaggerProperties swaggerProperties) {
       return new ApiInfoBuilder()
               .title(swaggerProperties.getTitle())
               .description(swaggerProperties.getDescription())
               .contact(new Contact(swaggerProperties.getContactName(), swaggerProperties.getContactUrl(), swaggerProperties.getContactEmail()))
               .version(swaggerProperties.getVersion())
               .build();
   }

   private List<ApiKey> securitySchemes() {
       //設置請求頭信息
       List<ApiKey> result = new ArrayList<>();
       ApiKey apiKey = new ApiKey("Authorization", "Authorization", "header");
       result.add(apiKey);
       return result;
   }

   private List<SecurityContext> securityContexts() {
       //設置需要登錄認證的路徑
       List<SecurityContext> result = new ArrayList<>();
       result.add(getContextByPath("/*/.*"));
       return result;
   }

   private SecurityContext getContextByPath(String pathRegex) {
       return SecurityContext.builder()
               .securityReferences(defaultAuth())
               .forPaths(PathSelectors.regex(pathRegex))
               .build();
   }

   private List<SecurityReference> defaultAuth() {
       List<SecurityReference> result = new ArrayList<>();
       AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
       AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
       authorizationScopes[0] = authorizationScope;
       result.add(new SecurityReference("Authorization", authorizationScopes));
       return result;
   }

   /**
    * 自定義Swagger配置
    * @return
    */
   public abstract SwaggerProperties swaggerProperties();
}
  1. SwaggerProperties
package cn.hsing.fat.swagger.properties;

import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;

/**
 * Swagger自定義配置
 */
@Data
@EqualsAndHashCode(callSuper = false)
@Builder
public class SwaggerProperties {
    /**
     * API文檔生成基礎路徑
     */
    private String apiBasePackage;
    /**
     * 是否要啓用登錄認證
     */
    private boolean enableSecurity;
    /**
     * 文檔標題
     */
    private String title;
    /**
     * 文檔描述
     */
    private String description;
    /**
     * 文檔版本
     */
    private String version;
    /**
     * 文檔聯繫人姓名
     */
    private String contactName;
    /**
     * 文檔聯繫人網址
     */
    private String contactUrl;
    /**
     * 文檔聯繫人郵箱
     */
    private String contactEmail;
}

3. 網關配置****knife4j SwaggerResourceConfig

package cn.hsing.fat.gateway.config;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.config.GatewayProperties;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.support.NameUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Component
@Slf4j
@AllArgsConstructor
public class SwaggerResourceConfig implements SwaggerResourcesProvider {

    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;


    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routes = new ArrayList<>();
        //獲取所有路由的ID
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        //過濾出配置文件中定義的路由->過濾出Path Route Predicate->根據路徑拼接成api-docs路徑->生成SwaggerResource
        gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId())).forEach(route -> {
            route.getPredicates().stream()
                    .filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
                    .forEach(predicateDefinition -> resources.add(swaggerResource(route.getId(),
                            predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
                                    .replace("**", "v2/api-docs"))));
        });

        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location) {
        log.info("name:{},location:{}", name, location);
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}

package cn.hsing.fat.gateway.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import springfox.documentation.swagger.web.*;

import java.util.Optional;

@RestController
@RequestMapping("/swagger-resources")
public class SwaggerHandler {

    @Autowired(required = false)
    private SecurityConfiguration securityConfiguration;

    @Autowired(required = false)
    private UiConfiguration uiConfiguration;

    private final SwaggerResourcesProvider swaggerResources;

    @Autowired
    public SwaggerHandler(SwaggerResourcesProvider swaggerResources) {
        this.swaggerResources = swaggerResources;
    }


    @GetMapping("/configuration/security")
    public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("/configuration/ui")
    public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

    @GetMapping("")
    public Mono<ResponseEntity> swaggerResources() {
        return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
    }
}

4. 在功能模塊中使用

    package cn.hsing.fat.system.config;
    
    import cn.hsing.fat.swagger.config.BaseSwaggerConfig;
    import cn.hsing.fat.swagger.properties.SwaggerProperties;
    import org.springframework.context.annotation.Configuration;
    import springfox.documentation.swagger2.annotations.EnableSwagger2;
    
    @Configuration
    @EnableSwagger2
    public class SwaggerConfig extends BaseSwaggerConfig {
    
        @Override
        public SwaggerProperties swaggerProperties() {
            return SwaggerProperties.builder()
                    .apiBasePackage("cn.hsing.fat.system")
                    .title("基礎模塊")
                    .description("基礎模塊相關接口文檔")
                    .contactName("xing.Li")
                    .version("1.0")
                    .enableSecurity(true)
                    .build();
        }
    }

注:其中Oauth2需添加配置

在 WebSecurityConfig中添加
  http.authorizeRequests()
	  .antMatchers("/doc.html","/webjars/**","/img.icons/**","/swagger-resources/**","/**","/v2/api-docs")
	.permitAll() //允許所有人訪問knife4j

代碼參考開源項目mall-swarm

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章