前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java在filter中修改一个http请求出入参内容

java在filter中修改一个http请求出入参内容

作者头像
天涯泪小武
发布2021-12-09 19:09:31
1.6K0
发布2021-12-09 19:09:31
举报
文章被收录于专栏:SpringCloud专栏

response保存了请求的返回信息,里面有个outputstream,你要返回给页面的流,都在这个地方保存. 之前遇到一个问题,想把outputstream修改一下.因为这是个输出流,想要改这个里面的东西不是这么简单的. sun为我们提供了这么一个工具HttpServletResponseWrapper抽象类,利用这个类的子类把servletresponse包装一下,在过滤器中使用,就可以去除response的文件流,对其作出修改.给出一个实现:

代码语言:javascript
复制
import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import java.io.*;

/**
 * ResponseWrapper
 *
 * @author wuweifeng
 * @version 1.0
 * @date 2021-08-16
 */
public class ResponseWrapper extends HttpServletResponseWrapper {
    /**
     * ByteArrayOutputStream
     */
    private ByteArrayOutputStream buffer;
    /**
     * ServletOutputStream
     */
    private ServletOutputStream out;
    /**
     * writer
     */
    private PrintWriter writer;

    /**
     * ResponseWrapper
     */
    public ResponseWrapper(HttpServletResponse resp) throws IOException {
        super(resp);
        buffer = new ByteArrayOutputStream();//真正存储数据的流
        out = new WrapperOutputStream(buffer);
        writer = new PrintWriter(new OutputStreamWriter(buffer, this.getCharacterEncoding()));
    }

    //重载父类获取outputstream的方法
    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        return out;
    }

    //重载父类获取writer的方法
    @Override
    public PrintWriter getWriter() throws UnsupportedEncodingException {
        return writer;
    }

    //重载父类获取flushBuffer的方法
    @Override
    public void flushBuffer() throws IOException {
        if (out != null) {
            out.flush();
        }
        if (writer != null) {
            writer.flush();
        }
    }

    @Override
    public void reset() {
        buffer.reset();
    }

    /**
     * 获取response的字符串
     */
    public String getContent() throws IOException {
        flushBuffer();//将out、writer中的数据强制输出到WapperedResponse的buffer里面,否则取不到数据
        return new String(buffer.toByteArray());
    }

    //内部类,对ServletOutputStream进行包装
    private class WrapperOutputStream extends ServletOutputStream {
        /**
         * ByteArrayOutputStream
         */
        private ByteArrayOutputStream bos;

        /**
         * WrapperOutputStream
         */
        WrapperOutputStream(ByteArrayOutputStream stream) {
            bos = stream;
        }

        @Override
        public void write(int b) {
            bos.write(b);
        }

        @Override
        public boolean isReady() {
            return false;
        }

        @Override
        public void setWriteListener(WriteListener writeListener) {

        }
    }
}

然后在你的过滤器中这么使用:

代码语言:javascript
复制
public class UserFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        ResponseWrapper mResp = new ResponseWrapper(resp);// 包装响应对象 resp 并缓存响应数据
        filterChain.doFilter(servletRequest, mResp);

        String content = mResp.getContent();//response流的内容
        System.out.println(content);


        //此处可以对content做处理,然后再把content写回到输出流中
        servletResponse.setContentLength(-1);

        PrintWriter out = servletResponse.getWriter();

        out.write(content);

        out.flush();

        out.close();
    }
}

关于入参request的,如果只是key-value型的,对应客户端是form那种传过来的,在filter里直接获取没事。但如果是application/json型的,如果这个输入流被提前读取了,则后续真正的controller就取不到了,也需要做个包装类。

代码语言:javascript
复制
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import static com.alibaba.fastjson.util.IOUtils.UTF8;

public class RequestWrapper extends HttpServletRequestWrapper {
    /**
     * log
     */
    private static final Logger log = LoggerFactory.getLogger(RequestWrapper.class);
    /**
     * application/json型的入参
     */
    private final String body;
    /**
     * key-value型所有的入参
     */
    private Map<String, String[]> params = new HashMap<>();


    public RequestWrapper(HttpServletRequest request) {
        super(request);
        this.params.putAll(request.getParameterMap());
        StringBuilder stringBuilder = new StringBuilder();
        BufferedReader bufferedReader = null;
        InputStream inputStream = null;
        try {
            inputStream = request.getInputStream();
            if (inputStream != null) {
                bufferedReader = new BufferedReader(new InputStreamReader(inputStream, UTF8));
                char[] charBuffer = new char[512];
                int bytesRead;
                while ((bytesRead = bufferedReader.read(charBuffer)) > 0) {
                    stringBuilder.append(charBuffer, 0, bytesRead);
                }
            }
        } catch (IOException ex) {
            log.error("requestBody read error ignore,message:" + ex.getMessage());
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error("requestBody inputStream close error,ignore");
                }
            }
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    log.error("requestBody bufferedReader close error,ignore");
                }
            }
        }
        body = stringBuilder.toString();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes(UTF8));
        ServletInputStream servletInputStream = new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {
            }

            @Override
            public int read() throws IOException {
                return byteArrayInputStream.read();
            }
        };
        return servletInputStream;

    }

    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new InputStreamReader(this.getInputStream(), UTF8));
    }

    public String getBody() {
        return this.body;
    }

    @Override
    public String getParameter(String name) {
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public String[] getParameterValues(String name) {
        return params.get(name);
    }


    @Override
    public Enumeration<String> getParameterNames() {
        return Collections.enumeration(params.keySet());
    }

}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档