【问题标题】:Spring log multipart data responses and post requestSpring 记录多部分数据响应和发布请求
【发布时间】:2021-10-08 15:57:05
【问题描述】:

我正在尝试使用自定义记录器类记录请求和响应。在我开始收到具有“多部分/数据”类型的 Http 请求之前,这一切都运行良好。

从那时起,所有发送的“多部分/数据”类型都引发错误并且无法正常运行。

我首先收到一条错误消息:无法处理部件,因为没有提供多部件配置

所以我尝试获取那些特定的多部分响应并以不同的方式管理它们,但无济于事。我删除了 super.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 && 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();
    }

}

当 multipart = true 时,它​​在 updateResponse(response) 部分失败。我尝试发送不同的响应,我什至可以发送空响应,但它只是没有正确处理它,并且当这是多部分时,类不会继续到控制器。

更新:

如果我删除记录器类,那么请求会直接发送到控制器,并且它可以完美运行。

这是 Bean 的初始化方式:


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();
    }

【问题讨论】:

    标签: java spring-boot http servlets


    【解决方案1】:

    您的else 可能不应该存在。

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

    应该是

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

    【讨论】:

    • 当我使用多部分内容执行“super.doDispatch(request, response)”时,我收到上面列出的错误:“无法处理部分,因为没有提供多部分配置”
    • 删除日志记录 servlet 后您的代码是否正常工作?
    • 是的,它有效。它直接进入控制器并正常执行功能,使用 ServletDispatcher 它甚至没有到达控制器
    • 可以肯定的是,这就是我们所说的org.springframework.web.servlet.DispatcherServlet,对吧?它是在 Spring 上下文(又名 @Bean)中创建的吗?
    • 正确,这是我正在使用的类,它是使用@Bean 注释初始化的。我用初始化类更新了答案
    猜你喜欢
    • 2016-11-11
    • 1970-01-01
    • 2020-03-14
    • 2021-03-23
    • 1970-01-01
    • 2015-10-07
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    相关资源
    最近更新 更多