springcloud gateway整合swagger做分佈式聚合文檔

項目中使用gateway做路由,根據請求頭訪問不同的api,api中使用openfegin,去訪問對應的service。爲了說明配置,摘取項目核心的代碼。包括gateway,user-api,standard-api。

1.swagger依賴

gateway和api中的需要引入swagger的相應依賴:

<properties>
    <swagger.version>2.9.2</swagger.version>
</properties>
<dependencies> 
    <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger2</artifactId>
            <version>2.9.2</version>
        </dependency>

        <dependency>
            <groupId>io.springfox</groupId>
            <artifactId>springfox-swagger-ui</artifactId>
            <version>2.9.2</version>
        </dependency>
</dependencies>      

2.gateway中配置加載swagger信息

import com.ruizhi.detection.component.SwaggerProvider;
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.*;

import java.util.List;

/**
 * @description: 用於加載swagger中相關信息的controller
 * @Author: 
 * @Date: 2020/2/11 11:27
 */
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerResourceController {

    private SwaggerProvider swaggerProvider;

    // TODO: 添加權限校驗
    @Autowired
    public SwaggerResourceController(SwaggerProvider swaggerProvider) {
        this.swaggerProvider = swaggerProvider;
    }

    @RequestMapping(value = "/configuration/security")
    public ResponseEntity<SecurityConfiguration> 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<>(swaggerProvider.get(), HttpStatus.OK);
    }
}

3.gateway中配置nacos中註冊的服務

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.stereotype.Component;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @description: 用於加載在nacos中註冊的服務
 * @Author:
 * @Date: 2020/2/11 11:23
 */
@Component
public class SwaggerProvider implements SwaggerResourcesProvider {

    /**
     * swagger2默認的url後綴
     */
    private static final String SWAGGER2URL = "/v2/api-docs";

    /**
     * 網關路由
     */
    private final RouteLocator routeLocator;

    /**
     * 網關應用名稱
     */
    @Value("${spring.application.name}")
    private String self;

    @Autowired
    public SwaggerProvider(RouteLocator routeLocator) {
        this.routeLocator = routeLocator;
    }

    @Override
    public List<SwaggerResource> get() {
        List<SwaggerResource> resources = new ArrayList<>();
        List<String> routeHosts = new ArrayList<>();
        // 獲取所有可用的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
            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;
    }
}

4.user-api和standard-api中設置swagger中的配置

這兩個類基本上差不多,我只貼其中一個

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

/**
 * @description: 配置描述swagger的描述
 * @Author: 
 * @Date: 2020/2/11 11:47
 */
@EnableSwagger2
@Configuration
public class SwaggerConfig {

    /**
     * 創建API
     */
    @Bean
    public Docket createRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                // 詳細定製
                .apiInfo(apiInfo("1.0.0"))
                .select()
                // 指定掃描的包路徑
              .apis(RequestHandlerSelectors.basePackage("com.detection.controller"))
                // 掃描所有
                .paths(PathSelectors.any())
                .build();
    }

    /**
     * 添加摘要信息
     */
    private ApiInfo apiInfo(String version) {
        // 用ApiInfoBuilder進行定製
        return new ApiInfoBuilder()
                .title("標準管理的接口文檔")
                .version(version)
                .build();
    }
}

5.gateway中路由規則的配置

spring:
  cloud:
    gateway:
      enabled: true
      discovery:
        locator:
          lower-case-service-id: true
      routes:
        #netty 路由過濾器(數組),http或https開頭 lb://代表是服務的名稱  predicates:表示會過濾掉的請求頭
        - id: user-router
          uri: lb://user-api
          predicates:
            - Path=/user-api/**
          filters:
          - StripPrefix=1
        - id: standard-router
          uri: lb://standard-api
          predicates:
            - Path=/standard-api/**
          filters:
          - StripPrefix=1
        - id: file-upload-router
          uri: lb://file-service
          predicates:
            - Path=/file-service/**
          filters:
          - StripPrefix=1
    #處理跨域請求問題
    globalcors:
      cors-configurations:
        '[/**]':
          allowedOrigins: "*"
          allowedMethods: "*"

這裏需要主要path中的請求頭,需要跟uri中的一致,都是你服務的名稱,否則你訪問的時候,就過濾不掉頭部,請求具體的api時會多一個請求頭。
配置好之後,啓動訪問http://localhost:{port}/swagger-ui.html就可以看到swagger的頁面了。其中port爲你的gateway端口.
在這裏插入圖片描述
具體swagger的配置,可以網上搜索一下api,這裏我貼幾個大概的參考下。

1.controller的代碼
    /**
     * 新增標準信息
     * @param dto 標準的dto
     * @return
     */
    @ApiOperation(value = "新增標準信息", httpMethod = "POST")
    @RequestMapping(value = "/saveStandardInfo", method = RequestMethod.POST)
    public ResponseDto saveStandardInfo(@RequestBody StandardInfoDto dto) {
        return iStandardInfoService.saveStandardInfo(dto);
    }

    /**
     * 標準信息--查看
     * @param standardId 標準的id
     * @return ResponseDto
     * <StandardInfoDto>這種寫法是爲了讓其在swagger中展示嵌套的json值
     */
    @ApiOperation(value = "根據id查詢標準信息", httpMethod = "GET")
    @RequestMapping(value = "/findStandardInfo", method = RequestMethod.GET)
    @ApiImplicitParam(name = "standardId", value = "標準id", dataType = "string")
    public ResponseDto<StandardInfoDto> findStandardInfo(@RequestParam(value = "standardId") String standardId) {
        return iStandardInfoService.findStandardInfo(standardId);
    }

    /**
     * 標準信息--修改狀態
     * @param standardId    標準的id
     * @param standardState 標準的狀態
     * @return
     */
    @ApiOperation(value = "修改標準信息的狀態", httpMethod = "GET")
    @RequestMapping(value = "/updateStateStandardInfo", method = RequestMethod.GET)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "standardId", value = "標準id", dataType = "string"),
            @ApiImplicitParam(name = "standardState", value = "標準的狀態", dataType = "string", example = "1,2,3")
    })
    public ResponseDto updateStateStandardInfo(@RequestParam(value = "standardId") String standardId, @RequestParam(value = "standardState") String standardState) {
        return iStandardInfoService.updateStateStandardInfo(standardId, standardState);
    }
2.model
/**
 * @description:用於返回數據的dto
 * @Author:
 * @Date: 2019/8/15  15:46
 */
@Data
@ApiModel("返回類")
public class ResponseDto<T> {

    /**
     * 狀態碼
     */
    @ApiModelProperty(value = "狀態碼")
    private Integer code;

    /**
     * 狀態信息
     */
    @ApiModelProperty(value = "狀態信息")
    private String message;

    /**
     * 數據
     */
    @ApiModelProperty(value = "數據")
    private T data;

    public ResponseDto(Integer code, String message, T data) {
        this.code = code;
        this.data = data;
        this.message = message;
    }
}

這裏注意就是apiModel中,可以用value,也可以用tag,但是用tag會出現多個的model,還有就是不管用tag還是value,不能出現"/"否則會報錯。

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