9 Haziran 2023 Cuma

SpringMVC ContentCachingRequestWrapper Sınıfı

Giriş
Şu satırı dahil ederiz
import org.springframework.web.util.ContentCachingRequestWrapper;
Problem Nedir
Açıklaması şöyle
Imagine that you have implemented a logging mechanism, for example, AOP techniques, to log each HTTP request details. This way, the body will be consumed.

Then you have a RestController with a method that tries to read the HttpServletRequest body. This time, the getInputStream() will be empty.
ContentCachingRequestWrapper Sınıfının Eksikleri
Açıklaması şöyle
Spring provides a ContentCachingRequestWrapper class. This class provides a method, getContentAsByteArray() to read the body multiple times.

This class has a limitation, though:  We can't read the body multiple times using the getInputStream() and getReader() methods.

This class caches the request body by consuming the InputStream. If we read the InputStream in one of the filters, then other subsequent filters in the filter chain can't read it anymore. Because of this limitation, this class is not suitable in all situations.
Alternatif
Örnek
Elimizde şöyle bir kod olsun. Bu kod InputStream nesnesini tüketir ve saklar. Her getInputStream() çağrısında yeni bir ByteArrayInputStream ile tekrar bize verir.
class CachedRequestHttpServletRequest extends HttpServletRequestWrapper {
  private final byte[] cachedBody;

  public CachedRequestHttpServletRequest(HttpServletRequest request)
  throws IOException {
    super(request);
    this.cachedBody = StreamUtils.copyToByteArray(request.getInputStream());
  }

  @Override
  public ServletInputStream getInputStream() {
    ByteArrayInputStream inputStream = new ByteArrayInputStream(this.cachedBody);
    return new ServletInputStream() {
      @Override
      public boolean isFinished() {
        return inputStream.available() == 0;
      }

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

      @Override
      public int read() {
        return inputStream.read();
      }

      @Override
      public void setReadListener(ReadListener readListener) {
        throw new UnsupportedOperationException();
      }
    };
  }
}
Şöyle yaparız. Yani cache yapan nesneyi filtre içinde kullandık
@Component
@Slf4j
public class HttpRequestCustomFilter implements Filter {

  @Override
  public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
    FilterChain chain) throws IOException, ServletException {
    CachedRequestHttpServletRequest cachedRequestHttpServletRequest =
      new CachedRequestHttpServletRequest((HttpServletRequest) servletRequest);
    chain.doFilter(cachedRequestHttpServletRequest, servletResponse);
  }
}
ve filtreyi takmak için şöyle yaparız.
@Configuration
@Slf4j
public class HttpRequestConfiguration {

  @Bean
  public FilterRegistrationBean<HttpRequestCustomFilter> loggingFilter() {
    FilterRegistrationBean<HttpRequestCustomFilter> bean = new FilterRegistrationBean<>();
    bean.setFilter(new HttpRequestCustomFilter());
    bean.addUrlPatterns("/demo/*");
    return bean;
  }
}


Hiç yorum yok:

Yorum Gönder