项目中使用gateway做路由,根据请求头访问不同的api,api中使用openfegin,去访问对应的service。为了说明配置,摘取项目核心的代码。包括gateway,user-api,standard-api。
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>
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);
}
}
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;
}
}
这两个类基本上差不多,我只贴其中一个
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();
}
}
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,这里我贴几个大概的参考下。
/**
* 新增标准信息
* @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);
}
/**
* @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,不能出现"/"否则会报错。