abstractGateway网关过滤请求

1.网关配置类增加路由过滤器配置

route:
  - id:sign
    uri:lb://consul注册的服务名称
    order:66
    metadata:
      fallbackBean: defaultFallbackHeadler
    predicates:
      -Path:/sign/*
    filters:
      - chnlnoMac  #过滤器名称,约束大于配置,请求入参的过滤器
      - responseMac #返回报文过滤器

2.配置熔断

可忽略此配置:可自己封装接口

@Component("defaultFallbackHeadler")
public DefaultFallbackHeadler implements IFallbackHandler{
	private static final Logger logger = LoggerFactory.getLOgger(DefaultFallbackHeadler.class);
	
	@Override
	public Object handle(ServerWebExchange exchange,Throwable throwable){
		loggin.info(------此请求出发熔断机制-------);
		JSONObject respInfo = new JSONObject();
		respInfo.put("errorMsg","触发熔断");
		respInfo.put("errorCode","1234");
		return respInfo ;
	}
}

3.对chnlnoMac 设置入参请求过滤器

@Component
public calss ChnlnoMacGatewayFIlterFactory extends AbstractGatewayFilterFactory{

private static final Logger logger = LoggerFactory.getLOgger(ChnlnoMacGatewayFIlterFactory .class);

private final ChnalMacFilter  filter = new ChnalMacFilter();

@Override
public GatewayFIlter apply(Object ovject){
	return filter;
}

private class ChnalMacFilter  implements GatewayFilter,Orderd{
		
		@Override
		public int getOder(){
		//定义过滤器顺序,越小越先执行
		return -4;
		}
		
		//获取入参
		private String getStringBody(Flux<DataBUffer> body){
				AtomicReference<String> ato = new AtomicReference<>();
				body.subscribe(buffer ->{
						CharBuffer charbuffer = StandardCharsets.UTF_8.decode(buffer.asByteBuffer());
						DataBUfferUtils.release(buffer);
						ato.set(chaebuffer.toString());
					}
				);
				return ato.get();
		}


		//过滤器
		@Override
		public Meno<Void> filter(ServerWebExchange exchange ,GatewayFilterChain chain){
			try{
				//从上下文对象中获取请求
				ServerHttpRequest request = exchange.getRequest();
				HttpHeaders headers = request.getHeaders();
				//获取请求体
				String reqBody = getStringBody(request.getBody());
				logger.info("请求入参:"+reqBody);
				
				JSONObject bodyObj =null;
				if(reqBody != null ){
					bodyObj = JSONObject.formObject(JSON.parse(reqBody));
					
				}else{
					bodyObj = new JSONObject();
				}
				
				//获取请求路径的最后一位,例如ip:端口/a/b,获取b
				String rawPath request.getURI().getRawPath();
				String b = rawPath.sustring(rawPath.lastIndexOf('/')+1);
				logger.info("b:"+b)

				//http头或者报文体获取参数
				if(headers.coontainsKey(c)){
					String c = headers.getFirst(c);
				}
				if(bodyObj.containsKey(d)){
					String d = (String)bodyObj.get(d);
				}

				
			}catch(Exception e){
				return intercep(exchange,e);
			}
			//请求继续执行
			return chain.filter(exchange);

		}

		protected Mono<Void> intercept(ServerWebExchange exchange,Exception e){
			logger.info("触发异常"+e+",请求为:"+exchange.getRequest().getURI());
			//封装状态码和错误信息
			exchange.getResponse().setStatusCode("500");
			return exchange.getRespnse.writeWith(Mono.error(new ZDYYCLException("1234","错误信息")));
			//注:ZDYYCLException为封装的异常类,继承运行异常runtimeException
		}
}}

4.responseMac返回报文过滤器

@Component
public calss responseMacGatewayFIlterFactory extends AbstractGatewayFilterFactory<object>{
	
	private static final Logger logger = LoggerFactory.getLOgger(responseMacGatewayFIlterFactory.class);
	
	private final responseMacFilter  filter = new responseMacFilter();
	
	@Override
	public GatewayFIlter apply(Object ovject){
		return filter;
	}

	private class filter implements GatewayFilter,Orderd{
			
			@Override
			public int getOder(){
			//定义过滤器顺序,越小越先执行
			return -2;
			}
			

			//过滤器
			@Override
			public Meno<Void> filter(ServerWebExchange exchange ,GatewayFilterChain chain){
				ServerHttpResponseDecorator decoratedResponse = new ServerHttpResponseDecorator(exchange.getResponse()){
					
					@Override
					public Mono<Void> writeWith(Publisher<? extends DataBuffer> body){
							//从上下文对象中获取请求
						ServerHttpRequest request = exchange.getRequest();
						//request头信息
						HttpHeaders headers = request.getHeaders();
						//response头信息
						HttpHeaders headers = getHeaders();
						
						//联机服务成功返回时,并且response body有值
						if(HttpStatus.OK.equals(getStatusCOde()) && body instanceof Flux){
							Flux<? extends DataBuffer> fluxBody = Flux.from(body);			
							return super.writhWith(fluxBody.buffer.map(dataBuffer ->{
								
								//将byte转换为jsonmap
								byte[][] contents = new byte[dataBuffers.size()][];
								int id =0;
								for(DataBuffer databuffer :dataBuffers){
									byte[] content = new byte[DataBUffer.readableByteCount()];
									dataBuffer.read(content);
									DataBufferUtils.release(dataBuffer);
									contents[id++] = content;
								}
								//拼接response报文体
								byte[] dodyBytes = ByteUtils.concatAll(contents);
								String resStr = new String(dodyBytes,"utf-8");
								//注意:此时,可以对返回报文进行更改了
								//更改完成之后,重新生成字节数组
								dodyBytes = resStr.getBytes("utf-8");
								
								logger.info("返回报文:"+resStr );
								//response报文长度变化,需要重新赋值
								header.remove(HttpHeaders.CONTENT_LENGTH);
								header.setContentLength(dodyBytes.length);
								return bufferFactory.wrap(dodyBytes);
							}));	
						}

	
						return super.writeWith(body);
					}
				};
				return chain.filter(exchange.mutate().response(decoratedResponse).build());
}}}

5.额外扩展:

5.1:第四部中,获取response的返回报文body时:

//将byte转换为jsonmap
								byte[][] contents = new byte[dataBuffers.size()][];
								int id =0;
								for(DataBuffer databuffer :dataBuffers){
									byte[] content = new byte[DataBUffer.readableByteCount()];
									dataBuffer.read(content);
									DataBufferUtils.release(dataBuffer);
									contents[id++] = content;
								}
								//拼接response报文体
								byte[] dodyBytes = ByteUtils.concatAll(contents);
								String resStr = new String(dodyBytes,"utf-8");

方法二:

private final Joiner joiner = Joiner.on("");
String jsonStr = joiner.join(dataBuffers.stream.map(dataBUffer ->{
	byte[] content = new byte[dataBUffer.readableByteCount()];
	databuffer.read(content);
	DataBUfferUtils.release(databuffer);
	return new String(content,"utf-8");
}).tpArray(String[] ::new));
//json转map
Map<String,Object> json = JSON.parseObject(jsonStr).getInnerMap;

方法三:

/**
 * 从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();
}

5.2quest入参过滤器中,在过滤器中,重新组装请求,访问另一个ip,

1。可看情况是否重新添加http头信息
ServerHttpRequest request = exchange.getRequest();
request.mutate().header("key","value");

或者
HttpHeaders headers = new httpHeaders();
headers.putAll(super.getHeaders());
headers.set("key""value");


2.重新组装一个请求访问业务服务;
private final List<HttpMessageReader<?>> messageReaders = HandlerStrategies.withDefaults().messageReaders();

ServerRequest serverRequest = ServerRequest.create(exchange,messageReaders);
final JSONObject finalBodyObj = bodyObj;//bodyObj,request的body体

Mono<byte[]> modifiedBody = serverRequest.bodyToMono(byte[].class).flatMap(body -> {
	byte[] bytes = JSON.toJSONString(finalBodyObj).getBytes(utf-8);
	return Mono.just(bytes);.
	
});

BodyInserter<Mono<byte[]>,ReactiveHttpOutputMessage> bodyInserter = BodyInserter.fromPublisher(modifiedBody,byte[].class);
CachedBodyOutputMessage outputMessage = new CachedBodyOutputMessage(exchange,headers);//headers例如上面的headers

//将处理后的格式重新发给自己
return bodyInserter.insert(outputMessage,new BodyInserterContext()).then(Mono.defer(() -> {
		//开始组装
		ServerHttpRequestDecorator decorator = new ServerHttpRequestDecorator(exchange.getrequest()){
			//ip
			@Override
			public URI getURI(){return "再次跳转的访问ip地址路径"}
			@Override
			public HttpHeaders getHeaders(){
				return headers;//可重新组装一个head
			}
			@Override
			Public Flux<DataBuffer> getBody(){
					return outputMessage.getBody();
				}
		};
		return chain.filter(exchange.mutate.request(decorator).build());

})).onErrorResume(Exception.class,e ->{ 
	return intercep(exchange,e);
});




	protected Mono<Void> intercept(ServerWebExchange exchange,Exception e){
				logger.info("触发异常"+e+",请求为:"+exchange.getRequest().getURI());
				//封装状态码和错误信息
				exchange.getResponse().setStatusCode("500");
				return exchange.getRespnse.writeWith(Mono.error(new ZDYYCLException("1234","错误信息")));
				//注:ZDYYCLException为封装的异常类,继承运行异常runtimeException
			}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值