SpringCloud-gateway全局GlobalFilter获取post的请求参数

xiaoxiao2025-05-16  35

gateway里面可以自定义普通filter,也可以创建自定义的GlobalFilter。

GlobalFilter实际上还是比较常用的,譬如可以在GlobalFilter里做日志处理、认证鉴权等,这里就涉及一个获取到请求参数的问题。

用户发起Get、Post请求,经过网关gateway,gateway的GlobalFilter进行拦截——获取参数——处理并包装——转到下一级,我们就来看看该怎么获取请求的参数。

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.6.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> <spring-cloud.version>Finchley.SR1</spring-cloud.version> </properties>

Get请求

/** * @author wuweifeng wrote on 2018/10/24. */ @Component public class AuthSignFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getQueryParams().getFirst("authToken"); if (token == null || token.isEmpty()) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return 0; } }

这里定义了一个GlobalFilter,如果是Get请求,就可以通过getQueryParams().getFirst("你的key")的方式来获取。

可以看到已经获取到了Get请求的参数,如果有多个请求参数,就可以通过遍历exchange.getRequest().getQueryParams()来获取。

Post请求

post请求的传参获取相对比较麻烦一些,gateway采用了webflux的方式来封装的请求体。

我们知道post常用的两种传参content-type是application/x-www-form-urlencoded和application/json,这两种方式还是有区别的。

下面来看一下获取Post请求体的方法,关于webflux获取内容的教程请看上一篇。

package com.example.gateway.filter; import io.netty.buffer.ByteBufAllocator; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.core.io.buffer.DataBufferUtils; import org.springframework.core.io.buffer.NettyDataBufferFactory; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpRequestDecorator; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.net.URI; import java.nio.CharBuffer; import java.nio.charset.StandardCharsets; import java.util.Map; import java.util.concurrent.atomic.AtomicReference; /** * @author wuweifeng wrote on 2018/10/24. */ @Component public class AuthSignFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { ServerHttpRequest serverHttpRequest = exchange.getRequest(); String method = serverHttpRequest.getMethodValue(); if ("POST".equals(method)) { //从请求里获取Post请求体 String bodyStr = resolveBodyFromRequest(serverHttpRequest); //TODO 得到Post请求的请求参数后,做你想做的事 //下面的将请求体再次封装写回到request里,传到下一级,否则,由于请求体已被消费,后续的服务将取不到值 URI uri = serverHttpRequest.getURI(); ServerHttpRequest request = serverHttpRequest.mutate().uri(uri).build(); DataBuffer bodyDataBuffer = stringBuffer(bodyStr); Flux<DataBuffer> bodyFlux = Flux.just(bodyDataBuffer); request = new ServerHttpRequestDecorator(request) { @Override public Flux<DataBuffer> getBody() { return bodyFlux; } }; //封装request,传给下一级 return chain.filter(exchange.mutate().request(request).build()); } else if ("GET".equals(method)) { Map requestQueryParams = serverHttpRequest.getQueryParams(); //TODO 得到Get请求的请求参数后,做你想做的事 return chain.filter(exchange); } return chain.filter(exchange); } /** * 从Flux<DataBuffer>中获取字符串的方法 * @return 请求体 */ private String resolveBodyFromRequest(ServerHttpRequest serverHttpRequest) { //获取请求体 Flux<DataBuffer> body = serverHttpRequest.getBody(); AtomicReference<String> bodyRef = new AtomicReference<>(); body.subscribe(buffer -> { CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer()); DataBufferUtils.release(buffer); bodyRef.set(charBuffer.toString()); }); //获取request body return bodyRef.get(); } private DataBuffer stringBuffer(String value) { byte[] bytes = value.getBytes(StandardCharsets.UTF_8); NettyDataBufferFactory nettyDataBufferFactory = new NettyDataBufferFactory(ByteBufAllocator.DEFAULT); DataBuffer buffer = nettyDataBufferFactory.allocateBuffer(bytes.length); buffer.write(bytes); return buffer; } @Override public int getOrder() { return 0; } }

这里有详细的获取Post请求体的方法,无论是application/x-www-form-urlencoded和application/json都可以通过上面的方式。

看结果:

下面是@RequestBody形式的

这是后端消费的服务代码

也能正常接收@RequestBody请求并解析。

 

 

 

转载请注明原文地址: https://www.6miu.com/read-5030206.html

最新回复(0)