第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

讀取異步請(qǐng)求中的響應(yīng)正文

讀取異步請(qǐng)求中的響應(yīng)正文

搖曳的薔薇 2024-01-05 14:47:58
我想知道如果 @Controller 方法返回 Callable 接口,如何從請(qǐng)求正文中讀取過濾器中的響應(yīng)。我的過濾器看起來像這樣。響應(yīng)始終為空。有什么辦法解決這個(gè)問題嗎?僅使用 AsyncListener 才允許這樣做嗎?@Componentpublic class ResposeBodyXmlValidator extends OncePerRequestFilter {    private final XmlUtils xmlUtils;    private final Resource xsdResource;    public ResposeBodyXmlValidator(        XmlUtils xmlUtils,        @Value("classpath:xsd/some.xsd") Resource xsdResource    ) {        this.xmlUtils = xmlUtils;        this.xsdResource = xsdResource;    }    @Override    protected void doFilterInternal(        HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain    ) throws ServletException, IOException {        ContentCachingResponseWrapper response = new ContentCachingResponseWrapper(httpServletResponse);        doFilter(httpServletRequest, response, filterChain);        if (MediaType.APPLICATION_XML.getType().equals(response.getContentType())) {            try {                xmlUtils.validate(new String(response.getContentAsByteArray(), response.getCharacterEncoding()), xsdResource.getInputStream());            } catch (IOException | SAXException e) {                String exceptionString = String.format("Chyba p?i volání %s\nNevalidní vystupní XML: %s",                    httpServletRequest.getRemoteAddr(),                    e.getMessage());                response.setContentType(MediaType.TEXT_PLAIN_VALUE + "; charset=UTF-8");                response.setCharacterEncoding(StandardCharsets.UTF_8.name());                response.getWriter().print(exceptionString);            }        }        response.copyBodyToResponse(); // I found this needs to be added at the end of the filter    }}
查看完整描述

1 回答

?
德瑪西亞99

TA貢獻(xiàn)1770條經(jīng)驗(yàn) 獲得超3個(gè)贊

Callable 的問題在于調(diào)度程序 servlet 本身會(huì)啟動(dòng)異步處理,并且過濾器會(huì)在實(shí)際處理請(qǐng)求之前退出。


當(dāng) Callable 到達(dá)調(diào)度程序 servlet 時(shí),它通過釋放所有過濾器(過濾器基本上完成其工作)來從池中釋放容器線程。當(dāng) Callable 產(chǎn)生結(jié)果時(shí),會(huì)使用相同的請(qǐng)求再次調(diào)用調(diào)度程序 servlet,并且響應(yīng)會(huì)立即由 Callable 返回的數(shù)據(jù)完成。這是由類型的 request 屬性處理的,AsyncTaskManager該屬性保存有關(guān)異步請(qǐng)求處理的一些信息。這可以用Filter和進(jìn)行測試HandlerInterceptor。Filter只執(zhí)行一次但HandlerInterceptor執(zhí)行了兩次(原始請(qǐng)求和Callable完成工作后的請(qǐng)求)


當(dāng)您需要讀取請(qǐng)求和響應(yīng)時(shí),解決方案之一是像這樣重寫dispatcherServlet:


@Bean

@Primary

public DispatcherServlet dispatcherServlet(WebApplicationContext context) {

    return new DispatcherServlet(context) {

        @Override

        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

            ContentCachingRequestWrapper requestWrapper = new ContentCachingRequestWrapper(request);

            ContentCachingResponseWrapper responseWrapper = new ContentCachingResponseWrapper(response);

            super.service(requestWrapper, responseWrapper);

            responseWrapper.copyBodyToResponse();

        }

    };

}

這樣您就可以確??梢远啻巫x取請(qǐng)求和響應(yīng)。另一件事是像這樣添加 HandlerInterceptor (您必須傳遞一些數(shù)據(jù)作為請(qǐng)求屬性):


    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws

        Exception {

        Object asyncRequestData = request.getAttribute(LOGGER_FILTER_ATTRIBUTE);

        if (asyncRequestData == null) {

            request.setAttribute(LOGGER_FILTER_ATTRIBUTE, new AsyncRequestData(request));

        }

        return true;

    }


    @Override

    public void afterCompletion(

        HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex

    ) throws Exception {

        Object asyncRequestData = request.getAttribute(LOGGER_FILTER_ATTRIBUTE);

        if (asyncRequestData != null && response instanceof ContentCachingResponseWrapper) {

            log(request, (ContentCachingResponseWrapper) response, (AsyncRequestData) asyncRequestData);

        }

    }

afterCompletion方法僅在異步請(qǐng)求完全處理后調(diào)用一次。preHandle被調(diào)用兩次,因此您必須檢查屬性是否存在。在afterCompletion中,調(diào)用的響應(yīng)已經(jīng)存在,如果您確實(shí)想要替換它,您應(yīng)該調(diào)用response.resetBuffer().


這是一種可能的解決方案,并且可能有更好的方法。


查看完整回答
反對(duì) 回復(fù) 2024-01-05
  • 1 回答
  • 0 關(guān)注
  • 150 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)