国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Spring-Cloud-Gateway修改請求(json,form帶文件請求)參數(shù),返回值參數(shù)

這篇具有很好參考價值的文章主要介紹了Spring-Cloud-Gateway修改請求(json,form帶文件請求)參數(shù),返回值參數(shù)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

新項目需要在getway統(tǒng)一做入?yún)?、出參加解密,記錄日志。記錄一下form,x-www-form-urlencoded , json 這幾種修改數(shù)據(jù)的方式。
gateway做攔截器是實現(xiàn)GlobalFilter接口,修改json方式網(wǎng)上有很多文章,后來又想研究研究能不能實現(xiàn)修改form-data參數(shù),以及文件請求,后者文章不多大部分是怎么讀數(shù)據(jù)的教學?,F(xiàn)在發(fā)一下我的實現(xiàn)方式。
使用的gateway版本是2.2.1.RELEASE cloud版本Greenwich.SR2


   @Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)   {
	    Mono<Void> 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<String, String> queryParams = exchange.getRequest().getQueryParams().toSingleValueMap();
				log.info("queryParams:{}", queryParams);
			}
		}
	    return mono;
	}

修改json數(shù)據(jù)

/**
	 * 修改修改body參數(shù)
	 */
	private Mono<Void> transferBody(ServerWebExchange exchange, GatewayFilterChain chain) {
	ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
	Mono<String> 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內數(shù)據(jù)過長讀取不完整的問題
				Flux<DataBuffer> 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);
						//到這可以讀取數(shù)據(jù),做校驗之類的
					    //JsonNode token = oldDataJSON.get("token");
						jsonNode .set("test","修改數(shù)據(jù)");
						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表單參數(shù),一般需要上傳文件的請求用這個。數(shù)據(jù)讀取都可以用json請求那個方法獲取,但是帶文件的請求用那個讀了以后文件數(shù)據(jù)就變了,修改數(shù)據(jù)以后文件沒法正常存儲,所以按以下方式,直接讀取字節(jié)然后拼接要改的數(shù)據(jù)

//修改form參數(shù)
	private Mono<Void> 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); 
					//添加一些自定義參數(shù),或者校驗
					String oldBody = addPara(contentType.toString(), new String(bytes));
					
					byte[] bytes1 = oldBody.getBytes();
					//這里截取數(shù)組是因為 form請求體數(shù)據(jù)末尾有--/r/n,這里需要截一段然后拼接自定義的數(shù)據(jù)。數(shù)據(jù)格式可以看文章末尾的鏈接
					byte[] bytes2 = byteMerger(Arrays.copyOf(bytes,bytes.length-4), bytes1);
					Flux<DataBuffer> 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參數(shù)
	 * @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<String, Object> formMap = Maps.newHashMap();
		/**
		 *
		 * 根據(jù)自己需求進行對bodyString信息修改,例如下面,根據(jù)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<split.length-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","添加自定義參數(shù)");
		formMap.put("tcu",22222);
		Integer count =0;
		for (Map.Entry<String, Object> 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參數(shù)

	/**
	 * 修改 x-www-form-urlencoded參數(shù)
	 * @param exchange
	 * @param chain
	 * @return
	 */
	private Mono<Void> xwFromBody(ServerWebExchange exchange, GatewayFilterChain chain){
		ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
		Mono<String> 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<DataBuffer> 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參數(shù)
	private void changeParamByXwForm(Flux<DataBuffer> 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);
			//直接拼接要改的數(shù)據(jù)就行
			oldBody+="&tcu=123888";
			DataBuffer data = outputMessage.bufferFactory().allocateBuffer();
			data.write(oldBody.getBytes(StandardCharsets.UTF_8));
			holder.length = data.readableByteCount();
			holder.dataBuffer=data;
		});
	}

修改請求參數(shù)完整代碼 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<HttpMessageReader<?>> MESSAGE_READERS = HandlerStrategies.withDefaults().messageReaders();

	@Autowired
	private RedisUtil redisUtil;
	@Autowired
	private UserConvert userConvert;
	@Autowired
	private ObjectMapper objectMapper;
	@Autowired
	private UserManager userManager;


    @Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)   {
	    Mono<Void> 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<String, String> queryParams = exchange.getRequest().getQueryParams().toSingleValueMap();
				log.info("queryParams:{}", queryParams);
			}
		}
	    return mono;
	}
	//修改form參數(shù)
	private Mono<Void> 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<DataBuffer> 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參數(shù)
	private void changeParamByXwForm(Flux<DataBuffer> 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=修改數(shù)據(jù)";
			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參數(shù)
	 * @param exchange
	 * @param chain
	 * @return
	 */
	private Mono<Void> xwFromBody(ServerWebExchange exchange, GatewayFilterChain chain){
		ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
		Mono<String> 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<DataBuffer> 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參數(shù)
	 */
	private Mono<Void> transferBody(ServerWebExchange exchange, GatewayFilterChain chain) {
	ServerRequest serverRequest = ServerRequest.create(exchange, HandlerStrategies.withDefaults().messageReaders());
	Mono<String> 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內數(shù)據(jù)過長讀取不完整的問題
				Flux<DataBuffer> 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<Void> 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參數(shù)
	 * @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<String, Object> formMap = Maps.newHashMap();
		/**
		 *
		 * 根據(jù)自己需求進行對bodyString信息修改,例如下面,根據(jù)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<split.length-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<String, Object> 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<DataBuffer> body){
		return new ServerHttpRequestDecorator(
				exchange.getRequest()) {
			@Override
			public HttpHeaders getHeaders() {
			//數(shù)據(jù)長度變了以后 需要修改header里的數(shù)據(jù),不然接收數(shù)據(jù)時會異常
			//我看別人說刪除會自動補充數(shù)據(jù)長度,但我這個版本不太行
//				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<DataBuffer> getBody() {
				return body;
			}
		};
	}


	/**
	 * 添加Multipart表單的數(shù)據(jù)項
	 *
	 * @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)));
			// 根據(jù)name的擴展名指定互聯(lián)網(wǎng)媒體類型,默認二進制流數(shù)據(jù)
			stringBuffer.append(StrUtil.format(CONTENT_TYPE_FILE_TEMPLATE, HttpUtil.getMimeType(fileName, "application/octet-stream")));
		} else {
			// 普通數(shù)據(jù)
			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<DataBuffer> 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<? extends Mono<Void>> action) {
    }
    @Override
    public boolean isCommitted() {
        return false;
    }
    @Override
    public HttpHeaders getHeaders() {
        return this.httpHeaders;
    }
    @Override
    public DataBufferFactory bufferFactory() {
        return this.bufferFactory;
    }

    public Flux<DataBuffer> getBody() {
        return this.body;
    }
    @Override
    public Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
        this.body = Flux.from(body);
        return Mono.empty();
    }

    @Override
    public Mono<Void> writeAndFlushWith(Publisher<? extends Publisher<? extends DataBuffer>> body) {
        return this.writeWith(Flux.from(body).flatMap((p) -> {
            return p;
        }));
    }
    @Override
    public Mono<Void> 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<Void> 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<Void> writeWith(Publisher<? extends DataBuffer> body) {
                if (getStatusCode().equals(HttpStatus.OK) && body instanceof Flux) {
                    // 獲取ContentType,判斷是否返回JSON格式數(shù)據(jù)
                    String originalResponseContentType = exchange.getAttribute(ORIGINAL_RESPONSE_CONTENT_TYPE_ATTR);
                    if (StringUtils.isNotBlank(originalResponseContentType) && originalResponseContentType.contains("application/json")) {
                        Flux<? extends DataBuffer> fluxBody = Flux.from(body);
                        //(返回數(shù)據(jù)內如果字符串過大,默認會切割)解決返回體分段傳輸
                        return super.writeWith(fluxBody.buffer().map(dataBuffers -> {
                            List<String> 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字節(jié)流異常,失敗原因:{}", 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();
                                    //壓縮輸出流中的數(shù)據(jù)
                                    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文章來源地址http://www.zghlxwxcb.cn/news/detail-597146.html

到了這里,關于Spring-Cloud-Gateway修改請求(json,form帶文件請求)參數(shù),返回值參數(shù)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。如若轉載,請注明出處: 如若內容造成侵權/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領支付寶紅包贊助服務器費用

相關文章

  • Spring-Cloud-Gateway如何自定義路由過濾器?

    遇到這么一個面試題:自定義網(wǎng)關過濾器實現(xiàn)把url中的請求參數(shù)放到http的header中傳遞給微服務。 我們知道網(wǎng)關的一個重要的作用就是路由轉發(fā),路由表的配置大概是這個樣子: 其中的filters就是配置的路由過濾器,Spring已經(jīng)內置了31個路由的過濾器,這些過濾器都是 org.spring

    2024年02月16日
    瀏覽(24)
  • spring-cloud-gateway版本和springboot版本不匹配

    在搭建gateway服務的時候,啟動出現(xiàn)以下問題: Description: An attempt was made to call a method that does not exist. The attempt was made from the following location: ? ? org.springframework.cloud.gateway.config.GatewayAutoConfiguration$NettyConfiguration.buildConnectionProvider(GatewayAutoConfiguration.java:798) The following method did no

    2024年02月16日
    瀏覽(23)
  • 芝法醬躺平攻略(14)——Nginx與Spring-Cloud-Gateway

    芝法醬躺平攻略(14)——Nginx與Spring-Cloud-Gateway

    上一章芝法醬躺平攻略(12)展望了微服務下常見的技術需求與常見解決方案,本期來講解第一部分,Nginx與SpringCloud-Gateway。 本章將實踐在nginx和spring-cloud-gateway的簡單使用。 首先,去官網(wǎng)查找最新穩(wěn)定版,把下載的nginx包放到DOWNLOAD文件夾下。 而后把該包解壓到SOFTWARE文件夾

    2024年02月07日
    瀏覽(32)
  • 【深入解析spring cloud gateway】05 gateway請求轉發(fā)實驗

    三個工程: eureka-server eureka-client gateway 實驗目的:通過網(wǎng)關訪問對應的微服務:eureka-client。gateway和eureka-client注冊到eureka-server上 eureka-server略 eureka-client application.yml 提供一個接口 pom.xml application.yml 定義一個filter用于去掉路徑中的/gateway 自定義一個GlobalFilter,用于去掉路徑

    2024年02月10日
    瀏覽(20)
  • 修改經(jīng)過Spring Gateway的Json數(shù)據(jù)

    使用Spring Cloud Gateway作為網(wǎng)關時經(jīng)常會需要對報文內的json數(shù)據(jù)進行修改,但是目前看到的實現(xiàn)方法看起來都很復雜,這里提供一種使用Spring官方提供的ModifyRequestBodyGatewayFilterFactory類來修改json報文的方法 Spring Boot版本:2.7.15 Hutool: 5.8.21 Java: 11 實現(xiàn)分為兩個部分 filter:在自定義

    2024年02月08日
    瀏覽(27)
  • 【Spring Cloud】網(wǎng)關Gateway的請求過濾工廠RequestRateLimiterGatewayFilterFactory

    【Spring Cloud】網(wǎng)關Gateway的請求過濾工廠RequestRateLimiterGatewayFilterFactory

    ??????? 關于微服務網(wǎng)關Gateway中有幾十種過濾工廠,這一篇博文記錄的是關于請求限流過濾工廠,也就是標題中的RequestRateLimiterGatewayFilterFactory。這個路由過濾工廠是 用來判斷當前請求是否應該被處理,如果不會被處理就會返回HTTP狀態(tài)碼為429的code 。接下來構建兩個模塊,

    2024年02月07日
    瀏覽(17)
  • 修改經(jīng)過Spring Gateway的表單中的Json數(shù)據(jù)

    使用Spring Cloud Gateway作為網(wǎng)關時有時候一個請求是既包含excel又包含json的表單數(shù)據(jù),出于各種層面考慮網(wǎng)關需要獲取并更新其中的json數(shù)據(jù) Spring Boot版本:2.7.15 Hutool: 5.8.21 Java: 11 實現(xiàn)分為2個部分 使用上文提到的ModifyRequestBodyGatewayFilterFactory類來修改請求體,這樣最后就不用我們

    2024年02月08日
    瀏覽(27)
  • 從Spring Cloud Gateway過濾器中獲取請求體的最優(yōu)方案

    在spring cloud gateway出現(xiàn)這個問題的時候我們第一反應應該很簡單,但是真正實現(xiàn)的時候卻有點困難。我看了很多相關的文檔,感覺太多都不清晰而且解決不了問題。下面我就把我的方便理解的解決方案寫下來。 1. 先重寫請求體(過濾器優(yōu)先級一定要在要獲取body之前執(zhí)行) 這

    2024年02月16日
    瀏覽(22)
  • spring cloud gateway中出現(xiàn)503 spring cloud gateway中出現(xiàn)503

    當搭建網(wǎng)關模塊的時候出現(xiàn)503的錯誤的最大的可能就是沒有設置負載均衡的依賴包 ?原先搭建的時候采用的是下面的方式進行設置的 上面的這種方式可以直接進行注冊和發(fā)現(xiàn),但是要求必須導入下面的依賴 希望簡單的隨筆能夠幫助你!

    2024年02月11日
    瀏覽(88)
  • POST請求中json和form的優(yōu)缺點

    互為對方的優(yōu)缺點 請求方式 Content-Type 優(yōu)點 缺點 form multipart/form-data 支持傳文件、易編寫、Postman調試方便 不支持嵌套類型 json application/json 支持嵌套類型 編寫麻煩 為什么接口設計都不用普通 POST 如何設置APIFlask入?yún)⒆侄螢榍短鬃侄?Java接口傳參時用form data好還是用json好?

    2024年02月13日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領取紅包,優(yōu)惠每天領

二維碼1

領取紅包

二維碼2

領紅包