SpringCloud学习:Gateway+Swagger2配置使用说明手册
gateway IP与Port
地址:http://IP:Port/swagger-ui.html
效果如下图:
可以通过右上角下拉,选择不同的服务,Swagger2还有一个功能就是支持页面直接调用调试,详细配置如下:
1.pom依赖引入
gateway中引入
<!-- swagger2 restful接口文档在线自动生成+功能测试 -->
<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>
微服务中引入
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
2.配置
1.gateway配置
将swagger配置在网关层,可以将所有配置在网关的微服务接口集中到一个页面
首先,需要在网关微服务新增一个Controller,用于swagger UI前端交互
@RestController
@RequestMapping("/swagger-resources")
public class SwaggerResourceController {
@Autowired(required = false)
private SecurityConfiguration securityConfiguration;
@Autowired(required = false)
private UiConfiguration uiConfiguration;
private final SwaggerResourcesProvider swaggerResources;
@Autowired
public SwaggerResourceController(SwaggerResourcesProvider swaggerResources) {
this.swaggerResources = swaggerResources;
}
@GetMapping("/configuration/security")
public Mono<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
因为Swagger暂不支持webflux项目,所以Gateway里不能配置SwaggerConfig,也就是说Gateway无法提供自身API。配置SwaggerProvider,获取Api-doc,即SwaggerResources
@Component
@Primary
public class SwaggerProvider implements SwaggerResourcesProvider {
public static final String API_URI = "/v2/api-docs";
public static final String NEW_API_URI = "/v2/api-docs?group="; // 这里访问设置的分组文档
@Autowired
private RouteLocator routeLocator;
@Autowired
private GatewayProperties gatewayProperties;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
//取出gateway的route
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
//结合配置的route-路径(Path),和route过滤,只获取有效的route节点
gatewayProperties.getRoutes().stream().filter(routeDefinition -> routes.contains(routeDefinition.getId()))
.forEach(routeDefinition -> routeDefinition.getPredicates().stream()
.filter(predicateDefinition -> ("Path").equalsIgnoreCase(predicateDefinition.getName()))
.forEach(predicateDefinition -> resources.add(swaggerResource(routeDefinition.getId(),
predicateDefinition.getArgs().get(NameUtils.GENERATED_NAME_PREFIX + "0")
.replace("/**", API_URI)))));//NEW_API_URI + routeDefinition.getId()
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;
}
}
2.服务配置
在需要接口发布的微服务中,新增Swagger配置类
@Configuration
@EnableSwagger2
public class SwaggerConfig {
@Autowired
private TypeResolver typeResolver;
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
// api接口路径,即controller层路径
.apis(RequestHandlerSelectors.basePackage("com.sinosig.sluw.application.controller"))
// 指定路径处理PathSelectors.any()代表所有的路径(除了被@ApiIgnore指定的请求)
.paths(PathSelectors.any())
.build()
.alternateTypeRules(
newRule(
typeResolver.resolve(
DeferredResult.class,
typeResolver.resolve(GenericType.class, WildcardType.class)
),
typeResolver.resolve(WildcardType.class)
)
)
// 支持的协议
.protocols(newHashSet("https", "http"))
.securitySchemes(securitySchemes())
.securityContexts(securityContexts());
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("寿险人核系统api")
.description("寿险人核系统接口")
.version("1.0")
.build();
}
/**
* 设置授权信息
*/
private List<ApiKey> securitySchemes() {
// 在请求头header添加一个名为Authorization的token
return Collections.singletonList(new ApiKey(HttpHeaders.AUTHORIZATION, "token", "header"));
}
/**
* 授权信息全局应用
*/
private List<SecurityContext> securityContexts() {
return Collections.singletonList(
SecurityContext.builder()
.securityReferences(
Collections.singletonList(new SecurityReference("Authorization",
new AuthorizationScope[]{new AuthorizationScope("global", "")}
)))
// 可通过配置正则表达式去排除一些不需要携带token访问的接口 这里不做特殊处理,全部接口访问都需要携带
// 比如.forPaths(PathSelectors.regex("^(?!auth).*$")) 对所有包含"auth"的接口不需要使用securitySchemes
.forPaths(PathSelectors.any())
.build()
);
}
@SafeVarargs
private final <T> Set<T> newHashSet(T... ts) {
if (ts.length > 0) {
return new LinkedHashSet<>(Arrays.asList(ts));
}
return null;
}
}
三、使用
微服务中需要发布的接口,开发可参考以下规范:
其中Api开头的注解为swagger专用注解
@Api(tags = "用户管理")
@RestController
@RequestMapping(value = "/users") // 通过这里配置使下面的映射都在/users下
public class SwapperTestController {
// 创建线程安全的Map,模拟users信息的存储
static Map<Long, User> users = Collections.synchronizedMap(new HashMap<>());
@GetMapping("/")
@ApiOperation(value = "获取用户列表")
public List<User> getUserList() {
List<User> r = new ArrayList<>(users.values());
return r;
}
@PostMapping("/")
@ApiOperation(value = "创建用户", notes = "根据User对象创建用户")
public String postUser(@RequestBody User user) {
users.put(user.getId(), user);
return "success";
}
@GetMapping("/{id}")
@ApiOperation(value = "获取用户详细信息", notes = "根据url的id来获取用户详细信息")
public User getUser(@PathVariable Long id) {
return users.get(id);
}
@PutMapping("/{id}")
@ApiImplicitParam(paramType = "path", dataType = "Long", name = "id", value = "用户编号", required = true, example = "1")
@ApiOperation(value = "更新用户详细信息", notes = "根据url的id来指定更新对象,并根据传过来的user信息来更新用户详细信息")
public String putUser(@PathVariable Long id, @RequestBody User user) {
User u = users.get(id);
u.setName(user.getName());
u.setAge(user.getAge());
users.put(id, u);
return "success";
}
@DeleteMapping("/{id}")
@ApiOperation(value = "删除用户", notes = "根据url的id来指定删除对象")
public String deleteUser(@PathVariable Long id) {
users.remove(id);
return "success";
}
}
@Data
@ApiModel(description="用户实体")
class User {
@ApiModelProperty("用户编号")
private Long id;
@ApiModelProperty("用户姓名")
private String name;
@ApiModelProperty("用户年龄")
private Integer age;
}
如有问题,欢迎批评指正,创作不易,欢迎一键三连