swagger在微服务下的实战应用(微服务整合token认证规范化入参)
Posted 张子行的博客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了swagger在微服务下的实战应用(微服务整合token认证规范化入参)相关的知识,希望对你有一定的参考价值。
本文目录
前言
6月19入的职到现在的7月27号,没错我已经实习了1个多月了,emmm怎么来说呢,拿我在学校敲代码的状态来比喻吧,如果把我在学校敲的代码比喻成一匹矫健驰骋在草原的黑马,那么我在公司敲的代码就更像是正规军,驰骋在赛场的汗血宝马了。
个人所感
以前在学校没怎么重视网络编程这块,即使以前有看过springCloud、duuble相关的视频,但是当时看视频的时候觉着这样开发项目太繁琐了,也没有坚持去系统化的去总结这一块的内容。以前我也刷到过牛客网上那些牛逼简历上写的项目是手写RPC框架、基于scoket开发的实时在线聊天系统相关的项目,当时觉着这些技术简直可以用俩个字“牛逼”来形容。当时本人痴迷于一个集合类、spring框架的源码分析就没有太注意这一块的技术。但是现在在公司开发的是一个微服务项目,核心业务都是涉及到网络编程相关的,迫于压力也是对于技术的一种热爱,于是我现在研究起了微服务相关框架的使用、源码、scoket、netty、dubbo、springCloud这些技术了,后续会陆续更新相关文章。
模块间依赖关系
email:依赖payment模块
gateway:网关负责路由相关到对应的实例(注册中心用的nacos)
payment:单独的模块
email、payment模块添加swagger依赖支持
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.20</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
email、payment模块开启swagger模块配置
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.context.request.async.DeferredResult;
import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ResponseMessageBuilder;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ResponseMessage;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import java.util.Arrays;
@Configuration
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class Swagger2Config {
@Bean
public Docket customDocket() {
return new Docket(DocumentationType.SWAGGER_2)
.genericModelSubstitutes(DeferredResult.class)
.useDefaultResponseMessages(false)
.forCodeGeneration(false)
.pathMapping("/")
.apiInfo(apiInfo())
.select()
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("接口文档title")
.description("接口文档说明")
.version("1.0.0")
.build();
}
}
网关模块配置(重点)
添加swagger接口支撑
/**
* zzh
*/
@RestController
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<ResponseEntity<SecurityConfiguration>> securityConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(securityConfiguration).orElse(SecurityConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources/configuration/ui")
public Mono<ResponseEntity<UiConfiguration>> uiConfiguration() {
return Mono.just(new ResponseEntity<>(
Optional.ofNullable(uiConfiguration).orElse(UiConfigurationBuilder.builder().build()), HttpStatus.OK));
}
@GetMapping("/swagger-resources")
public Mono<ResponseEntity> swaggerResources() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
@GetMapping("/")
public Mono<ResponseEntity> swaggerResourcesN() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
@GetMapping("/csrf")
public Mono<ResponseEntity> swaggerResourcesCsrf() {
return Mono.just((new ResponseEntity<>(swaggerResources.get(), HttpStatus.OK)));
}
}
对swagger请求进行过滤(可有可无)
/**
* zzh
*/
@Component
public class SwaggerHeaderFilter extends AbstractGatewayFilterFactory {
private static final String HEADER_NAME = "X-Forwarded-Prefix";
@Override
public GatewayFilter apply(Object config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
String path = request.getURI().getPath();
if (!StringUtils.endsWithIgnoreCase(path, SwaggerProvider.API_URI)) {
return chain.filter(exchange);
}
String basePath = path.substring(0, path.lastIndexOf(SwaggerProvider.API_URI));
ServerHttpRequest newRequest = request.mutate().header(HEADER_NAME, basePath).build();
ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
return chain.filter(newExchange);
};
}
}
全局swagger配置(放在网关模块)
/**
* 全局swagger配置
*/
@Component
@Primary
@AllArgsConstructor
public class SwaggerProvider implements SwaggerResourcesProvider {
//注意这个地址
public static final String API_URI = "/v2/api-docs?urls.primaryName";
private final RouteLocator routeLocator;
private final GatewayProperties gatewayProperties;
/**
* swagger会与返回值中的SwaggerResource进行路径匹配,如果匹配不到那么会出现swagger页面404无法访问的情况
*
* @return
*/
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
List<String> routes = new ArrayList<>();
routeLocator.getRoutes().subscribe(route -> routes.add(route.getId()));
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")
//swagger API地址
.replace("/**", 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;
}
}
网关路由配置
server:
port: 8005
spring:
application:
name: gateway
cloud:
discovery:
locator:
enabled: true
gateway:
routes:
- id: email_id
uri: lb://email
predicates:
- Path=/email/**
filters:
- name: SwaggerHeaderFilter
- StripPrefix=1
- id: payment_id
uri: lb://payment
predicates:
- Path=/payment/**
filters:
- name: SwaggerHeaderFilter
- StripPrefix=1
nacos:
discovery:
server-addr: 127.0.0.1:8848
config:
server-addr: 127.0.0.1:8848
mybatis-plus:
mapper-locations: classpath:mapperXml/*.xml
全局token验证、方式一
在swagger配置文件中加入如下配置,每次请求都会把 name为 X-Auth-Token 的参数放入请求中进行请求
/**
* 对每个接口都添加token认证
*
* @return
*/
private List<Parameter> setHeaderToken() {
ParameterBuilder tokenPar = new ParameterBuilder();
List<Parameter> pars = new ArrayList<>();
tokenPar.name("X-Auth-Token").description("token").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
pars.add(tokenPar.build());
return pars;
}
加入swagger配置
全局token验证、方式二
一次添加模块下的所有接口下次请求都会携带 token
@Bean
public Docket customDocket() {
// 配置全局参数返回状态
java.util.List<ResponseMessage> resMsgList = Arrays.asList(
new ResponseMessageBuilder().code(200).message("成功!").build(),
new ResponseMessageBuilder().code(-1).message("失败!").build(),
new ResponseMessageBuilder().code(401).message("参数校验错误!").build(),
new ResponseMessageBuilder().code(403).message("没有权限操作,请后台添加相应权限!").build(),
new ResponseMessageBuilder().code(500).message("服务器内部异常,请稍后重试!").build(),
new ResponseMessageBuilder().code(501).message("请登录!").build());
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo()).select()
.apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
.paths(PathSelectors.any())
.build()
.globalResponseMessage(RequestMethod.GET, resMsgList)
.globalResponseMessage(RequestMethod.POST, resMsgList)
.globalResponseMessage(RequestMethod.PUT, resMsgList)
.globalResponseMessage(RequestMethod.DELETE, resMsgList)
.globalOperationParameters(setHeaderToken())
.securityContexts(securityContexts());
}
/**
* 以下代码添加全局token配置
*
* @return
*/
private List<ApiKey> security() {
ArrayList list = new ArrayList();
list.add(new ApiKey("Authorization", "Authorization", "header"));
return list;
}
private List<SecurityContext> securityContexts() {
List<SecurityContext> securityContexts = new ArrayList<>();
securityContexts.add(
SecurityContext.builder()
.securityReferences(defaultAuth())
.forPaths(PathSelectors.regex("^(?!auth).*$"))
.build());
return securityContexts;
}
private List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope = new AuthorizationScope("gl以上是关于swagger在微服务下的实战应用(微服务整合token认证规范化入参)的主要内容,如果未能解决你的问题,请参考以下文章
SpringCloud分布式事务实战在微服务1中创建整合函数,调用微服务2
SpringBoot系列十一:SpringBoot整合Restful架构(使用 RestTemplate 模版实现 Rest 服务调用Swagger 集成动态修改日志级别)