Написать запрос в файл в Spring MVC - PullRequest
4 голосов
/ 28 июля 2011

Я хотел бы иметь возможность записать весь запрос в файл в контроллере Spring MVC.

Я пробовал следующее, но файл всегда пуст, хотя я делаю POST-запрос с множеством параметров:

    @RequestMapping(method = RequestMethod.POST, value = "/payments/confirm")
public void receiveCallback(ServletInputStream inputStream)
{
    try
    {
        inputStream.reset();
        byte[] data = IOUtils.toByteArray(inputStream);

        File file = new File(System.getProperty("java.io.tmpdir") + "test" + System.currentTimeMillis() + ".txt");
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(data);
        fos.close();
    }
    catch (Exception e)
    {
        logger.error("Error writing request", e);
    }
}

Я также пытался использовать HttpServletRequest.getInputStream (), но результаты те же.

Ответы [ 2 ]

7 голосов
/ 31 июля 2011

Использование InputStream не будет работать (см. Ответ BalusC).Вот пример того, как вы могли бы вместо этого использовать объект HTTPServletRequest для записи заголовков и параметров:

@RequestMapping(method = RequestMethod.POST, value = "/payments/confirm")
public void receiveCallback(HttpServletRequest request) {
    try {
        StringBuilder sb = new StringBuilder();
        sb.append("Headers:\n");
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            Enumeration<String> headers = request.getHeaders(headerName);
            while (headers.hasMoreElements()) {
                String headerValue = headers.nextElement();
                sb.append(headerName).append(':').append(headerValue).append('\n');
            }
        }
        sb.append("\nParameters:\n");
        for(Entry entry: (Set<Entry>) request.getParameterMap().entrySet(){
            sb.append(entry.getKey()).append(':').append(entry.getValue()).append('\n');
        }
        byte[] data = sb.toString().getBytes();

        File file = new File(System.getProperty("java.io.tmpdir") + "test"
                + System.currentTimeMillis() + ".txt");
        FileOutputStream fos = new FileOutputStream(file);
        fos.write(data);
        fos.close();
    } catch (Exception e) {
        logger.error("Error writing request", e);
    }
}
5 голосов
/ 31 июля 2011

Я ничего не знаю о Spring, но я могу, по крайней мере, сказать, что тело запроса POST может быть прочитано только один раз . Это именно те данные, которые клиент отправил на сервер. Клиент не будет отправлять его повторно несколько раз, когда это потребуется серверу несколько раз.

Я предполагаю, что Spring уже прочитал тело запроса, чтобы проанализировать вложенную строку запроса и получить параметры запроса перед входом в метод контроллера Spring. Это можно сделать под прикрытием Spring с request.getParameter() и суппортами. В Servlet API, после вызова этого метода, request.getInputStream() и request.getReader() впоследствии ничего не вернут. Просто потому, что тело запроса уже прочитано, чтобы вернуть параметры. Это также упоминается в javadoc getParameter() .

Если данные параметров были отправлены в теле запроса, например, при запросе HTTP POST, то чтение тела напрямую через getInputStream() или getReader() может помешать выполнению этого метода.

Лучше всего создать фильтр , который будет делать копию тела запроса до того, как Spring выполнит свою работу, а затем поместить фильтр перед контроллером Spring. Создание копии тела запроса возможно с помощью HttpServletRequestWrapper, в котором вы переопределяете методы getInputStream() и getReader(), чтобы сначала прочитать тело запроса в ByteArrayInputStream и / или CharArrayReader чтобы у вас была локальная копия, а затем вернуть ее. Ссылка на HttpServletRequestWrapper может быть сохранена как атрибут запроса, так что вы можете получить его как атрибут запроса в контроллере Spring и, наконец, получить копию тела запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...