SpringCloud2.0 Gateway引入knife4j管理接口文档

前言

最近几年一直使用showdoc来进行接口文档的管理。其实,知道swagger可以很方面的在找接口的时候找到它的文档。但是,说服我的是,我需要在研发开始的时候确认接口文档,但是这个时候是还没有代码的。而swagger就无法满足这种需要。但是,由于接口文档和代码分离,其有效性其实是大打折扣的,也很难检索和阅读以及和接口对应。最近,看到了这个框架,就试试吧,把接口文档还是挪到代码里去维护吧。

引入

官网文档地址为:https://doc.xiaominfo.com/guide/
我手上的项目是springcloud的,所以就直接看springcloud怎么引入了。本文档为折腾过程的记录。

注册中心

看官方文档,注册中心是不需要任何改变的,就是单纯的erueka注册中心

接口服务

这里它直接引入了一个starter


    com.github.xiaoymin
    knife4j-micro-spring-boot-starter
    2.0.1

版本是我在mvnrepository.com上找的,最新版本。据说这个依赖的区别是,去掉了ui的内容。
创建配置类SwaggerConfig:

@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SwaggerConfig {


    @Bean(value = "userApi")
    @Order(value = 1)
    public Docket groupRestApi() {
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(groupApiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.xiaominfo.swagger.service.user.controller"))
                .paths(PathSelectors.any())

                .build();
    }

    private ApiInfo groupApiInfo(){
        return new ApiInfoBuilder()
                .title("swagger-bootstrap-ui很棒~~~!!!")
                .description("
swagger-bootstrap-ui-demo RESTful APIs
") .termsOfServiceUrl("http://www.group.com/") .contact("[email protected]") .version("1.0") .build(); } }

官网的代码比这个多一个@EnableSwaggerBootstrapUi,在类上面。应该是写错了,因为在这个项目里是没有引入ui依赖的。然后,这似乎就完了

gateway

我这里使用的是spring2.0,网关用的是Gateway。这里引入的依赖就是完整的依赖了:


    com.github.xiaoymin
    knife4j-spring-boot-starter
    2.0.1

另说,如果在gateway上没有接口的话,单纯得引入ui也是可以的:


    com.github.xiaoymin
    knife4j-spring-ui
    2.0.1

在yml配置文件里,配置每个服务的时候多了

          filters:
            - SwaggerHeaderFilter
            - StripPrefix=1

这样的filter的配置在routes下每个id中进行配置。
另外,它说单体应用时使用包路径进行分组的,但是微服务架构下就是使用服务来进行业务分组了。springfox-swagger提供的分组接口是swagger-resource,返回的是分组接口名称、地址等信息。在SpringCloud微服务架构下,我们需要重写该接口,主要是通过网关的注册中心动态发现所有的微服务群的那个,代码如下:

@Component
@Primary
public class SwaggerResourceConfig implements SwaggerResourcesProvider {

    private static Logger logger= LoggerFactory.getLogger(SwaggerResourceConfig.class);

    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;

    public SwaggerResourceConfig(RouteLocator routeLocator,GatewayProperties gatewayProperties){
        this.routeLocator=routeLocator;
        this.gatewayProperties=gatewayProperties;
    }

    @Override
    public List get() {
        List resources = new ArrayList<>();
        List routes = new ArrayList<>();
        routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
        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) {
        logger.info("name:{},location:{}",name,location);
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}

实现相关接口,代码如下:

@RestController
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("/swagger-resources/configuration/security")
    public Mono> securityConfiguration() {
        return Mono.just(new ResponseEntity<>(
                Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
    }

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

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

实现SwaggerHeaderFilter过滤器,下面这段代码是官网给的,我一个字都没改。

@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
    private static final String HEADER_NAME = "X-Forwarded-Prefix";

    private static final String URI = "/v2/api-docs";

    @Override
    public GatewayFilter apply(Object config) {
        return (exchange, chain) -> {
            ServerHttpRequest request = exchange.getRequest();
            String path = request.getURI().getPath();
            if (!StringUtils.endsWithIgnoreCase(path,URI )) {
                return chain.filter(exchange);
            }
            String basePath = path.substring(0, path.lastIndexOf(URI));
            ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
            ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
            return chain.filter(newExchange);
        };
    }
}

验证

请求你gateway监听端口的doc.html页面即可。具体来说,我的是:

http://localhost:8770/doc.html

怎么写接口就不说了,看官方文档或者swagger2文档自己慢慢坑吧。打完收工。

备注

guava版本过低

这个问题是在我尝试启动我的接口服务时发现的。直接的提示是调用里面的某个类时,有个方法找不到,而我当前的版本是16。这经常发生在版本过低中。由于我并没有直接引入过guava包,所以我尝试在maven依赖中找到是谁给我带进来的。最后定位到springcloud的rebbin依赖。这个大版本暂时我不想动,所以就单独引入了guava版本23,启动成功。

接口会话拦截

这个其实很容易理解。我的session拦截是做在Gateway的,而knife4j想要获得接口信息,本质上也是接口请求。所以我需要将其排除在外,而其指定这个接口就是通过Gateway中添加的SwaggerHeaderFilter 来指定的,我们将其模式匹配的排除即可。

你可能感兴趣的:(SpringCloud2.0 Gateway引入knife4j管理接口文档)