webflux使用ServerHttpRequest 获取多body体内容

weblux构造多body体

webflux 可以用于提升项目吞吐量,cpu利用率,其使用非阻塞异步io,基于reactor的非阻塞,发布订阅模式。优点可自行百度。

项目中因为需要构造多body体接口,并且接口功能开放,可以传入任何参数,传入好几个参数,类似 加上不定个数的@RequestPart 注解。针对原始springmvc项目可以使用 httpservletRequest作为接口入参,但对于webflux框架的话,就需要使用对应的serverHttpRequest作为接口入参

sping-web

@PostMapping
    @ResponseBody
    public DynamicResponse<Book> test(HttpServletRequest httpServletRequest) {

        return DynamicResponse.of(()->bookService.updateBook(bookUpdateReq));
    }

spring-webflux

@RequestMapping(value="/testBodys",method=RequestMethod.GET)
	@ResponseBody
	public Mono<ResponseEntity> testHttpRequest(ServerHttpRequest httpRequest){

    return Mono.justOrEmpty(new ResponseEntity(HttpStatus.OK));
}

从webflux请求中获取请求数据

使用ServerHttpRequest可以解决接口不指定body体,传入多个body体的需求,但是业务层如何获取到响应的请求体body体呢?

网上有很多针对springCloud-gateway的相关问题解答,主要使用如下的方式:

String bodyString = new String("");
Flux<DataBuffer> body = exchange.getRequest().getBody();
 
        body.subscribe(buffer -> {
            byte[] bytes = new byte[buffer.readableByteCount()];
            buffer.read(bytes);
            DataBufferUtils.release(buffer);
            try {
                String bodyString = new String(bytes, "utf-8");
                System.out.println(bodyString);
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        });
// 主线程继续操作获取的 bodyString
bodyString ... 一系列操作

经过测试,会有几个问题,一个是 subsribe进行订阅的时候,由于webflux使用异步非阻塞,所以可能主线程已经开始往下走了,subscribe可能还没有执行,导致bodyString还没有获取到,其次,假如buffer一次消费不完的话,后面主线程获取的数据也不够。所以此处需要进行阻塞一下。

可以修改为

@RequestMapping(value="/testBodys",method=RequestMethod.GET)
	@ResponseBody
	public Mono<ResponseEntity> testHttpRequest(ServerHttpRequest httpRequest){
		Flux<DataBuffer> body = httpRequest.getBody();
		CountDownLatch downLatch = new CountDownLatch(1);
		byte[] bytesAll = new byte[200000];
		List<byte[]> byteList = new ArrayList<>();
		body.doOnComplete(()->downLatch.countDown())
				.subscribe(buffer -> {
					byte[] bytes = new byte[buffer.readableByteCount()];
					buffer.read(bytes);
					DataBufferUtils.release(buffer);
					// bytes 复制到bytesAll中
					System.arraycopy(bytes, 0 , bytesAll, 0 ,bytes.length);
					// bytes 增加到bytesList中
					byteList.add(bytes);
					try {
						String bodyString = new String(bytes, "utf-8");
						System.out.println(bodyString);
					} catch (UnsupportedEncodingException e) {
						e.printStackTrace();
					}

				});
		//  使用 coutdownLatch去阻塞让subscirbe订阅完
		try {
			downLatch.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// bytesAll 复制到新bytes 替换掉多余的bytes[] 中为0的数组
		int size = (int) byteList.stream().mapToInt(bytes -> bytes.length).count();
		byte[] bytesResult = new byte[size];
		System.arraycopy(bytesAll, 0 , bytesResult, 0 ,size);
		// result为request 中的body的值
		String result = new String(bytesResult);
		// 同时获取的 bytesResult也可以 获取到请求对应的form-data, 以boundary分割
		
		return Mono.justOrEmpty(new ResponseEntity(HttpStatus.OK));
	}

其中使用 countdown进行阻塞,最后获取到请求的对应多有 byte[] ,该byte[] 无论是构造请求body,还是做别的操作,都可以,byte[]使用boundary进行分割, 可以看到多body的请求格式。

 

  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值