在网关全局过滤器中中进行的一些操作,开发可能会用到,持续更新
直接返回字符串或json格式
获取请求头中token
拿到get或者post请求中的参数
拿到请求返回值
处理网关出现的异常(如其他服务不可用的异常)
动态路由(在url中指定服务名和接口名)
……………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………
代码如下
package com.example.filter;
import com.example.code.Res;
import com.example.code.ResultCode;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.reactivestreams.Publisher;
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.DataBufferFactory;
import org.springframework.core.io.buffer.DataBufferUtils;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpResponseDecorator;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.zip.GZIPInputStream;
/**
* @author 刘通
* @date 2022年05月10日 10:52
*/
@Component
@Slf4j
public class MyGlobaTest implements GlobalFilter, Ordered {
// /**
// * 返回自定义json对象
// * @param exchange
// * @param chain
// * @return
// */
// @Override
// @SneakyThrows
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ObjectMapper objectMapper = new ObjectMapper();
// String s = objectMapper.writeValueAsString(Res.failed(ResultCode.FAILED,"失败咯"));
// ServerHttpResponse response = exchange.getResponse();
// response.setStatusCode(HttpStatus.OK);
// response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
// return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(s.getBytes()))));
// }
// /**
// * 获取token
// * @param exchange
// * @param chain
// * @return
// */
// @Override
// @SneakyThrows
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ServerHttpRequest request = exchange.getRequest();
// String authorization = request.getHeaders().getFirst("Authorization");
// if (!ObjectUtils.isEmpty(authorization)){
// authorization = authorization.replace("Bearer", "").trim();
// }
// return chain.filter(exchange);
// }
// /**
// * 获取get或者post请求参数
// * @param exchange
// * @param chain
// * @return
// */
// @Override
// @SneakyThrows
// public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// ServerHttpRequest request = exchange.getRequest();
// String method = request.getMethod().name();
// if (HttpPost.METHOD_NAME.equals(method)) {
// return DataBufferUtils.join(exchange.getRequest().getBody())
// .flatMap(dataBuffer -> {
// byte[] bytes = new byte[dataBuffer.readableByteCount()];
// dataBuffer.read(bytes);
// // 拿到post请求参数
// String bodyString = new String(bytes, StandardCharsets.UTF_8);
// exchange.getAttributes().put("POST_BODY", bodyString);
// DataBufferUtils.release(dataBuffer);
// Flux<DataBuffer> cachedFlux = Flux.defer(() -> {
// DataBuffer buffer = exchange.getResponse().bufferFactory()
// .wrap(bytes);
// return Mono.just(buffer);
// });
//
// ServerHttpRequest mutatedRequest = new ServerHttpRequestDecorator(
// exchange.getRequest()) {
// @Override
// public Flux<DataBuffer> getBody() {
// return cachedFlux;
// }
// };
// return chain.filter(exchange.mutate().request(mutatedRequest).build());
// });
// }else {
// // 拿到get请求参数
// MultiValueMap<String, String> queryParams = request.getQueryParams();
// ObjectMapper obj = new ObjectMapper();
// String valueAsString = obj.writeValueAsString(queryParams);
// return chain.filter(exchange);
// }
// }
/**
* 在网关拿到接口返回数据
* @param exchange
* @param chain
* @return
*/
@SneakyThrows
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpResponseDecorator responseBody = getResponseBody(exchange);
return chain.filter(exchange.mutate().response(responseBody).build());
}
/**
* order须为负的才生效,-1 is response write filter, must be called before that
* @param exchange
* @return
*/
public ServerHttpResponseDecorator getResponseBody(ServerWebExchange exchange){
ServerHttpResponse originalResponse = exchange.getResponse();
DataBufferFactory bufferFactory = originalResponse.bufferFactory();
return new ServerHttpResponseDecorator(originalResponse) {
@Override
public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
if (body instanceof Flux) {
Flux<? extends DataBuffer> fluxBody = (Flux<? extends DataBuffer>) body;
return super.writeWith(fluxBody.buffer().map(dataBuffer -> {
DataBufferFactory dataBufferFactory = new DefaultDataBufferFactory();
DataBuffer join = dataBufferFactory.join(dataBuffer);
byte[] content = new byte[join.readableByteCount()];
join.read(content);
//释放掉内存
DataBufferUtils.release(join);
String s = new String(content, StandardCharsets.UTF_8);
List<String> strings = exchange.getResponse().getHeaders().get(HttpHeaders.CONTENT_ENCODING);
if (!CollectionUtils.isEmpty(strings) && strings.contains("gzip")) {
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(content), content.length);
StringWriter writer = new StringWriter();
IOUtils.copy(gzipInputStream, writer, "UTF-8");
s = writer.toString();
} catch (IOException e) {
log.error("====Gzip IO error", e);
} finally {
if (gzipInputStream != null) {
try {
gzipInputStream.close();
} catch (IOException e) {
log.error("===Gzip IO close error", e);
}
}
}
} else {
s = new String(content, StandardCharsets.UTF_8);
}
return bufferFactory.wrap(content);
}));
}
return super.writeWith(body);
}
};
}
@Override
public int getOrder() {
return -2;
}
}
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
@RequiredArgsConstructor
// 网关处理异常
public class GatewayExceptionConfiguration implements ErrorWebExceptionHandler {
@Override
@SneakyThrows
public Mono<Void> handle(ServerWebExchange serverWebExchange, Throwable throwable) {
ServerHttpResponse response = serverWebExchange.getResponse();
response.setStatusCode(HttpStatus.OK);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(Res.failed(503,throwable.getLocalizedMessage()));
return response.writeAndFlushWith(Flux.just(ByteBufFlux.just(response.bufferFactory().wrap(json.getBytes()))));
}
}
@Component
@Slf4j
public class DynamicEverythingFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 动态修改路由开始
ServerHttpRequest request = exchange.getRequest();
MultiValueMap<String, String> queryParams = request.getQueryParams();
if (ObjectUtils.isEmpty(queryParams.get("服务名参数"))){
// TODO: 2022/9/17 返回错误
}
if (ObjectUtils.isEmpty(queryParams.get("接口名参数"))){
// TODO: 2022/9/17 返回错误
}
//lb
String service = queryParams.get("服务名参数").get(0);
//方法
String function = queryParams.get("接口名参数").get(0);
Route route =exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// 修改路由规则
Route newRoute = Route.async()
.asyncPredicate(route.getPredicate())
.filters(route.getFilters())
.id(route.getId())
.order(route.getOrder())
.uri("lb://"+service)
.build();
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, newRoute);
String path = "通过网关的基础路径如http://localhost:9000/small/";
String newPath = path+function;
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(newPath);
//排除服务名参数和接口名参数
if (queryParams.size()>2&& HttpMethod.GET.name().equals(request.getMethodValue())){
for (String next : queryParams.keySet()) {
if (!"服务名参数".equals(next)&&!"接口名参数".equals(next)){
// get请求的话,其他参数加入
builder.queryParam(next, queryParams.get(next));
}
}
}
URI uri = builder.build().toUri();
// 构建新的请求
ServerHttpRequest newRequest = request.mutate().uri(uri).build();
return chain.filter(exchange.mutate().request(newRequest).build());
}
@Override
public int getOrder() {
return -50;
}
}