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,不能出现"/"否则会报错。

发布了97 篇原创文章 · 获赞 44 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/github_38924695/article/details/104269865