SpringBoot - HttpServletRequest 请求重复读取解决方案
发布日期:2021-06-30 23:28:38
浏览次数:2
分类:技术文章
本文共 5883 字,大约阅读时间需要 19 分钟。
RequestHandler
package com.chinadaas.platform.servicecenter.mycommon.handler;import com.alibaba.fastjson.JSON;import com.google.common.collect.Maps;import lombok.Getter;import lombok.Setter;import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;import javax.servlet.ReadListener;import javax.servlet.ServletInputStream;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletRequestWrapper;import javax.servlet.http.Part;import java.io.*;import java.nio.charset.Charset;import java.util.Collection;import java.util.Map;import java.util.Objects;@Getter@Setterpublic class RequestHandler extends HttpServletRequestWrapper { private String rawJson; private String form; private String query; public static RequestHandler getInstance(HttpServletRequest request) { if (request instanceof StandardMultipartHttpServletRequest) { request = ((StandardMultipartHttpServletRequest) request).getRequest(); } return (RequestHandler)request; } public RequestHandler(HttpServletRequest request) throws IOException { super(request); StringBuilder sb = new StringBuilder(); InputStream ins = request.getInputStream(); BufferedReader isr = null; try{ // rawJson case if(ins != null){ isr = new BufferedReader(new InputStreamReader(ins, Charset.defaultCharset())); char[] charBuffer = new char[128]; int readCount; while((readCount = isr.read(charBuffer)) != -1){ sb.append(charBuffer,0,readCount); } setRawJson(sb.toString()); } // check getParameterMap MaptParamMap = request.getParameterMap(); if (!(Objects.nonNull(tParamMap) && tParamMap.size() > 0)) { return; } Map paramMap = Maps.newHashMap(); tParamMap.entrySet().forEach(param -> { /* Array T String */ String[] valArr = param.getValue(); StringBuilder sbVal = new StringBuilder(); for (String val : valArr) { sbVal.append(val).append(","); } // clean last "," String val = sbVal.substring(0, sbVal.length()-1); paramMap.put(param.getKey(), val); }); // form case // business try catch try { Collection parts = request.getParts(); Map form = Maps.newHashMap(); parts.forEach(part -> { String paramKey = part.getName(); String paramVal = paramMap.get(paramKey); paramMap.remove(paramKey); form.put(paramKey, paramVal); }); setForm(JSON.toJSONString(form)); } catch (Exception e) { e.printStackTrace(); // no form-data } // query case setQuery(JSON.toJSONString(paramMap)); System.out.println(1); } finally { if(isr != null) { isr.close(); } } } @Override public ServletInputStream getInputStream() { try { final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(rawJson.getBytes(Charset.defaultCharset())); return new ServletInputStream() { @Override public int read() { return byteArrayInputStream.read(); } @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener listener) { } }; }catch (Exception e){ e.printStackTrace(); return null; } } @Override public BufferedReader getReader() { return new BufferedReader(new InputStreamReader(this.getInputStream())); }}
- 注意:HttpServletRequest 请求中的 body 内容仅能调用 request.getInputStream(), request.getReader() 和request.getParameter("key") 方法读取一次,重复读取会报 java.io.IOException: Stream closed 异常。
- 原来两个同名参数的值都能在后台拿到,难怪request.getParamterMap()方法的返回值类型是Map<String, String[]>,第二个String[]数组就能很好地处理同名参数。
Filter
package com.chinadaas.platform.servicecenter.mycommon.filter;import com.chinadaas.platform.servicecenter.mycommon.handler.RequestHandler;import javax.servlet.*;import javax.servlet.annotation.WebFilter;import javax.servlet.http.HttpServletRequest;import java.io.IOException;@WebFilter(filterName = "myFilter", urlPatterns = "/exec/convert/service/*")public final class RequestFilter implements Filter { @Override public void init(FilterConfig filterConfig) { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { RequestHandler request = new RequestHandler((HttpServletRequest) servletRequest); filterChain.doFilter(request, servletResponse); } @Override public void destroy() { }}
Application
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.boot.web.servlet.ServletComponentScan;/** * @author Lux Sun * @date 2020/7/8 */@SpringBootApplication@ServletComponentScan("com.chinadaas.platform.servicecenter.mycommon")public class DspServiceExecutorApplication { public static void main(String[] args) { SpringApplication.run(DspServiceExecutorApplication.class, args); }}
转载地址:https://lux-sun.blog.csdn.net/article/details/107351149 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月24日 08时09分07秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
基于MATLAB的模拟调制信号与解调的仿真——DSB
2019-04-30
基于MATLAB的模拟调制信号与解调的仿真——SSB
2019-04-30
HDU - 1166 敌兵布阵 (树状数组模板题/线段树模板题)
2019-04-30
CodeForces - 761C Dasha and Password (思维 暴力)
2019-04-30
POJ - 2481 Cows (树状数组 入门题)
2019-04-30
CodeForces - 987C Three displays (暴力/dp)
2019-04-30
计蒜客 NAIPC 2016 F. Mountain Scenes(dp)
2019-04-30
牛客国庆集训派对Day4——I 连通块计数(思维)
2019-04-30
牛客国庆集训派对Day4——G 区间权值(找规律,双重前缀和)
2019-04-30
牛客国庆集训派对Day5——L 数论之神(找规律/数论)
2019-04-30
CodeForces - 629B Far Relative’s Problem(模拟)
2019-04-30
CodeForces - 1059B Forgery (思维)
2019-04-30
CodeForces - 456C Boredom (dp)
2019-04-30
CodeForces - 675A Infinite Sequence(简单数论 细节)
2019-04-30
CodeForces - 1042B Vitamins (思维)
2019-04-30
ACM 2013 长沙区域赛 Collision (几何)
2019-04-30