Ведение журнала параметров HttpRequest и тела запроса - PullRequest
9 голосов
/ 12 июня 2011

Я пытаюсь создать журнал запросов для моего веб-приложения. Я использую Spring 3. 0.

Я реализовал класс, расширяющий HandlerInterceptorAdapter, и использовал preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) для перехвата запроса.

В методе я хочу иметь возможность регистрировать тело запроса (мои параметры - это объекты в XML, которые записываются непосредственно в тело запроса), и для этого я использую request.getReader();

Проблема в том, что позже я получу IllegalStateException, когда контроллер пружины попытается прочитать запрос.

Есть ли способ сделать то, что я намерен?

Ответы [ 3 ]

6 голосов
/ 12 июня 2011

Вы можете сделать это с помощью фильтра. Параметры запроса просты в обращении. Однако работать с телом запроса будет гораздо сложнее и потребует упаковки запроса сервлета: HttpServletRequest .

Вам необходимо посмотреть, насколько велик входящий запрос, и решить, хотите ли вы сохранить тело запроса в виде файла или строки tmp.

Вам потребуется переопределить ServetRequest.getInputStream () с помощью файла или сохраненной строки, которая использовалась для ведения журнала.

Если тело запроса огромно, я рекомендую поместить поток ввода в буферизованный поток ввода, а затем прочитать начало тела.

public class LogRequest extends HttpServletRequestWrapper {

    public LogRequest(HttpServletRequest request) {
        super(request);
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        //read from tmp file or string.
    }

    @Override
    public BufferedReader getReader() throws IOException {
        //read from tmp file or string
    }

}
4 голосов
/ 27 ноября 2014

Spring имеет готовый фильтр, чтобы сделать это для вас - посмотрите использование AbstractRequestLoggingFilter и его подклассов, описанных в этот ответ .

Имейте в виду, что при использовании этого решения тело запроса будет зарегистрировано только после того, как обработка запроса будет завершена и тело будет прочитано вашим приложением.

0 голосов
/ 06 февраля 2017

Простая реализация для небольших запросов.Не используйте его для составного запроса.

package ru.rbs.logger.web;

import org.apache.commons.io.IOUtils;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

class CachedRequestWrapper extends HttpServletRequestWrapper {
    private final byte[] cachedBody;

    CachedRequestWrapper(HttpServletRequest request) throws IOException {
        super(request);

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        IOUtils.copy(request.getInputStream(), bos);
        cachedBody = bos.toByteArray();
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new CachedServletInputStream();
    }

    byte[] toByteArray(){
        return cachedBody;
    }

    private class CachedServletInputStream extends ServletInputStream {
        private InputStream baseInputStream;

        CachedServletInputStream() throws IOException {
            baseInputStream = new ByteArrayInputStream(cachedBody);
        }

        @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 baseInputStream.read();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...