Jsp/Servlet Request getReader()/getInputStream()返回空值的解决方法
来源:互联网 发布:淘宝培训班 编辑:程序博客网 时间:2024/06/05 08:02
因为同一次递交,request的三个方法getInputStream()/getReader()和getParameterMap(),任何一个方法使用过一次,postdata就会被清空,这三个方法再也无法使用。
现在有一个框架的流程是先用了getParameterMap()取出参数表,后面再视情况而定调用getreader()获得post data的具体数据, 如果用原来的request则无法满足此要求 , 这时候我们可以自定义HttpServletRequestWrapper,在filter里面拦截处理。
首先,我们定义一个可复用post data的HttpServletRequestWrapper,里面有个rebuildParams()方法,用于将POST过来的带?key1=value1&key2=value2的url参数和post data好里面的参数合并在一起, 几个getXXX获取参数的都重写了,改为从合并后的参数列表中取出参数:
package com.freestyle.common.servletsupport;import java.io.BufferedReader;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.InputStreamReader;import java.io.UnsupportedEncodingException;import java.net.URLDecoder;import java.util.ArrayList;import java.util.Arrays;import java.util.Enumeration;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Vector;import javax.servlet.ReadListener;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import org.apache.commons.io.IOUtils;public class MultiReadHttpServletRequest extends HttpServletRequestWrapper { private ByteArrayOutputStream cachedBytes; private Map<String,String[]> mParams=null; public MultiReadHttpServletRequest(HttpServletRequest request) { super(request); } public void rebuildParams(){ mParams=new HashMap<String,String[]>(); String lvTmp=(String) getAttribute("_request_body"); if (lvTmp!=null){ String[] lvItems=lvTmp.split("&"); for(String item:lvItems){ String[] lvItems1=item.split("=", 2); try { if (lvItems1.length==2){ lvItems1[1]=URLDecoder.decode(lvItems1[1], "utf8"); }} catch (UnsupportedEncodingException e) {// TODO Auto-generated catch blocke.printStackTrace();} if (mParams.containsKey(lvItems1[0])){ String[] lvV=mParams.get(lvItems1[0]); List<String> lvList=new ArrayList<String>(Arrays.asList(lvV)); if (lvItems1.length==2){ lvList.add(lvItems1[1]); } else{ lvList.add(null); } mParams.put(lvItems1[0], lvList.toArray(new String[lvList.size()])); } else{ String[] lvV=new String[]{lvItems1.length==2? lvItems1[1]:null}; mParams.put(lvItems1[0], lvV); } } } Map<String,String[]> lvParams=super.getParameterMap(); for(java.util.Map.Entry<String, String[]> item:lvParams.entrySet()){ mParams.put(item.getKey(),item.getValue()); } } @Override public ServletInputStream getInputStream() throws IOException { if (cachedBytes == null){ cacheInputStream(); } return new CachedServletInputStream(); } public String getParameter(String pvKey){ /*if (super.getParameterMap().containsKey(pvKey)){ return super.getParameter(pvKey); } String[] lvRet=mParams.get(pvKey); if (lvRet==null)return null; return lvRet[0];*/ Object lvV = mParams.get(pvKey); if (lvV == null) { return null; } else if (lvV instanceof String[]) { String[] lvStrArr = (String[]) lvV; if (lvStrArr.length > 0) { return lvStrArr[0]; } else { return null; } } else if (lvV instanceof String) { return (String) lvV; } else { return lvV.toString(); } } public Map<String, String[]> getParameterMap(){ /*Map<String, String[]> lvRet=super.getParameterMap(); lvRet.putAll(mParams); return lvRet;*/ return mParams; } public Enumeration getParameterNames() { Vector l = new Vector(mParams.keySet()); return l.elements(); } public String[] getParameterValues(String name) { Object v = mParams.get(name); if (v == null) { return null; } else if (v instanceof String[]) { return (String[]) v; } else if (v instanceof String) { return new String[] { (String) v }; } else { return new String[] { v.toString() }; } } @Override public BufferedReader getReader() throws IOException{ return new BufferedReader(new InputStreamReader(getInputStream())); } private void cacheInputStream() throws IOException { /* Cache the inputstream in order to read it multiple times. For * convenience, I use apache.commons IOUtils */ cachedBytes = new ByteArrayOutputStream(); IOUtils.copy(super.getInputStream(), cachedBytes); } /* An inputstream which reads the cached request body */ public class CachedServletInputStream extends ServletInputStream { private ByteArrayInputStream input; private boolean mIsFinished=false; public CachedServletInputStream() { /* create a new input stream from the cached request body */ input = new ByteArrayInputStream(cachedBytes.toByteArray()); mIsFinished=false; } @Override public int read() throws IOException { int lvReaded=input.read(); mIsFinished=lvReaded==-1; return lvReaded; }@Overridepublic boolean isFinished() {// TODO Auto-generated method stubreturn mIsFinished;}@Overridepublic boolean isReady() {// TODO Auto-generated method stubreturn false;}@Overridepublic void setReadListener(ReadListener arg0) {// TODO Auto-generated method stub} }}
然后我们定义一个Filter, 重写doFilter方法,在里面重新定义request, 并在POST方法&非上传文件的时候将post Data放在“_request_body"属性里面, 后面框架里面有个通用类会从“_request_body”属性里面取出此post Data解析出相应的pojo类。
package com.freestyle.common.servletsupport;import java.io.IOException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import org.apache.commons.fileupload.servlet.ServletFileUpload;import com.alco.bms.beans.HttpBeanUtil;public class RequestFilter implements Filter {@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { /* wrap the request in order to read the inputstream multiple times */ MultiReadHttpServletRequest multiReadRequest = new MultiReadHttpServletRequest((HttpServletRequest) request); /* here I read the inputstream and do my thing with it; when I pass the * wrapped request through the filter chain, the rest of the filters, and * request handlers may read the cached inputstream */ boolean isMultipart = ServletFileUpload.isMultipartContent(multiReadRequest); if (!isMultipart&&multiReadRequest.getMethod().toUpperCase().equals("POST")){ String c_request_body=HttpBeanUtil.getRequestPayload(multiReadRequest); multiReadRequest.setAttribute("_request_body", c_request_body); } multiReadRequest.rebuildParams(); chain.doFilter(multiReadRequest, response); }@Overridepublic void destroy() {// TODO Auto-generated method stub}@Overridepublic void init(FilterConfig arg0) throws ServletException {// TODO Auto-generated method stubif (arg0==null){}}}
而读出post data的方法很简单,如果用java 1.8的话,一句话就搞定了,下面写这么复杂只为了兼容性:
public static String getRequestPayload(HttpServletRequest req) {StringBuilder sb = new StringBuilder();try {BufferedReader reader = req.getReader();char[] buff = new char[1024];int len;while ((len = reader.read(buff)) != -1) {sb.append(buff, 0, len);}} catch (IOException e) {e.printStackTrace();}return sb.toString();}
现在在web.xml里面增加此filter:
<filter> <filter-name>MultiRequestCacheFilter</filter-name> <filter-class>com.freestyle.common.servletsupport.RequestFilter</filter-class> </filter> <filter-mapping> <filter-name>MultiRequestCacheFilter</filter-name> <url-pattern>*</url-pattern> </filter-mapping>
0 0
- Jsp/Servlet Request getReader()/getInputStream()返回空值的解决方法
- (转)servlet/jsp中得到表单数据的3种方法request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- request.getParameter() 、 request.getInputStream()和request.getReader()
- request.getParameter() request.getInputStream() request.getReader()
- request.getParameter()、request.getInputStream()和request.getReader()
- 解决request.getParameter() 、 request.getInputStream()和request.getReader()只能使用一次的问题
- 关于request.getInputStream和request.getReader 方法的一些区别以及遇到的一些问题
- JSP&&SERVLET学习笔记(六):getReader(), getInputStream()读取Body内容
- request.getParameter() 、 request.getInputStream()和request.getReader() 使用体会
- request.getParameter() 、 request.getInputStream()和request.getReader() 使用体会
- request.getParameter() 、request.getInputStream()和request.getReader() 使用体会
- 深入理解JavaScript系列(3):强大的原型和原型链
- 小细节决定大人生 或 对于细节的在意程度决定你人生到达的高度 或 对于细节的把控决定你是否比水平大致相同的人优秀与否 + 做事要带点脑子
- apusic5.1与c标签兼容
- 去除list里面的重复项
- Android Studio使用ViewPager+Fragment实现仿微信滑动切换界面
- Jsp/Servlet Request getReader()/getInputStream()返回空值的解决方法
- Infinidb问题处理
- linux常用命令
- java中System.setProperty()方法
- ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock
- ffmpeg 将视频和图片互转化
- mysql的价格存储类型
- android framework 添加系统服务
- fedora samba