• springboot Java HttpServletRequest 转 CURL 命令 【Servlet】利用 HttpServletRequestWrapper 实现对request body的二次读取,可用于记录日志


    https://blog.csdn.net/weixin_43833834/article/details/119816469

    http://www.manongjc.com/detail/25-hjxgtagcwdpkpuv.html

    https://blog.csdn.net/woluoyifan/article/details/81280702


    private static final String FORMAT_HEADER = "-H \"%1$s:%2$s\"";
    private static final String FORMAT_METHOD = "-X %1$s";
    private static final String FORMAT_BODY = "-d '%1$s'";
    private static final String FORMAT_URL = "\"%1$s\"";
    private static final String CONTENT_TYPE = "Content-Type";

    /**
    * <p>
    * HttpServletRequest 转化为 CURL 命令
    * </p>
    *
    * @param request request
    * @return String
    * @author Tophua
    * @since 2021/8/19
    */
    public String getCurl(HttpServletRequest request) {
    String curl;
    try {
    List<String> parts = new ArrayList<>();
    parts.add("curl");
    String url = request.getRequestURL().toString();
    String method = request.getMethod();
    String contentType = request.getContentType();
    String queryString = request.getQueryString();
    parts.add(String.format(ControllerLogAspect.FORMAT_METHOD, method.toUpperCase()));

    Map<String, String> headers = new HashMap<>(16);
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
    String key = headerNames.nextElement();
    headers.put(key, request.getHeader(key));
    }
    headers.forEach((k, v) -> parts.add(String.format(ControllerLogAspect.FORMAT_HEADER, k, v)));
    if (StrUtil.isNotEmpty(contentType) && !headers.containsKey(ControllerLogAspect.CONTENT_TYPE)) {
    parts.add(String.format(ControllerLogAspect.FORMAT_HEADER, ControllerLogAspect.CONTENT_TYPE, contentType));
    }
    if (StrUtil.isNotEmpty(queryString)) {
    url = HttpUtil.urlWithForm(url, queryString, CharsetUtil.CHARSET_UTF_8, false);
    }
    if (ContentType.isFormUrlEncode(contentType) && CollUtil.isNotEmpty(request.getParameterMap())) {
    request.getParameterMap().forEach((k, v) ->
    parts.add(StrUtil.format("--data-urlencode '{}={}'", k, ArrayUtil.get(v, 0))));
    }
    if (StrUtil.startWithIgnoreCase(contentType, ContentType.JSON.toString())) {
    BodyReaderHttpServletRequestWrapper wrapper = (BodyReaderHttpServletRequestWrapper) request;
    // String body = StrUtil.utf8Str(wrapper.getCachedBody());
    String body = IoUtil.readUtf8(wrapper.getInputStream());
    if (StrUtil.isNotEmpty(body)) {
    parts.add(String.format(ControllerLogAspect.FORMAT_BODY, body));
    }
    }
    parts.add(String.format(ControllerLogAspect.FORMAT_URL, url));
    curl = StrUtil.join(" ", parts);
    } catch (Exception e) {
    e.printStackTrace();
    curl = null;
    }
    return curl;
    }


    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;

    @WebFilter(filterName = "httpServletRequestWrapperFilter", urlPatterns = "/*")
    public class HttpServletRequestWrapperFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    if (request instanceof HttpServletRequest) {
    ServletRequest requestWrapper = new BodyReaderHttpServletRequestWrapper((HttpServletRequest) request);
    chain.doFilter(requestWrapper, response);
    } else {
    chain.doFilter(request, response);
    }
    }

    @Override
    public void destroy() {
    }
    }


    import javax.servlet.ReadListener;
    import javax.servlet.ServletInputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletRequestWrapper;
    import java.io.*;

    public class BodyReaderHttpServletRequestWrapper extends HttpServletRequestWrapper {

    private final byte[] bytes;

    public BodyReaderHttpServletRequestWrapper(HttpServletRequest request) throws IOException {
    super(request);
    try (BufferedInputStream bis = new BufferedInputStream(request.getInputStream());
    ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
    byte[] buffer = new byte[1024];
    int len;
    while ((len = bis.read(buffer)) > 0) {
    baos.write(buffer, 0, len);
    }
    this.bytes = baos.toByteArray();
    String body = new String(this.bytes);
    System.out.println(body);
    } catch (IOException ex) {
    throw ex;
    }
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
    final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(this.bytes);
    return 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();
    }
    };
    }

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


    
    

    最近项目上有一个需求,在api上收到的请求,需要在springmvc转化成实体参数之前把request body读取出来记录日志。

    在通常的响应流程上,使用了request.getInputStream()之后,流就会失效,即这个request body的流只能读取一次,这也是流本身的特性所致(当然,还有一种特殊的流——推回输入流PushbackInputStream)。

    通过servlet api,可以通过继承 HttpServletRequestWrapper 这个类,在 filter 中 对 request 进行一次封装,再传进chain中,如此便可以实现日志的记录。

    最近项目上有一个需求,在api上收到的请求,需要在springmvc转化成实体参数之前把request body读取出来记录日志。

    在通常的响应流程上,使用了request.getInputStream()之后,流就会失效,即这个request body的流只能读取一次,这也是流本身的特性所致(当然,还有一种特殊的流——推回输入流PushbackInputStream)。

    通过servlet api,可以通过继承 HttpServletRequestWrapper 这个类,在 filter 中 对 request 进行一次封装,再传进chain中,如此便可以实现日志的记录。
    ————————————————
    版权声明:本文为CSDN博主「苏笛南风」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/woluoyifan/article/details/81280702



  • 相关阅读:
    Pytorch-实战之对Himmelblau函数的优化
    Pytorch-tensor的感知机,链式法则
    Pytorch-tensor的激活函数
    Pytorch-tensor的分割,属性统计
    Pytorch-tensor的转置,运算
    Pytorch-tensor维度的扩展,挤压,扩张
    Transformer代码细节
    Leetcode 1494
    格雷码
    两个正序数组的中位数
  • 原文地址:https://www.cnblogs.com/suizhikuo/p/16266541.html
Copyright © 2020-2023  润新知