Spring MVC InterceptorHandler 使用 DeferredResult 调用了两次

2022-09-02 08:53:15

当我使用自定义并且我的控制器返回时,我的自定义拦截器的方法在每个请求上调用两次。考虑一个玩具的例子。HandlerInterceptorDeferredResultpreHandle

我的自定义拦截器:

public class MyInterceptor implements HandlerInterceptor {
    static int i = 0;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println(i++);
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    }
}

我的Spring Java配置:

@Configuration
@EnableWebMvc
public class ApplicationConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor());
    }
}

我的控制器:

@Controller
public class MyController {

    @RequestMapping(value = "/test", method = RequestMethod.GET)
    public DeferredResult<String> test() {
        DeferredResult<String> df = new DeferredResult<String>();
        df.setResult("blank");
        return df;
    }
}

因此,在每个页面加载时,我看到来自方法的两个输出。但是,如果我进行修改以仅返回“空白”模板(而不是“空白”模板),则每个页面加载时我只看到一个输出。preHandleMyControllerDeferredResultpreHandle

所以,我的问题是为什么在我使用时调用两次,是否有可能避免这种情况?preHandleDeferredResult


答案 1

您需要使用:org.springframework.web.servlet.AsyncHandlerInterceptor

public interface AsyncHandlerInterceptor extends HandlerInterceptor {

    void afterConcurrentHandlingStarted(
            HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception;

}

弹簧 MVC 执行序列:

preHandle
afterConcurrentHandlingStarted
preHandle
postHandle
afterCompletion

答案 2

通过检查 request.getDispatcherType() 的值可以看出这两个调用之间的差异。


推荐