У нас есть ServletFilter
, который извлекает <title/>
из ServletResponse
. Мы делаем это, используя Piped*Stream
API в нашем собственном расширении HttpServletResponseWrapper
.
Чтобы быть более конкретным, текущий подход заключается в следующем (в псевдокоде):
- Создайте пару потоков
PipedInput
и PipedOutput
и соедините их друг с другом.
- Введите
PipedOutputStream
в нашем расширении HttpServletResponseWrapper
.
- Запустить поток, который ожидает записи байтов в
PipedOutputStream
(когда он будет готов, поток будет считывать <title/>
с подключенного PipedInputStream
).
- Передайте наше расширение от
HttpServletResponseWrapper
до filterChain.doFilter()
(это позволяет Servlet
обработать запрос и записать в PipedOutputStream
.
И это фактический код:
PipedInputStream pipedInputStream = new PipedInputStream( BUFFER_SIZE );
PipedOutputStream pipedOutputStream = new PipedOutputStream( pipedInputStream );
// ResponseSplitter extends HttpServletResponseWrapper.
// When getOutputStream() is called, the splitter returns a class called
// SplitStream, which extends ServletOutputStream, overriding the write() method by
// writing to both the response's original outputStream and the pipedOutputStream.
HttpServletResponseSplitter httpServletResponseSplitter =
new HttpServletResponseSplitter(
httpServletResponse,
pipedOutputStream,
true );
Future<?> future = null;
try {
// Fire off a thread that waits for the PipedInputStream to have
// content, then reads data.
// Specifically, we pass the PipedInputStream to jericho
// StreamedSource to examine the DOM segment-by-segment, without
// buffering the whole document into memory.
future = recordHistory( httpServletResponseSplitter );
// On the main thread, we pass the request and responseSplitter
// down the chain so that the servlet can write to the
// responseSplitter's splitStream
chain.doFilter( httpServletRequest, httpServletResponseSplitter );
// block until the servlet's done writing
future.get();
}
catch ( Exception e ) {
throw new RuntimeException( e );
}
Мы пытаемся избежать сложности потоков, и в то же время можем читать документ response
как поток и, таким образом, извлекать тег <title/>
без буферизации весь документ в память.
Есть ли более простой синхронный подход к тому, что мы пытаемся сделать?
редактировать: добавлен фактический код