SpringBoot - HttpServletRequest 请求重复读取解决方案

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
@Setter
public 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
            Map<String, String[]> tParamMap = request.getParameterMap();
            if (!(Objects.nonNull(tParamMap) && tParamMap.size() > 0)) {
                return;
            }
            Map<String, String> 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<Part> parts = request.getParts();
                Map<String, String> 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);
    }

}

猜你喜欢

转载自blog.csdn.net/Dream_Weave/article/details/107351149