如何利用装饰器模式使重复读取请求体Request Body

如何利用装饰器模式使重复读取请求体Request Body

1、在获取请求体的时候, HttpServletRequest提供了getInputStream方法用来获取,但这是一次性的,流关闭以后就不能再获取,此时我们可以继承HttpServletRequestWrapper来增强HttpServletRequest

2、继承

@Slf4j
public class RequestBodyWrapper extends HttpServletRequestWrapper {
    /**
     * 保存body
     */
    private byte[] requestBody = null;

    public RequestBodyWrapper(HttpServletRequest request) {
        super(request);
        try {
            requestBody = StreamUtils.copyToByteArray(request.getInputStream());
        } catch (IOException e) {
            log.error("", e);
        }
    }

    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream is = new ByteArrayInputStream(requestBody);
        return new ServletInputStream() {
            @Override
            public int read() {
                return is.read();
            }

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

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

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }

    public byte[] getRequestBody() {
        return requestBody;
    }
}

3、使用前置过滤器封装HttpServletRequest

@WebFilter(filterName = "requestBodyFilter",urlPatterns = {"/*"})
@Order(Integer.MIN_VALUE)
@Slf4j
public class RequestBodyFilter implements Filter {
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        //requestWrapper中保存着供二次使用的请求数据
        ServletRequest requestWrapper = null;
        if (request instanceof HttpServletRequest) {
            requestWrapper = new RequestBodyWrapper((HttpServletRequest) request);
        }
        if(requestWrapper == null) {
            chain.doFilter(request, response);
        } else {
            chain.doFilter(requestWrapper, response);
        }
    }
    @Override
    public void destroy() {
    }
}

4、封装一个公共方法,随时在业务逻辑中获取body

public static String getBody(HttpServletRequest request) {
    if(request instanceof RequestBodyWrapper) {
        RequestBodyWrapper wrapper = (RequestBodyWrapper)request;
        return new String(wrapper.getRequestBody());
    } else {
        return "";
    }
}

注:在Controller层,@RequestBody的使用完全不受影响,可正常使用

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值