spring cloud gateway 获取body体中的内容
实现GlobalFilter
@Component
@Slf4j
public class RequestGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
URI URIPath = request.getURI();
String path = request.getPath().value();
// 获取请求方式
String method = request.getMethodValue();
// 获取请求头
HttpHeaders header = request.getHeaders();
// 根据请求头参数名获取值
String heardValue = header.getFirst("参数名");
// 获取请求参数
MultiValueMap<String, String> queryParams = request.getQueryParams();
Map<String, String> map = queryParams.toSingleValueMap();
if (HttpMethod.GET.name().equals(methodValue)) {
// get请求.......
}
if (HttpMethod.POST.name().equals(methodValue)) {
// postt请求.......
}
// 针对错误的提示处理
if("发生错误") {
Map<String,Object> map = new HashMap<>();
map.put("code","-1");
map.put("msg","发送错误,自己定义");
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
DataBuffer buffer = response.bufferFactory().wrap(JSONUtil.toJsonStr(map).getBytes(StandardCharsets.UTF_8));
return response.writeWith(Mono.just(buffer));
}
return chain.filter(exchange);
}
@Override
public int getOrder() {
// 过滤器执行顺序,数值越小,越早执行
return -100;
}
// 获取请求体body内容
public String getJSONStr(ServerWebExchange exchange){
Flux<DataBuffer> body = exchange.getRequest().getBody();
AtomicReference<String> bodyRef = new AtomicReference<>();
body.subscribe(buffer -> {
CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
DataBufferUtils.release(buffer);
bodyRef.set(charBuffer.toString());
});
return bodyRef.get();
}
// 如果要在网关通过feign调用其它服务,要添加以下代码
/**
* 向容器中注册一个 HttpMessageConverters
*
* @param converters converters
* @return 返回结果
*/
@Bean
@ConditionalOnMissingBean
public HttpMessageConverters messageConverters(ObjectProvider<HttpMessageConverter<?>> converters) {
return new HttpMessageConverters(converters.orderedStream().collect(Collectors.toList()));
}
}
当然以上代码还不够,是无法获取到数据的,request.getbody里面的数据是在spring cloud内置的另外一个拦截器(AdaptCachedBodyGlobalFilter)中初始化数据的
1 . AdaptCachedBodyGlobalFilter类中通过routesToCache判断当前路由是否缓存body体里面的数据到request里面,然后重构request,通过org.springframework.cloud.gateway.support.ServerWebExchangeUtils#cacheRequestBody静态方法获取数据
2. AdaptCachedBodyGlobalFilter实现了ApplicationListener接口监听了EnableBodyCachingEvent事件,因此我们需要缓存对应路由的body,需要发布对应的EnableBodyCachingEvent事件
3. AdaptCachedBodyGlobalFilter类实现了接口ApplicationListener事件监听监听EnableBodyCachingEvent事件可以使用spring内置事件处理器处理代码如下
编写配置类
```bash
@Component
public class GatewayCommonConfig{
@Autowired
private GatewayProperties gatewayProperties;
@Autowired
private ApplicationContext applicationContext;
@PostConstruct
public void init(){
//发布对应路由的EnableBodyCachingEvent事件
gatewayProperties.getRoutes().forEach(e->{
EnableBodyCachingEvent enableBodyCachingEvent = new EnableBodyCachingEvent(new Object(), e.getId());
//发布事件
applicationContext.publishEvent(enableBodyCachingEvent);
});
}
}
这个时候在自定义的拦截器中使用request.getbody就可以获取到数据
此方法来自:https://www.zhihu.com/tardis/bd/art/471402045?source_id=1001