3.PrintWriter缓冲区大小-16384

故事

所有的事情都由一个失误引起。

一般前端请求服务端的某个服务,也就是执行某个方法,该方法都会返回一个字符串,用来页面转发。

如果不需要页面转发,可以return null;

但是我不小心return ""; return了一个空字符串。

这样的话,页面会跳转到自身,就比如你本身是index.html,结果还是跳转到index.html。

我需要服务端返回一个base64编码过的图片字符串,是一串很长的字符,大概50000+。

之前没有发现return "";的默认转发错误问题,但是报错了,报错如下。

也就是页面转发失败了,它说的是response已经被提交过了,而我拿到response的PrintWriter只是在里面写入了值,

并没有flush(),close()等操作。

它怎么就说提交过了呢?之前没注意这个错误,但是我把这个写入过程注释掉,报错消失了,

但是客户端拿到的返回值是整个indel.html的页面代码

识别结果内本身是接收返回结果的,但是我注释掉了,发现还是返回了页面代码,起初以为是Response的body不写,默认会返回页面源码。最后发现是retun "";应该写成 return null;

那么return “”“;

也就是

request.getRequestDispatcher("").forward(req,resp);

这个操作到底会发生什么?

应该是页面转发,通过在resp中塞入index.html的方式,让前端显示这个页面,所以这个转发发生,前端就拿到了indel.html的源代码。

而在转发之前,拿到response的PrintWriter,写入数据,只要不触发flush()方法,都会触发这个最后的转发操作。

而我在PrintWriter中塞入一个50000+的长字符串,提示了response已经提交过了,不能转发。

而塞入一个类似“abc”的短字符串,能够触发转发操作。

这个问题说明什么问题?

也就是我们在Response的PringWriter中塞入一个长字符串的时候,会迫使response提前提交,也就是后来知道的,它会触发flush()函数,把缓冲区内的数据输出。

当时我是不知道这个缓冲区的概念的,是比较抠脚的那种。

但是我拿到的信息是,往response中塞入长字符串会迫使response提前提交,而通过getRequestDispatcher()的方式来转发页面的方式不允许在转发之前提交response。

接下来的问题是:这个字符串要多长,才会让response提前提交?

经过在3-50000之间进行若干次2分法,创建对应长度的字符串的方法进行测试,最后得到答案是16384。

(这个时候有的朋友可能会说,这个博主脑子有问题吧!没有错,朋友,我的脑子确实是有点问题的。)

在当时的环境下,我只知道,字符串长度大于等于16384,都会迫使response提前提交,把转发操作无效化。

而16384到底是个什么东西?

16384是2的14次方,凡是和2的多少次方搞上关系的都是有故事的,所以16384绝对是个有故事的数字。

没有错,你看完这篇文章,会记住这个神奇的数字,16384!

通过搜索“16384+PrintWriter”的方式,没有查到什么有用的东西,但是渐渐了解到这个东西和缓冲区有关系。

接着我搜索“16384+缓冲区”,拿到的可能是最后答案的答案。

这个东西是Tcp收发缓冲区的默认大小,

通过在服务器上打开文件查看tcp发送缓冲区的默认值,键入

cat /proc/sys/net/ipv4/tcp_wmem

得到结果如下

根据可靠的小道消息,这个东西是tcp发送缓冲区的默认大小

也就是经过java的封装,我们的PrintWriter的发送缓冲区就是16384?而这个缓冲区对应这tcp的发送缓冲区....

也就是塞入这个大小了,PrintWriter就执行一波flush(),把缓冲区提交,这样response已经提交过了,也就不能转发了。

不知道我的故事说的好不好,我现在现出真身了!

我是个傻吊!没有错,你没有看错。

这个故事是关于宇宙起源的16384问题,困扰许许多多的科学家很多年,大家都在问PrintWriter的缓冲区大小是多大呢?但是鲜有人能够把这个答案回答出来。没有错,这个装逼的机会交给你,是16384!当然这个答案还不是很站得住脚,当时候你装逼失败,被人打一顿,不要告诉别人你是从我这里看到的,好吗?

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值