Servlet Request的 getInputStream() getReader() getParameter()
如果你知道了这三者的区别,请忽略
最近碰到了servlet对入参获取方式的处理问题,因为二方库处理不当,导致了获取不到入参的情况,之前也知道这三个方法不兼容,现简单介绍下
1、这三个获取入参的方法,是互斥的,也就是使用了其中一个,再使用另外的两,是获取不到数据的
(Content-Type为 multipart/form-data除外,此时getParameter只能获取在url串当中的入参,但getInputStream与getReader还可以有其中一个获取请求的流数据)
2、getInputStream() getReader()只能使用一次,getParameter单线程上可重复使用
为什么要这么设计呢?
And for good reason. It would require the servlet infrastructure to keep a copy of the input in case the servlet decided to replay reopen. That would be an unwarranted overhead.
减少不必要的资源浪费呗。
因此tomcat servlet的输入流父类ServletInputStream以及其实现类CoyoteInputStream等,继承了InputStream,但没重写reset markSupported mark这三方法,因此数据的解析是一次性的,
同样,CoyoteReader,也没有重写父类Reader的这三方法,因此也是一次性读取的,两者最终读取的都是InputBuffer里面封装的字节数据
而其他的输入流,比如ByteArrayInputStream,三方法重写了,组合使用后数据是可重复读取的,里面可以设置mark标签,前面读取过,后面可以继续读取数据,具体可以写代码测试
对于getParameter,也只是其帮我们处理好了数据而已,底层是getInputStream读取了数据,然后解析出来而已,可查看org.apache.catalina.connector.Request org.apache.tomcat.util.http.Parameters的实现,tomcat7.0.47采用了LinkedHashMap存储了解析出来后的入参(老版本基于hashtable),当第一次getParameter时,会解析所有的入参放如这个map(processParameters方法),后面的get直接从map里面获取,他里面只有用parametersParsed didQueryParameters这两标记判断是否已经解析过,所以如果要多线程getParameter,结果你懂得,但同一个线程上N次getParameter肯定没问题,因为后面都只是map的get操作,至于getParameterNames,getParameterValues,getParameterMap这些方法,只是从map里面捞数据而已
如果要避免冲突,有两个方案
1、坚决只使用其中一种办法去获取入参,就如坚决维护一党专政一样
2、重写request里面的这三个方法,把数据保持住,后面可以随便使,要修改兼容的方法很多,风险比较大,当然这也违背了最初的设计初衷
Servlet Request的 getInputStream() getReader() getParameter()的更多相关文章
- org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.1428942566812653608
一.异常信息 org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet reque ...
- SpringBoot 上传文件突然报错 Failed to parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location [/tmp/tomcat.1428942566812653608
异常信息 org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request ...
- Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadBase$IOFileUploadException: Processing of multipart/form-data request failed.
org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nes ...
- Could not parse multipart servlet request; nested exception is java.io.IOException: The temporary upload location
spring-boot项目,生产环境运行一段时间后,上传图片报错,如下: threw exception [Request processing failed; nested exception is ...
- jsp当做第二个servlet request的生命周期 请求 响应 不管中间经历多少个servlet 只要最后一个serlvt执行后 则生命周期结束 request的域消失
jsp当做第二个servlet request的生命周期 请求 响应 不管中间经历多少个servlet 只要最后一个serlvt执行后 则生命周期结束 request的域消失
- Springboot 上传报错: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: The multi-part request contained parameter data (excluding uploaded files) that exceede
Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: The ...
- JSP内置对象--request对象 (setCharacterEncoding("GBK"),getParameter(),getParameterValues(),getParameterNames(),getServletPath(),getContextPath()
使用最多,主要用来接收客户端发送而来的请求信息,他是javax.servlet.http.HttpServletRequest接口的实例化对象. public interface HttpServle ...
- servlet request
request.getRequestURI(); request.getRequestURL(); getQueryString();//返回查询信息 getRemoteAddr();//得到来访者地 ...
- Servlet中使用getInputStream进行文件上传
据说古老了点,所以代码比较繁琐,主要用于处理文件的地方太多. 下节用SERVLET3.0的Part进行操作一下. form.html: <!DOCTYPE html> <html&g ...
随机推荐
- Linux 下以其他用户身份运行程序—— su、sudo、runuser
本文综合分析了Linux系统下,如何使用runuser命令.su命令和sudo命令以其他用户身份来运行程序,以及这三个命令的运行效率比较. 一.su 命令临时切换用户身份 SU:( Switch ...
- Java学习之ConcurrentHashMap实现一个本地缓存
ConcurrentHashMap融合了Hashtable和HashMap二者的优势. Hashtable是做了线程同步,HashMap未考虑同步.所以HashMap在单线程下效率较高,Hashtab ...
- C语言创始人
丹尼斯·麦卡利斯泰尔·里奇(英语:Dennis MacAlistair Ritchie,1941年9月9日-2011年10月12日[3]),生于美国纽约州布朗克斯维尔(Bronxville),著名的美 ...
- PHP ElasticSearch的使用
系统是Windows server 2003. ElasticSearch是一个基于Lucene的稳定的.分布式.RESTFul的搜索引擎.其实所谓的RestFul就是它提供URL供你调用(建立索引和 ...
- ES6新特性:Function函数扩展, 扩展到看不懂
本文所有Demo的运行环境为nodeJS, 参考:让nodeJS支持ES6的词法----babel的安装和使用 : 函数的默认值: 如果有参数 ,那就用参数, 如果没有参数, 那就用默认的参数: aj ...
- 写chrome插件---一个优酷自动加粉丝助手
写chrome插件主要就是写js , 我们要构造界面(HTML), 以及样式(CSS), 以及chrome给我们提供的jsAPI, 主要是chrome的API, 调试的话可以使用chrome的开发者 ...
- wow.js使用方法
近日,在做项目中,需要做到滚动条滑到某个位置时,才能显示动画,网上查询到有个wow.js可以达到要求,现在把使用方法做如下总结: wow.js演示地址 wow.js的github地址 使用方法真是超简 ...
- matplotlib 柱状图、饼图;直方图、盒图
#-*- coding: utf-8 -*- import matplotlib.pyplot as plt import numpy as np import matplotlib as mpl m ...
- 【codeforces 733F】 Drivers Dissatisfaction
http://codeforces.com/problemset/problem/733/F (题目链接) 题意 给出一张n个点的无向图,每一条变有两个特征值:${w,c}$:分别表示这条边的权值为$ ...
- 树莓派启用root账户
树莓派使用的linux是debian系统,所以树莓派启用root和debian是相同的. debian里root账户默认没有密码,但账户锁定. 当需要root权限时, 直接执行 sudo su 即可切 ...