新项目需要在getway统一做入参、出参加解密,记录日志。记录一下form,x-www-form-urlencoded , json 这几种修改数据的方式。 gateway做拦截器是实现GlobalFilter接口,修改json方式网上有很多文章,后来又想研究研究能不能实现修改form-data参数,以及文件请求,后者文章不多大部分是怎么读数据的教学。现在发一下我的实现方式。 使用的gateway版本是2.2.1.RELEASE cloud版本Greenwich.SR2

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

Mono mono = chain.filter(exchange);

ServerHttpRequest request = exchange.getRequest();

MediaType contentType = request.getHeaders().getContentType();

if (Objects.nonNull(contentType) && Objects.nonNull(exchange.getRequest().getMethod())

&& exchange.getRequest().getMethod().equals(HttpMethod.POST)) {

if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {

// json 请求体处理

mono = this.transferBody(exchange, chain);

}else if(MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)){

// multipart/form-data处理

mono = this.fileRequest(contentType,exchange,chain);

}else if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)){

// x-www-form-urlencoded 格式处理

mono = this.xwFromBody(exchange,chain);

}

}else{

if(exchange.getRequest().getMethod().equals(HttpMethod.GET)){

Map queryParams = exchange.getRequest().getQueryParams().toSingleValueMap();

log.info("queryParams:{}", queryParams);

}

}

return mono;

}

修改json数据

/**

* 修改修改body参数

*/

private Mono transferBody(ServerWebExchange exchange, GatewayFilterChain chain) {

ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());

Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(Mono::just);

BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);

HttpHeaders headers = new HttpHeaders();

headers.putAll(exchange.getRequest().getHeaders());

headers.remove(HttpHeaders.CONTENT_LENGTH);

MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers);

ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();

requestBuilder.headers(k -> k.remove("Content-length"));

Mono mono = bodyInserter.insert(outputMessage, new BodyInserterContext())

.then(Mono.defer(() -> {

//解决body内数据过长读取不完整的问题

Flux body = outputMessage.getBody();

DataBufferHolder holder = new DataBufferHolder();

try{

body.subscribe(dataBuffer -> {

int len = dataBuffer.readableByteCount();

holder.length = len;

byte[] bytes = new byte[len];

dataBuffer.read(bytes);

DataBufferUtils.release(dataBuffer);

String oldBody = new String(bytes, StandardCharsets.UTF_8);

JsonNode jsonNode = objectMapper.readTree(in);

//到这可以读取数据,做校验之类的

//JsonNode token = oldDataJSON.get("token");

jsonNode .set("test","修改数据");

DataBuffer data = outputMessage.bufferFactory().allocateBuffer();

data.write(jsonNode.toString().getBytes(StandardCharsets.UTF_8));

holder.length = data.readableByteCount();

holder.dataBuffer=data;

});

}catch (Exception e){

if(e.getCause() instanceof ServiceException){

ServiceException e1 = (ServiceException) e.getCause();

return handleFailedRequest(exchange, JSONObject.toJSONString(CommonResponse.error(e1.getCode(), e1.getMessage())));

}

return handleFailedRequest(exchange, JSONObject.toJSONString(CommonResponse.error(SYSTEM_ERROR.getCode(), SYSTEM_ERROR.getMessage())));

}

ServerHttpRequestDecorator decorator = newDecorator(exchange,holder.length, Flux.just(holder.dataBuffer));

return chain.filter(exchange.mutate().request(decorator).build());

}));

return mono;

}

修改form表单参数,一般需要上传文件的请求用这个。数据读取都可以用json请求那个方法获取,但是带文件的请求用那个读了以后文件数据就变了,修改数据以后文件没法正常存储,所以按以下方式,直接读取字节然后拼接要改的数据

//修改form参数

private Mono fileRequest(MediaType contentType,ServerWebExchange exchange, GatewayFilterChain chain){

return DataBufferUtils.join(exchange.getRequest().getBody())

.flatMap(dataBuffer -> {

byte[] bytes = new byte[dataBuffer.readableByteCount()];

dataBuffer.read(bytes);

DataBufferUtils.release(dataBuffer);

// new String(bytes);

//添加一些自定义参数,或者校验

String oldBody = addPara(contentType.toString(), new String(bytes));

byte[] bytes1 = oldBody.getBytes();

//这里截取数组是因为 form请求体数据末尾有--/r/n,这里需要截一段然后拼接自定义的数据。数据格式可以看文章末尾的链接

byte[] bytes2 = byteMerger(Arrays.copyOf(bytes,bytes.length-4), bytes1);

Flux cachedFlux = Flux.defer(() -> {

DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes2);

DataBufferUtils.retain(buffer);

return Mono.just(buffer);

});

ServerHttpRequestDecorator mutatedRequest = newDecorator(exchange,bytes2.length,cachedFlux);

ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();

return ServerRequest.create(mutatedExchange, MESSAGE_READERS)

.bodyToMono(byte[].class)

.then(chain.filter(mutatedExchange));

});

}

/**

* 修改form参数

* @param contentType 请求类型

* @param bodyString 请求body信息

*/

@SneakyThrows

public static String addPara(String contentType, String bodyString) {

StringBuffer stringBuffer = new StringBuffer();

String boundary = contentType.substring(contentType.lastIndexOf("boundary=") + 9);//获取随机字符传信息

String boundary_end = StrUtil.format("--{}--\r\n", boundary);

Map formMap = Maps.newHashMap();

/**

*

* 根据自己需求进行对bodyString信息修改,例如下面,根据boundary对传入的bodyString进行了分割

* String[] split = bodyString.split(boundary);

* 然后将修改完后的信息封装到formMap中,需要注意的是,file文件需要以new FileResource(file, fileName)的形式当作value放到formMap中

*/

String part = "^\r\nContent-Disposition: form-data; name=\"([^/?]+)\"\r\n\r\n([^/?]+)\r\n--?$";

Pattern r = Pattern.compile(part);

String[] split = bodyString.split(boundary);

for(int x=1;x

Matcher m = r.matcher(split[x]);

if(m.find()){

String name = m.group(1);

String value = m.group(2);

System.out.println("name:"+name+" value:"+value);

// formMap.put(name,value);

}

}

formMap.put("test","添加自定义参数");

formMap.put("tcu",22222);

Integer count =0;

for (Map.Entry entry : formMap.entrySet()) {

stringBuffer.append(appendPart(boundary, entry.getKey(), entry.getValue(),count));

count++;

}

stringBuffer.append(boundary_end);//拼接结束信息

log.info(stringBuffer.toString());

return stringBuffer.toString();

}

修改x-www-form-urlencoded参数

/**

* 修改 x-www-form-urlencoded参数

* @param exchange

* @param chain

* @return

*/

private Mono xwFromBody(ServerWebExchange exchange, GatewayFilterChain chain){

ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());

Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(Mono::just);

BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);

HttpHeaders headers = new HttpHeaders();

headers.putAll(exchange.getRequest().getHeaders());

headers.remove(HttpHeaders.CONTENT_LENGTH);

MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers);

ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();

requestBuilder.headers(k -> k.remove("Content-length"));

return bodyInserter.insert(outputMessage, new BodyInserterContext())

.then(Mono.defer(() -> {

Flux body = outputMessage.getBody();

DataBufferHolder holder = new DataBufferHolder();

changeParamByXwForm(body,holder,outputMessage);

ServerHttpRequestDecorator decorator = newDecorator(exchange,holder.length, Flux.just(holder.dataBuffer));

return chain.filter(exchange.mutate().request(decorator).build());

}));

}

//修改 x-www-form-urlencoded参数

private void changeParamByXwForm(Flux body,DataBufferHolder holder,MyCachedBodyOutputMessage outputMessage){

body.subscribe(dataBuffer -> {

int len = dataBuffer.readableByteCount();

holder.length = len;

byte[] bytes = new byte[len];

dataBuffer.read(bytes);

DataBufferUtils.release(dataBuffer);

String oldBody = new String(bytes, StandardCharsets.UTF_8);

//直接拼接要改的数据就行

oldBody+="&tcu=123888";

DataBuffer data = outputMessage.bufferFactory().allocateBuffer();

data.write(oldBody.getBytes(StandardCharsets.UTF_8));

holder.length = data.readableByteCount();

holder.dataBuffer=data;

});

}

修改请求参数完整代码 ReadAndChangeResFilter .java

import cn.hutool.core.io.IORuntimeException;

import cn.hutool.core.io.resource.MultiResource;

import cn.hutool.core.io.resource.Resource;

import cn.hutool.core.util.ObjectUtil;

import cn.hutool.core.util.StrUtil;

import cn.hutool.http.ContentType;

import cn.hutool.http.HttpUtil;

import com.alibaba.fastjson.JSON;

import com.alibaba.fastjson.JSONObject;

import com.fasterxml.jackson.databind.JsonNode;

import com.fasterxml.jackson.databind.ObjectMapper;

import com.fasterxml.jackson.databind.node.ObjectNode;

import com.google.common.collect.Maps;

import lombok.SneakyThrows;

import lombok.extern.slf4j.Slf4j;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;

import org.springframework.cloud.gateway.filter.GlobalFilter;

import org.springframework.cloud.gateway.support.BodyInserterContext;

import org.springframework.core.io.buffer.DataBuffer;

import org.springframework.core.io.buffer.DataBufferUtils;

import org.springframework.http.*;

import org.springframework.http.codec.HttpMessageReader;

import org.springframework.http.server.reactive.ServerHttpRequest;

import org.springframework.http.server.reactive.ServerHttpRequestDecorator;

import org.springframework.stereotype.Component;

import org.springframework.web.reactive.function.BodyInserter;

import org.springframework.web.reactive.function.BodyInserters;

import org.springframework.web.reactive.function.server.HandlerStrategies;

import org.springframework.web.reactive.function.server.ServerRequest;

import org.springframework.web.server.ServerWebExchange;

import org.springframework.core.Ordered;

import reactor.core.publisher.Flux;

import reactor.core.publisher.Mono;

import java.io.IOException;

import java.nio.charset.StandardCharsets;

import java.util.*;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import static com.byaero.utm.common.constant.CommonErrorCodeEnum.SYSTEM_ERROR;

import static com.byaero.utm.common.constant.CommonErrorCodeEnum.TOKEN_NOT_EXISTENT_ERROR;

@Slf4j

@Component

public class ReadAndChangeResFilter implements GlobalFilter, Ordered {

private static final String CONTENT_DISPOSITION_TEMPLATE = "Content-Disposition: form-data; name=\"{}\"\r\n\r\n";

private static final String CONTENT_DISPOSITION_FILE_TEMPLATE = "Content-Disposition: form-data; name=\"{}\"; filename=\"{}\"\r\n";

private static final String CONTENT_TYPE_MULTIPART_PREFIX = ContentType.MULTIPART.getValue() + "; boundary=";

private static final String CONTENT_TYPE_FILE_TEMPLATE = "Content-Type: {}\r\n\r\n";

private final static String TOKEN_USERINFO_CACHE_FLAG = "TI-%s";

private static final List> MESSAGE_READERS = HandlerStrategies.withDefaults().messageReaders();

@Autowired

private RedisUtil redisUtil;

@Autowired

private UserConvert userConvert;

@Autowired

private ObjectMapper objectMapper;

@Autowired

private UserManager userManager;

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

Mono mono = chain.filter(exchange);

ServerHttpRequest request = exchange.getRequest();

MediaType contentType = request.getHeaders().getContentType();

final GatewayContext gatewayContext = new GatewayContext();

// ServerWebExchangeUtils.putUriTemplateVariables();

if (Objects.nonNull(contentType) && Objects.nonNull(exchange.getRequest().getMethod())

&& exchange.getRequest().getMethod().equals(HttpMethod.POST)) {

if (MediaType.APPLICATION_JSON.isCompatibleWith(contentType)) {

// json 请求体处理

mono = this.transferBody(exchange, chain);

}else if(MediaType.MULTIPART_FORM_DATA.isCompatibleWith(contentType)){

// multipart/form-data处理

mono = this.fileRequest(contentType,exchange,chain);

}else if(MediaType.APPLICATION_FORM_URLENCODED.isCompatibleWith(contentType)){

// x-www-form-urlencoded 格式处理

mono = this.xwFromBody(exchange,chain);

}

}else{

if(exchange.getRequest().getMethod().equals(HttpMethod.GET)){

Map queryParams = exchange.getRequest().getQueryParams().toSingleValueMap();

log.info("queryParams:{}", queryParams);

}

}

return mono;

}

//修改form参数

private Mono fileRequest(MediaType contentType,ServerWebExchange exchange, GatewayFilterChain chain){

return DataBufferUtils.join(exchange.getRequest().getBody())

.flatMap(dataBuffer -> {

byte[] bytes = new byte[dataBuffer.readableByteCount()];

dataBuffer.read(bytes);

DataBufferUtils.release(dataBuffer);

String oldBody = addPara(contentType.toString(), new String(bytes));

byte[] bytes1 = oldBody.getBytes();

byte[] bytes2 = byteMerger(Arrays.copyOf(bytes,bytes.length-4), bytes1);

Flux cachedFlux = Flux.defer(() -> {

DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes2);

DataBufferUtils.retain(buffer);

return Mono.just(buffer);

});

ServerHttpRequestDecorator mutatedRequest = newDecorator(exchange,bytes2.length,cachedFlux);

ServerWebExchange mutatedExchange = exchange.mutate().request(mutatedRequest).build();

return ServerRequest.create(mutatedExchange, MESSAGE_READERS)

.bodyToMono(byte[].class)

.then(chain.filter(mutatedExchange));

});

}

public static byte[] byteMerger(byte[] bt1, byte[] bt2){

byte[] bt3 = new byte[bt1.length+bt2.length];

System.arraycopy(bt1, 0, bt3, 0, bt1.length);

System.arraycopy(bt2, 0, bt3, bt1.length, bt2.length);

return bt3;

}

//修改 x-www-form-urlencoded参数

private void changeParamByXwForm(Flux body,DataBufferHolder holder,MyCachedBodyOutputMessage outputMessage){

body.subscribe(dataBuffer -> {

int len = dataBuffer.readableByteCount();

holder.length = len;

byte[] bytes = new byte[len];

dataBuffer.read(bytes);

DataBufferUtils.release(dataBuffer);

String oldBody = new String(bytes, StandardCharsets.UTF_8);

oldBody+="&test=修改数据";

DataBuffer data = outputMessage.bufferFactory().allocateBuffer();

data.write(oldBody.getBytes(StandardCharsets.UTF_8));

holder.length = data.readableByteCount();

holder.dataBuffer=data;

});

}

@Override

public int getOrder() {

return Ordered.HIGHEST_PRECEDENCE;

}

/**

* 修改 x-www-form-urlencoded参数

* @param exchange

* @param chain

* @return

*/

private Mono xwFromBody(ServerWebExchange exchange, GatewayFilterChain chain){

ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());

Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(Mono::just);

BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);

HttpHeaders headers = new HttpHeaders();

headers.putAll(exchange.getRequest().getHeaders());

headers.remove(HttpHeaders.CONTENT_LENGTH);

MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers);

ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();

requestBuilder.headers(k -> k.remove("Content-length"));

return bodyInserter.insert(outputMessage, new BodyInserterContext())

.then(Mono.defer(() -> {

Flux body = outputMessage.getBody();

DataBufferHolder holder = new DataBufferHolder();

changeParamByXwForm(body,holder,outputMessage);

ServerHttpRequestDecorator decorator = newDecorator(exchange,holder.length, Flux.just(holder.dataBuffer));

return chain.filter(exchange.mutate().request(decorator).build());

}));

}

/**

* 修改修改body参数

*/

private Mono transferBody(ServerWebExchange exchange, GatewayFilterChain chain) {

ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());

Mono modifiedBody = serverRequest.bodyToMono(String.class).flatMap(Mono::just);

BodyInserter bodyInserter = BodyInserters.fromPublisher(modifiedBody, String.class);

HttpHeaders headers = new HttpHeaders();

headers.putAll(exchange.getRequest().getHeaders());

headers.remove(HttpHeaders.CONTENT_LENGTH);

MyCachedBodyOutputMessage outputMessage = new MyCachedBodyOutputMessage(exchange, headers);

ServerHttpRequest.Builder requestBuilder = exchange.getRequest().mutate();

requestBuilder.headers(k -> k.remove("Content-length"));

Mono mono = bodyInserter.insert(outputMessage, new BodyInserterContext())

.then(Mono.defer(() -> {

//解决body内数据过长读取不完整的问题

Flux body = outputMessage.getBody();

DataBufferHolder holder = new DataBufferHolder();

try{

body.subscribe(dataBuffer -> {

int len = dataBuffer.readableByteCount();

holder.length = len;

byte[] bytes = new byte[len];

dataBuffer.read(bytes);

DataBufferUtils.release(dataBuffer);

String oldBody = new String(bytes, StandardCharsets.UTF_8);

JsonNode jsonNode = readNode(oldBody);

checkTokenAndSaveUser((ObjectNode)jsonNode);

DataBuffer data = outputMessage.bufferFactory().allocateBuffer();

data.write(jsonNode.toString().getBytes(StandardCharsets.UTF_8));

holder.length = data.readableByteCount();

holder.dataBuffer=data;

});

}catch (Exception e){

if(e.getCause() instanceof ServiceException){

ServiceException e1 = (ServiceException) e.getCause();

return handleFailedRequest(exchange, JSONObject.toJSONString(CommonResponse.error(e1.getCode(), e1.getMessage())));

}

return handleFailedRequest(exchange, JSONObject.toJSONString(CommonResponse.error(SYSTEM_ERROR.getCode(), SYSTEM_ERROR.getMessage())));

}

ServerHttpRequestDecorator decorator = newDecorator(exchange,holder.length, Flux.just(holder.dataBuffer));

return chain.filter(exchange.mutate().request(decorator).build());

}));

return mono;

}

private void checkTokenAndSaveUser(ObjectNode oldDataJSON) throws ServiceException{

JsonNode token = oldDataJSON.get("token");

if(token==null){

throw new ServiceException(TOKEN_NOT_EXISTENT_ERROR.getCode(), TOKEN_NOT_EXISTENT_ERROR.getMessage());

}

Object userIdCacheKey = redisUtil.get(token.asText());

if(userIdCacheKey!=null){

Object cacheInfo = redisUtil.get(userIdCacheKey+"");

UserCacheBO cacheDataObj = null;

if(cacheInfo!=null){

cacheDataObj = (UserCacheBO) cacheInfo;

}else{

cacheDataObj = userManager.flushUserCache(userIdCacheKey+"",token.asText());

}

UserBO userBO = userConvert.cacheToBo(cacheDataObj);

try {

String s = JSON.toJSONString(userBO);

JsonNode node = objectMapper.readTree(s);

oldDataJSON.set("userBO",node);

} catch (IOException e) {

e.printStackTrace();

throw new IllegalStateException(e);

}

}else{

throw new ServiceException(TOKEN_NOT_EXISTENT_ERROR.getCode(), TOKEN_NOT_EXISTENT_ERROR.getMessage());

}

}

private Mono handleFailedRequest(ServerWebExchange exchange, String message) {

byte[] bytes = message.getBytes(StandardCharsets.UTF_8);

DataBuffer buffer = exchange.getResponse().bufferFactory().wrap(bytes);

exchange.getResponse().setStatusCode(HttpStatus.OK);

return exchange.getResponse().writeWith(Flux.just(buffer));

}

private JsonNode readNode(String in) {

try {

return objectMapper.readTree(in);

} catch (Exception e) {

throw new IllegalStateException(e);

}

}

private class DataBufferHolder {

DataBuffer dataBuffer;

int length;

}

/**

* 修改form参数

* @param contentType 请求类型

* @param bodyString 请求body信息

*/

@SneakyThrows

public static String addPara(String contentType, String bodyString) {

StringBuffer stringBuffer = new StringBuffer();

String boundary = contentType.substring(contentType.lastIndexOf("boundary=") + 9);//获取随机字符传信息

String boundary_end = StrUtil.format("--{}--\r\n", boundary);

Map formMap = Maps.newHashMap();

/**

*

* 根据自己需求进行对bodyString信息修改,例如下面,根据boundary对传入的bodyString进行了分割

* String[] split = bodyString.split(boundary);

* 然后将修改完后的信息封装到formMap中,需要注意的是,file文件需要以new FileResource(file, fileName)的形式当作value放到formMap中

*/

String part = "^\r\nContent-Disposition: form-data; name=\"([^/?]+)\"\r\n\r\n([^/?]+)\r\n--?$";

Pattern r = Pattern.compile(part);

String[] split = bodyString.split(boundary);

for(int x=1;x

Matcher m = r.matcher(split[x]);

if(m.find()){

String name = m.group(1);

String value = m.group(2);

System.out.println("name:"+name+" value:"+value);

// formMap.put(name,value);

}

}

formMap.put("ft",11111);

formMap.put("tcu",22222);

Integer count =0;

for (Map.Entry entry : formMap.entrySet()) {

stringBuffer.append(appendPart(boundary, entry.getKey(), entry.getValue(),count));

count++;

}

stringBuffer.append(boundary_end);//拼接结束信息

log.info(stringBuffer.toString());

return stringBuffer.toString();

}

public ServerHttpRequestDecorator newDecorator(ServerWebExchange exchange,long dataLength,Flux body){

return new ServerHttpRequestDecorator(

exchange.getRequest()) {

@Override

public HttpHeaders getHeaders() {

//数据长度变了以后 需要修改header里的数据,不然接收数据时会异常

//我看别人说删除会自动补充数据长度,但我这个版本不太行

// long contentLength = headers.getContentLength();

HttpHeaders httpHeaders = new HttpHeaders();

httpHeaders.putAll(super.getHeaders());

// if (contentLength > 0) {

httpHeaders.setContentLength(dataLength);

// } else {

// httpHeaders.set(HttpHeaders.TRANSFER_ENCODING, "chunked");

// }

return httpHeaders;

}

@Override

public Flux getBody() {

return body;

}

};

}

/**

* 添加Multipart表单的数据项

*

* @param boundary 随机串信息

* @param formFieldName 表单名

* @param value 值,可以是普通值、资源(如文件等)

*/

private static String appendPart(String boundary, String formFieldName, Object value,Integer count) throws IORuntimeException {

StringBuffer stringBuffer = new StringBuffer();

// 多资源

if (value instanceof MultiResource) {

for (Resource subResource : (MultiResource) value) {

appendPart(boundary, formFieldName, subResource,count);

}

return stringBuffer.toString();

}

if(count!=0){

stringBuffer.append("--").append(boundary).append(StrUtil.CRLF);

}else{

stringBuffer.append(StrUtil.CRLF);

// stringBuffer.append(boundary).append(StrUtil.CRLF);

}

if (value instanceof Resource) {

// 文件资源(二进制资源)

final Resource resource = (Resource) value;

final String fileName = resource.getName();

stringBuffer.append(StrUtil.format(CONTENT_DISPOSITION_FILE_TEMPLATE, formFieldName, ObjectUtil.defaultIfNull(fileName, formFieldName)));

// 根据name的扩展名指定互联网媒体类型,默认二进制流数据

stringBuffer.append(StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE, HttpUtil.getMimeType(fileName, "application/octet-stream")));

} else {

// 普通数据

stringBuffer.append(StrUtil.format(CONTENT_DISPOSITION_TEMPLATE, formFieldName)).append(value);

}

stringBuffer.append(StrUtil.CRLF);

return stringBuffer.toString();

}

}

MyCachedBodyOutputMessage.java

import java.util.function.Supplier;

import org.reactivestreams.Publisher;

import org.springframework.core.io.buffer.DataBuffer;

import org.springframework.core.io.buffer.DataBufferFactory;

import org.springframework.http.HttpHeaders;

import org.springframework.http.ReactiveHttpOutputMessage;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Flux;

import reactor.core.publisher.Mono;

public class MyCachedBodyOutputMessage implements ReactiveHttpOutputMessage {

private final DataBufferFactory bufferFactory;

DataBuffer dataBuffer;

private final HttpHeaders httpHeaders;

private Flux body = Flux.error(new IllegalStateException("The body is not set. Did handling complete with success?"));

public MyCachedBodyOutputMessage(ServerWebExchange exchange, HttpHeaders httpHeaders) {

this.bufferFactory = exchange.getResponse().bufferFactory();

this.httpHeaders = httpHeaders;

}

@Override

public void beforeCommit(Supplier> action) {

}

@Override

public boolean isCommitted() {

return false;

}

@Override

public HttpHeaders getHeaders() {

return this.httpHeaders;

}

@Override

public DataBufferFactory bufferFactory() {

return this.bufferFactory;

}

public Flux getBody() {

return this.body;

}

@Override

public Mono writeWith(Publisher body) {

this.body = Flux.from(body);

return Mono.empty();

}

@Override

public Mono writeAndFlushWith(Publisher> body) {

return this.writeWith(Flux.from(body).flatMap((p) -> {

return p;

}));

}

@Override

public Mono setComplete() {

return this.writeWith(Flux.empty());

}

}

修改返回值代码

import com.google.common.base.Joiner;

import com.google.common.base.Throwables;

import org.apache.commons.lang3.StringUtils;

import org.reactivestreams.Publisher;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

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.http.HttpStatus;

import org.springframework.http.server.reactive.ServerHttpRequest;

import org.springframework.http.server.reactive.ServerHttpResponse;

import org.springframework.http.server.reactive.ServerHttpResponseDecorator;

import org.springframework.stereotype.Component;

import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Flux;

import reactor.core.publisher.Mono;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.charset.Charset;

import java.nio.charset.StandardCharsets;

import java.util.ArrayList;

import java.util.List;

import java.util.zip.GZIPOutputStream;

import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR;

@Component

public class ResponseFilter implements GlobalFilter, Ordered {

private static final Logger log = LoggerFactory.getLogger(ResponseFilter.class);

private static Joiner joiner = Joiner.on("");

// @Autowired

// private IgnoreWhiteProperties ignoreWhite;

/**

* 约定的压缩格式

*/

private final static String GZIP = "gzip";

@Override

public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {

String acceptEncoding = exchange.getRequest().getHeaders().getFirst("Accept-Encoding");

ServerHttpResponse originalResponse = exchange.getResponse();

DataBufferFactory bufferFactory = originalResponse.bufferFactory();

ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(originalResponse) {

@Override

public Mono writeWith(Publisher body) {

if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {

// 获取ContentType,判断是否返回JSON格式数据

String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);

if (StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) {

Flux fluxBody = Flux.from(body);

//(返回数据内如果字符串过大,默认会切割)解决返回体分段传输

return super.writeWith(fluxBody.buffer().map(dataBuffers -> {

List list = new ArrayList<>();

dataBuffers.forEach(dataBuffer -> {

try {

byte[] content = new byte[dataBuffer.readableByteCount()];

dataBuffer.read(content);

DataBufferUtils.release(dataBuffer);

list.add(new String(content, StandardCharsets.UTF_8));

} catch (Exception e) {

log.info("加载Response字节流异常,失败原因:{}", Throwables.getStackTraceAsString(e));

}

});

String responseData = joiner.join(list);

System.out.println("responseData:"+responseData);

String responseDataEncode = null;

// String responseDataEncode = AESUtil.aesEncodeByKey(responseData, "MP5v0^zee5Qlgq5V");

if(responseDataEncode==null){

return bufferFactory.wrap(responseData.getBytes(StandardCharsets.UTF_8));

}

responseDataEncode = responseDataEncode.replaceAll("\r\n", "").replaceAll("\n","");

byte[] uppedContent = new String(responseDataEncode.getBytes(), StandardCharsets.UTF_8).getBytes();

originalResponse.getHeaders().setContentLength(uppedContent.length);

if(!StringUtils.isAnyBlank(acceptEncoding)){

assert acceptEncoding != null;

//是否支持压缩

if(acceptEncoding.contains(GZIP)){

//支持压缩

ByteArrayOutputStream bout = new ByteArrayOutputStream();

//压缩输出流中的数据

GZIPOutputStream gout;

try {

gout = new GZIPOutputStream(bout);

gout.write(uppedContent);

gout.close();

uppedContent = bout.toByteArray();

originalResponse.getHeaders().setContentLength(uppedContent.length);

originalResponse.getHeaders().set("content-encoding", GZIP);

} catch (IOException e) {

e.printStackTrace();

}

}else{

originalResponse.getHeaders().setContentLength(uppedContent.length);

}

}

return bufferFactory.wrap(uppedContent);

}));

}

}

return super.writeWith(body);

}

};

return chain.filter(exchange.mutate().response(decoratedResponse).build());

}

@Override

public int getOrder() {

return Ordered.HIGHEST_PRECEDENCE;

}

}

参考文章:https://blog.csdn.net/Hardworking666/article/details/123833192

精彩文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: