一、简介
本篇文章要实现的是给接口服务引入swagger来生成接口文档,并用gateway来聚合API。
ok,开始实战吧。
二、引入swagger
shop-service-api添加swagger依赖,pom如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shop-parent</artifactId>
<groupId>com.liazhan</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-service-api</artifactId>
<packaging>pom</packaging>
<modules>
<module>shop-service-api-member</module>
<module>shop-service-api-weixin</module>
</modules>
<dependencies>
<!-- swagger-spring-boot -->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
</dependencies>
</project>
修改shop-service-api-weixin的实体类TestEntity和接口WeiXinService,如下
package com.liazhan.weixin.entity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @version V1.0
* @description: 测试用实体类
* @author: Liazhan
* @date: 2020/4/7 21:55
*/
@ApiModel(value = "测试实体类")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestEntity {
/**
* 姓名
*/
@ApiModelProperty(value = "姓名")
String name;
/**
* 地址
*/
@ApiModelProperty(value = "地址")
String address;
}
package com.liazhan.weixin.service;
import com.liazhan.weixin.entity.TestEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @version V1.0
* @description: 微信服务接口
* @author: Liazhan
* @date: 2020/4/7 21:59
*/
@Api(tags = "微信服务接口")
public interface WeiXinService {
/**
* 测试接口
* @return
*/
@ApiOperation(value = "测试接口")
@GetMapping("/test")
public TestEntity test();
}
修改shop-service-impl-weixin的入口类AppWeiXin ,添加@EnableSwagger2Doc注释;修改application.yml文件,添加swagger相关配置,如下:
package com.liazhan.weixin;
import com.spring4all.swagger.EnableSwagger2Doc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @version V1.0
* @description: 微信服务入口类
* @author: Liazhan
* @date: 2020/4/8 0:14
*/
@SpringBootApplication
@EnableSwagger2Doc
public class AppWeiXin {
public static void main(String[] args) {
SpringApplication.run(AppWeiXin.class,args);
}
}
#服务端口号
server:
port: 8200
#eureka信息配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8100/eureka
spring:
application:
name: liazhan-weixin
####swagger相关配置
swagger:
base-package: com.liazhan.weixin.service
title: 微服务电商项目-微信服务接口
description: 微信服务
version: 1.1
terms-of-service-url: www.baidu.com
contact:
name: liazhan
email: 33421352+liazhan@users.noreply.github.com
启动eureka和微信服务,访问http://localhost:8200/swagger-ui.html
如此微信服务就引入swagger成功了。
同理,我们对会员服务进行相似的修改,如下所示:
package com.liazhan.member.service;
import com.liazhan.weixin.entity.TestEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
/**
* @version V1.0
* @description: 会员服务接口
* @author: Liazhan
* @date: 2020/4/7 23:54
*/
@Api(tags = "会员服务接口")
public interface MemberService {
/**
* 调用微信服务测试接口
* @return
*/
@ApiOperation(value = "调用微信服务测试接口")
@GetMapping("/callWeiXin")
public TestEntity callWeiXin();
}
package com.liazhan.member;
import com.spring4all.swagger.EnableSwagger2Doc;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
/**
* @version V1.0
* @description: 会员服务入口类
* @author: Liazhan
* @date: 2020/4/8 0:13
*/
@SpringBootApplication
@EnableFeignClients
@EnableSwagger2Doc
public class AppMember {
public static void main(String[] args) {
SpringApplication.run(AppMember.class,args);
}
}
#服务端口号
server:
port: 8300
#eureka信息配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8100/eureka
spring:
application:
name: liazhan-member
####swagger相关配置
swagger:
base-package: com.liazhan.member.service
title: 微服务电商项目-会员服务接口
description: 会员服务
version: 1.1
terms-of-service-url: www.baidu.com
contact:
name: liazhan
email: 33421352+liazhan@users.noreply.github.com
启动会员服务,访问http://localhost:8300/swagger-ui.html
如此会员服务就引入swagger成功了
如此有一个问题是,
查看微信服务文档要访问http://localhost:8200/swagger-ui.html,
查看会员服务文档要访问http://localhost:8300/swagger-ui.html
这不是很方便,因此我们引入网关gateway来聚合Api的同时,统一管理swagger文档。
三、在shop-basics基础上创建Module——shop-basics-cloud-gateway
项目目录如下:
跟创建eureka时一样,使用maven创建,jar类型。
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>shop-basics</artifactId>
<groupId>com.liazhan</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>shop-basics-cloud-gateway</artifactId>
<packaging>jar</packaging>
<dependencies>
<!-- gateway -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!-- swagger-spring-boot -->
<dependency>
<groupId>com.spring4all</groupId>
<artifactId>swagger-spring-boot-starter</artifactId>
<version>1.7.0.RELEASE</version>
</dependency>
</dependencies>
</project>
MySwaggerResourceProvider文件如下:
package com.liazhan.config;
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.*;
/**
* @version V1.0
* @description: 聚合各个服务的swagger接口
* @author: Liazhan
* @date: 2020/4/10 14:25
*/
@Component
public class MySwaggerResourceProvider 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 MySwaggerResourceProvider(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,存在同一个应用注册了多个服务在eureka上
Set<String> dealed = new HashSet<>();
routeHosts.forEach(instance -> {
// 拼接url
String url = "/" + instance.toLowerCase() + SWAGGER2URL;
if (!dealed.contains(url)) {
dealed.add(url);
SwaggerResource swaggerResource = new SwaggerResource();
swaggerResource.setUrl(url);
swaggerResource.setName(instance);
resources.add(swaggerResource);
}
});
return resources;
}
}
SwaggerResourceController文件如下:
package com.liazhan.controller;
import com.liazhan.config.MySwaggerResourceProvider;
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;
/**
* @version V1.0
* @description: swagger聚合接口,三个接口都是swagger-ui.html需要访问的接口
* @author: Liazhan
* @date: 2020/4/10 14:30
*/
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerResourceController {
private MySwaggerResourceProvider swaggerResourceProvider;
@Autowired
public SwaggerResourceController(MySwaggerResourceProvider swaggerResourceProvider) {
this.swaggerResourceProvider = swaggerResourceProvider;
}
@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<>(swaggerResourceProvider.get(), HttpStatus.OK);
}
}
AppGateway文件如下:
package com.liazhan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @version V1.0
* @description: 网关入口类
* @author: Liazhan
* @date: 2020/4/10 14:35
*/
@SpringBootApplication
public class AppGateway {
public static void main(String[] args) {
SpringApplication.run(AppGateway.class,args);
}
}
application.yml文件如下,网关的端口一般设置成80端口:
server:
port: 80
eureka:
client:
service-url:
defaultZone: http://localhost:8100/eureka/
spring:
application:
name: liazhan-gateway
cloud:
gateway:
discovery:
locator:
enabled: true
routes:
- id: service_member
uri: lb://LIAZHAN-MEMBER
order: 0
predicates:
- Path=/liazhan-member/**
filters:
- StripPrefix=1
- id: service_weixin
uri: lb://LIAZHAN-WEIXIN
order: 0
predicates:
- Path=/liazhan-weixin/**
filters:
- StripPrefix=1
logging:
level:
org.springframework.cloud.gateway: debug
启动网关入口类
发现报错了
Parameter 0 of method modifyRequestBodyGatewayFilterFactory in org.springframework.cloud.gateway.config.GatewayAutoConfiguration required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer' that could not be found.
出现这个错误的原因是,gateway使用的是webflux
而我们在父项目shop-parent配置了web依赖,那么我们的网关项目也会继承依赖web
<!-- web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
而web和webflux会出现冲突。
因此,我们通过将父项目shop-parent的web依赖,移动到shop-service-api就可以解决这个问题。
我们再次启动网关入口类,不会再出现之前的问题。
访问http://localhost/swagger-ui.html
通过图中红色方框圈住的那个下拉框,可以切换到微信服务的接口文档。
如此,便实现了gateway统一管理swagger文档。
并且,我们可以通过gateway聚合Api,
访问微信服务的test接口可以通过访问http://localhost/liazhan-weixin/test
访问会员服务的callWeiXin接口可以通过访问http://localhost/liazhan-member/callWeiXin
github项目地址https://github.com/liazhan/shop-project/tree/0a289f6b5f2d8f4cecabfbe89f149ea4576c3c42
版本号为0a289f6b5f2d8f4cecabfbe89f149ea4576c3c42