Ответы на составные данные весеннего журнала и запрос на публикацию

#java #spring-boot #http #servlets

Вопрос:

Я пытаюсь регистрировать запросы и ответы с помощью пользовательского класса регистратора. Все это прекрасно работало, пока я не начал получать Http-запросы с типами «составные/данные».

С тех пор все отправленные типы «составных/данных» выдают ошибки и не работают должным образом.

Сначала я получил сообщение об ошибке: Не удалось обработать детали, так как не была предоставлена конфигурация из нескольких частей

Поэтому я попытался схватить эти конкретные составные ответы и управлять ими по-разному, но безрезультатно. Я убрал супер.doDispatcher(req, res) Я не уверен, что это правильный путь.

Вот мой класс логгера:

 public class LoggableDispatcherServlet extends DispatcherServlet {

    private final Log logger = LogFactory.getLog(getClass());

    @Override
    protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
        if (!(request instanceof ContentCachingRequestWrapper)) {
            request = new ContentCachingRequestWrapper(request);
        }
        if (!(response instanceof ContentCachingResponseWrapper)) {
            response = new ContentCachingResponseWrapper(response);
        }
        HandlerExecutionChain handler = getHandler(request);

        boolean mulipart = false;
        try {
            if (request.getContentType() != null amp;amp; request.getContentType().toLowerCase().contains("multipart/form-data")){
                logger.info("MULTIPART FILE RECEIVED");
                mulipart = true;
            }else
                super.doDispatch(request, response);

        }catch(Exception e){
            logger.error(e.getMessage(), e);
        }finally {
            if (mulipart){
                response = new ContentCachingResponseWrapper(response);                
                log(request, null, handler);               
                updateResponse(response);
            } else {
                log(request, response, handler);
                updateResponse(response);
            }
        }
    }

    private void log(HttpServletRequest requestToCache, HttpServletResponse responseToCache, HandlerExecutionChain handler) {
        LogMessage log = new LogMessage();
        log.setHttpMethod(requestToCache.getMethod());
        log.setUrl(requestToCache.getRequestURI());
        log.setClientIp(requestToCache.getRemoteAddr());
        log.setJavaMethod(handler.toString());
        if(responseToCache != null){
            log.setHttpStatus(responseToCache.getStatus());
            log.setResponse(getResponsePayload(responseToCache));
        }
        logger.info(log);
    }

    private String getResponsePayload(HttpServletResponse response) {
        ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
        if (wrapper != null) {

            byte[] buf = wrapper.getContentAsByteArray();

            if (buf.length > 0) {
                int length = Math.min(buf.length, 5120);
                try {
                    return new String(buf, 0, length, wrapper.getCharacterEncoding());
                }
                catch (UnsupportedEncodingException e) {
                    logger.error(e.getMessage(), e);
                }
            }
        }
        return "[unknown]";
    }


    private void updateResponse(HttpServletResponse response) throws IOException {
        ContentCachingResponseWrapper responseWrapper =
                WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
        responseWrapper.copyBodyToResponse();
    }

}
 

Он завершается ошибкой в части updateResponse(ответ), когда multipart = true. Я пытался отправлять разные ответы, я бы жил с отправкой даже пустого ответа, но он просто неправильно его обрабатывает, и класс не переходит к контроллеру, когда он состоит из нескольких частей.

Обновить:

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

Именно так инициализируются компоненты:

 
import com.altair.autoTester.logs.LoggableDispatcherServlet;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;

@Configuration
public class LogsConfig {

    @Bean
    public ServletRegistrationBean dispatcherRegistration() {
        return new ServletRegistrationBean(dispatcherServlet());
    }

    @Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
    public DispatcherServlet dispatcherServlet() {
        return new LoggableDispatcherServlet();
    }
 

Ответ №1:

У вас есть else то, чего, вероятно, там быть не должно.

            if (request.getContentType() != null amp;amp; request.getContentType().toLowerCase().contains("multipart/form-data")){
                logger.info("MULTIPART FILE RECEIVED");
                mulipart = true;
            }else
                super.doDispatch(request, response);
 

должно быть

            if (request.getContentType() != null amp;amp; request.getContentType().toLowerCase().contains("multipart/form-data")){
                logger.info("MULTIPART FILE RECEIVED");
                mulipart = true;
            }
            super.doDispatch(request, response);
 

Комментарии:

1. Когда я исполню » супер. doDispatch(запрос, ответ)’ с составным содержимым я получаю ошибку, указанную выше: «Не удается обработать детали, поскольку конфигурация из нескольких частей не была предоставлена».

2. Работает ли ваш код при удалении сервлета ведения журнала?

3. Да, это работает. Он идет прямо к контроллеру и выполняет функции нормально, с помощью ServletDispatcher он даже не попадает на контроллер

4. Просто чтобы быть уверенным, org.springframework.web.servlet.DispatcherServlet мы ведь об этом говорим, верно? Создается ли он внутри контекста Spring (он же @Bean)?

5. правильно, это класс, который я использую, и он инициализирован аннотацией @Bean. Я обновил ответ с помощью класса инициализации