`

Spring Cloud Gateway聚合Springfox 3.0.0

阅读更多

Spring Cloud Gateway聚合Springfox 3.0.0

前言

    就在上个月Springfox 3.0.0发布了,增加了对Webflux、OpenApi 3的支持,很适合用于Gateway,微服务中为方便管理各微服务的接口文档,特此来摸索一下Spring Cloud Gateway集成管理,整个过程没什么代码,简单易用

 

一、环境及工具介绍

         1、gradle,一个基于 JVM 的富有突破性构建工具,简化maven的xml繁琐配置

         2、nacos,阿里开发的动态服务发现、配置和服务管理平台,appllo不喜欢用就它了

         3、knife4j,Java MVC框架集成Swagger生成Api文档的增强解决方案,前身是swagger-bootstrap-ui

              (swagger2用的好好的为啥要用这玩意???原皮看厌倦了换上新鲜的感觉)

         4、Spring Cloud版本用的是Hoxton.RELEASE,SpringBoot版本2.2.1.RELEASE

 

         以上gradle、nacos环境自行百度搭建,比较简单,不做赘述了

 

二、微服务端

        1、先写两个简单的微服务,这里起个很随便的名字(example、cart-service)

        端口分别设置为8081和8082

      

server:    
  port: 8081

   

    build.gradle文件中依赖大致如下: 

         

compile (
            /** api文档 */
            'com.github.xiaoymin:knife4j-spring-boot-starter:2.0.4',
            /**  nacos配置中心 */
            'org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config:0.9.0.RELEASE',
            /**  nacos注册与发现中心 */
            'org.springframework.cloud:spring-cloud-starter-alibaba-nacos-discovery:0.9.0.RELEASE',
            /**  nacos客户端 */
            'com.alibaba.nacos:nacos-client:1.1.3',
            'org.springframework.boot:spring-boot-starter-web',
            'org.springframework.boot:spring-boot-starter-undertow',
            /** -----------------------分割线---------------------------*/
            'org.springframework.boot:spring-boot-starter-data-redis',
            /** 集成springboot-admin */
            'de.codecentric:spring-boot-admin-starter-client:2.2.0',
            'org.projectlombok:lombok',
            /** 数据库连接池 */
            'com.alibaba:druid-spring-boot-starter:1.1.21',
            /* 数据库 **/
            'mysql:mysql-connector-java:5.1.47',
            /** mybatis */
            'tk.mybatis:mapper-spring-boot-starter:2.1.5',
            /** jpa持久化 */
            'javax.persistence:persistence-api:1.0',
            /** 分页插件 */
            'com.github.pagehelper:pagehelper:5.1.11',
            /** springboot2.X默认使用lettuce连接池,需要引入commons-pool2 */
            'org.apache.commons:commons-pool2:2.5.0'
    )

       注:   分割线以下忽略不要,因为nacos里集成配置了就放在这了,加在这里装作是内容,呕吼!

     

      这里主要就是启动微服务集成knife4j文档,容器用的undertow,web默认用的tomcat,如果需要需要使用

      undertow,增加如下内容排除tomcat依赖:

    

configurations {
    compile.exclude module: 'tomcat-embed-el'
    compile.exclude module: 'spring-boot-starter-tomcat'
}

 

    两个微服务客户端增加一个配置类:

    注:也可以写到二方库里写成配置形式方便使用,也可以不加就使用默认(反正加了没啥用),这里为了      区分一下就加一个了

    

package com.jcokee.example.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
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.service.Contact;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

@Configuration
@EnableSwagger2
@EnableKnife4j
public class Swagger2Config {

    @Bean
public Docket createRestApi(){
        return new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo())
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.jcokee.example.controller"))
                .paths(PathSelectors.any())
                .build();
    }

    private ApiInfo apiInfo() {
        Contact contact = new Contact("冲大大", "http://www.jcokee.com", "jcokee@163.com");
        return new ApiInfoBuilder()
                .title("example服务文档")
                .description("example服务API文档")
                .contact(contact)
                .version("1.0")
                .build();
    }
}

 

 

    增加启动类ExampleApplication

    

package com.jcokee.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@EnableDiscoveryClient
public class ExampleApplication {
    public static void main(String[] args) {
        SpringApplication.run(ExampleApplication.class, args);
    }

}

   

    接着来一个Controller做文档展示:

   Controller这里自己随便写吧,能看到就行,这里也贴一下吧显得不那么空

 

package com.jcokee.example.controller;

import com.alibaba.fastjson.JSON;
import com.jcokee.example.entity.Cat;
import com.jcokee.example.pojo.dto.CatDto;
import com.jcokee.example.pojo.vo.PageResult;
import com.jcokee.example.pojo.vo.ResultVO;
import com.jcokee.example.service.impl.CatServiceImpl;
import com.jcokee.example.util.BeanCopierUtil;
import com.jcokee.example.util.RedisClient;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import tk.mybatis.mapper.entity.Example;

@RestController
@RequestMapping("/v1/example/cat")
@Slf4j
public class CatController {

    @Autowired
    private CatServiceImpl catService;
    @Autowired
    private RedisClient redisClient;

    @ApiOperation("获取信息")
    @GetMapping
    public ResultVO<String> getCat(@ApiParam("主键") @RequestHeader("cid") Integer cid) {
        Cat cat = catService.selectById(cid);
        if (cat != null) {
            // 测试缓存
            redisClient.setForTimeMIN("SOA:TEXMPLE:CAT:"+cid.toString(), JSON.toJSONString(cat), 30);
        }
        return new ResultVO(cat);
    }

    @ApiOperation("新增信息")
    @PostMapping
    public ResultVO<String> addCat(@RequestBody CatDto catDto) {
        Cat cat = new Cat();
        BeanCopierUtil.copy(catDto, cat);
        catService.insert(cat);
        return new ResultVO(Constants.RESULT_SUCCESS);
    }

    @ApiOperation("修改信息")
    @PutMapping
    public ResultVO<String> updateCat(@RequestBody CatDto catDto) {
        Cat cat = new Cat();
        BeanCopierUtil.copy(catDto, cat);
        catService.updateById(cat);
        return new ResultVO(Constants.RESULT_SUCCESS);
    }

    @ApiOperation("删除信息")
    @DeleteMapping
    public ResultVO<String> deleteCat(@ApiParam("主键") @RequestHeader("cid") Integer cid) {
        catService.deleteById(cid);
        return new ResultVO(Constants.RESULT_SUCCESS);
    }

    @ApiOperation("分页查询信息")
    @GetMapping(value = "/page")
    public ResultVO<String> getPageCat(@RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                       @RequestBody(required = false) CatDto catDto) {
        Example example = null;
        if (catDto != null) {
            example = new Example(Cat.class);
            Example.Criteria criteria = example.createCriteria();
            if (catDto.getId() != null) {
                criteria.andEqualTo("id", catDto.getId());
            }
            if (catDto.getName() != null) {
                criteria.andEqualTo("name", catDto.getName());
            }
            if (catDto.getColour() != null) {
                criteria.andEqualTo("colour", catDto.getColour());
            }
        }
        PageResult pageResult = catService.selectByPage(pageNum, 20, example);
        return new ResultVO(pageResult);
    }
}
 

 

 

    然后复制项目更改名称为cart-service,settings-gradle记得也改下

    controller里仅修改了路径和类名CartController

 

    2、gateway集成微服务端

    启动类一样复制一个过来,改名GatewayApplication

    build.gradle文件增加依赖

   

compile (
            /** api文档 */
            'com.github.xiaoymin:knife4j-spring-boot-starter:2.0.4',
            'io.springfox:springfox-boot-starter:3.0.0',
            /**  nacos配置中心 */
            'org.springframework.cloud:spring-cloud-starter-alibaba-nacos-config:0.9.0.RELEASE',
            /**  nacos注册与发现中心 */
            'org.springframework.cloud:spring-cloud-starter-alibaba-nacos-discovery:0.9.0.RELEASE',
            /**  nacos客户端 */
            'com.alibaba.nacos:nacos-client:1.1.3',
            'javax.servlet:javax.servlet-api:3.1.0',
            'org.springframework.cloud:spring-cloud-starter-gateway'
    )
 

 

    下面增加一个配置类

    

package com.jcokee.gateway.config;

import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
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.Configuration;
import org.springframework.context.annotation.Primary;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.SwaggerResourcesProvider;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

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

/**
 * @author Jaakko
 */
@Configuration
@Primary
@EnableSwagger2
@EnableKnife4j
public class SwaggerResourceConfig implements SwaggerResourcesProvider {
    public static final String API_URI = "v2/api-docs";

    private final RouteLocator routeLocator;
    private final GatewayProperties gatewayProperties;

    public SwaggerResourceConfig(RouteLocator routeLocator, GatewayProperties gatewayProperties) {
        this.routeLocator = routeLocator;
        this.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("**", API_URI)))));
        return resources;
    }

    private SwaggerResource swaggerResource(String name, String location) {
        SwaggerResource swaggerResource = new SwaggerResource();
        swaggerResource.setName(name);
        swaggerResource.setLocation(location);
        swaggerResource.setSwaggerVersion("2.0");
        return swaggerResource;
    }
}
    nacos中配置 :   
server:    
  port: 9200

spring:
  cloud:
    gateway:
      routes: #配置路由路径
        - id: example
          uri: lb://example
          predicates:
            - Path=/example/**
          filters:
            - StripPrefix=1  
        - id: cart-service
          uri: lb://cart-service
          predicates:
            - Path=/cart-service/**
          filters:
            - StripPrefix=1     
      discovery:
        locator:
          enabled: true #开启从注册中心动态创建路由的功能
          lower-case-service-id: true #使用小写服务名,默认是大写      
    
    启动两个微服务端,再启动gateway服务

    参考资料:

          nacos

          knife4j

  
    图片暂不能上传就到此吧,有问题欢迎交流 QQ1527380337
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics