Входные значения формы Spring возвращают нуль после прочтения его один раз в фильтре, несмотря на использование оболочки запросов - PullRequest
1 голос
/ 09 апреля 2020

В моем проекте весенней загрузки я использую шаблоны бесплатных маркеров для образцов форм. Мне нужно было добавить фильтр, чтобы читать полезные данные и делать что-то еще. Я знаю, если вы читаете полезную нагрузку в фильтре, вам нужно сбросить тело запроса. Потому что это можно прочитать один раз. Так как я столкнулся с этой проблемой раньше, я знал, что я должен был использовать обертку. Я ожидал решить мою проблему, как и раньше. Однако в контроллере все поля во входных объектах являются нулевыми.

Чего мне здесь не хватает?

Мой фильтр:

public class KfsInMsgFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

       HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;

        Map<String, String[]> extraParams = new TreeMap<String, String[]>();
        WrappedRequest wrappedRequest = new WrappedRequest(request, extraParams);

        String body = IOUtils.toString(new BufferedReader(new InputStreamReader(wrappedRequest.getInputStream(), Constants.UTF_8)));

        // doing some stuff using body
        // ....

        // resetting payload
        wrappedRequest.resetStream(body.getBytes(Constants.UTF_8));

        ...

    } 
}

Класс WrappedRequest:


@Slf4j
public class WrappedRequest extends HttpServletRequestWrapper {
    private final Map<String, String[]> modifiableParameters;
    private ResettableServletInputStream servletStream;
    private byte[] rawData;
    private HttpServletRequest request;
    private String payload;


    /**
     * Create a new request wrapper that will merge additional parameters into
     * the request object without prematurely reading parameters from the
     * original request.
     *
     * @param request
     * @param additionalParams
     */
    public WrappedRequest(final HttpServletRequest request,
                          final Map<String, String[]> additionalParams) {
        super(request);
        this.request = request;
        this.modifiableParameters = new TreeMap<String, String[]>();
        this.modifiableParameters.putAll(additionalParams);
        this.servletStream = new ResettableServletInputStream();
    }

    /**
     * @param newRawData
     */
    public void resetStream(byte[] newRawData) {
        servletStream.stream = new ByteArrayInputStream(newRawData);
    }

    /**
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        if (rawData == null) {
            rawData = IOUtils.toByteArray(this.request.getReader());
            servletStream.stream = new ByteArrayInputStream(rawData);
        }
        return servletStream;
    }

    /**
     * @return
     * @throws IOException
     */
    @Override
    public BufferedReader getReader() throws IOException {
        if (rawData == null) {
            rawData = IOUtils.toByteArray(this.request.getReader());
            servletStream.stream = new ByteArrayInputStream(rawData);
        }
        return new BufferedReader(new InputStreamReader(servletStream, Constants.UTF_8));
    }

    /**
     * @return
     */
    private String getBodyAsString() {
        StringBuffer buff = new StringBuffer();
        buff.append(" BODY_DATA START [ ");
        char[] charArr = new char[getContentLength()];
        try {
            BufferedReader reader = new BufferedReader(getReader());
            reader.read(charArr, 0, charArr.length);
            reader.close();
        } catch (IOException e) {
            log.error("", e);
        }
        buff.append(charArr);
        buff.append(" ] BODY_DATA END ");
        return buff.toString();
    }

    /**
     * @return
     */
    public String getPayload() {
        return payload;
    }

    /**
     * @param payload
     */
    public void setPayload(String payload) {
        this.payload = payload;
    }

    private static class ResettableServletInputStream extends ServletInputStream {

        private InputStream stream;

        @Override
        public int read() throws IOException {
            return stream.read();
        }

        @Override
        public boolean isFinished() {
            return false;
        }

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

        @Override
        public void setReadListener(ReadListener readListener) {

        }
    }
}

Тело, которое я ожидал получить в контроллере : filter

Что я получаю: controller

@PostMapping(value = "/edit")
    public String editPlatform(EditInfo editInfo, Model model) {
        Optional<Platform> p = platformService.findById(editInfo.getId());
        List<SafeCustodyOffice> officeList = safeCustodyOfficeService.getAll();

        if (p.isPresent()) {
            model.addAttribute("platform", p.get());
            model.addAttribute("offices", officeList);
            return "platform-edit";
        } else {
            throw new KfsException(ErrorCodes.KFS19);
        }
    }

Важно Редактировать:

Я обнаружил кое-что интересное и дал мне подсказки о проблеме. Это может иметь больше смысла для всех, кроме меня.

Я вижу, что тип содержимого ввода изменяет результат следующим образом:

enter image description here

Есть ли обходной путь, чтобы комбинация строки 5 работала так же, как строка 3?

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