使用最新最好的 Spring 3.2.3、Tomcat 7.0.42、Servlet 3.0 容器、Java 7。我们需要为响应执行 JSONP,因此我们通过执行 Servlet Filter 来实现它,如下所示:
但目前没有 web.xml..我们正在使用 Java Annotation Config。
在 our@Controller
中,我们返回一个DeferredResult<String>
,然后在@Service
由 our 调用的 our@Controller
中,我们有@Async
注解。我们走这@Async
条路线(不是 AysncContext 路线)的原因是因为这是一个“即发即弃”类型的异步操作。但我确实需要向请求者返回一些表明操作已开始的 JSON。
@RequestMapping(method = RequestMethod.GET, produces=MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public DeferredResult<String> testing(@RequestParam(value="submit", required=true) String param)
{
final DeferredResult<String> result = new DeferredResult<String>();
service.doIt(param, result);
return result;
}
而在我们的@Service
@Async
public DeferredResult<String> doIt(String param2, DeferredResult<String> result)
{
log.info("Calling Async doIt Method");
result.setResult("{hello:there}");
}
我被卡住了...我想弄清楚是否有办法在 Java Config 中为 Servlet 过滤器添加支持异步的标签?我基于看到此演示文稿(幻灯片 28):
http://rstoyanchev.github.io/spring-mvc-32-update/#28
其他一些信息:
在配置上,我们@EnableAsync
正在使用 AbstractAnnotationConfigDispatcherServletInitializer 来定义我们的应用程序,但我似乎无法弄清楚如何告诉它使用异步过滤器(仅使用getServletFilters()
返回我们的 JsonpFilter)。
基本上发生的事情是JSONP过滤器没有“包装”任何东西......但我确实看到过滤器第二次被调用,在TaskExecutor线程中设置结果之后......但此时响应已经消失...所以,我看到过滤器“获取数据”两次..在@Controller
方法退出时一次,然后在设置 DeferredResult.setResult() 后第二次。
我们也在我们的过滤器类上尝试了这个:
@WebFilter(urlPatterns = "/*", asyncSupported = true)
但这不起作用(甚至看起来它甚至根据日志制作了 2 个单独的过滤器..但是,我可能错了)。
如果需要,我们可以切换到 Callable ......这没什么大不了的。我确实看到 DeferredResult 和 Callable 在 Spring 所知道的线程方面存在一些差异。
如果答案是您需要使用 web.xml,那么有什么真正好的方法可以使用 web.xml 混合进行 Java Config?
编辑1:
基于阅读一些不同的资源,我发现了几件事:
- 来自:Spring Aync 预览博客
Servlet 过滤器
*所有 Spring Framework Servlet 过滤器实现都已根据需要进行了修改,以在异步请求处理中工作。至于任何其他过滤器,有些过滤器会起作用——通常是那些进行预处理的过滤器,而其他过滤器则需要修改——通常是那些在请求结束时进行后处理的过滤器。此类过滤器需要识别何时退出初始 Servlet 容器线程,为另一个线程继续处理让路,以及何时将它们作为异步调度的一部分调用以完成处理。**
- 来自 Spring MVC 参考。docs,我实际上是 RTFM 的:
使用 DeferredResult 处理异步请求的事件序列原则上是相同的,只是由应用程序从某个线程产生异步结果:(1)控制器返回一个 DeferredResult 并将其保存在某个内存队列或列表中,其中它可以被访问,(2) Spring MVC 启动异步处理,(3) DispatcherServlet 和所有配置的 Filter 退出请求处理线程但响应保持打开,(4) 应用程序从某个线程设置 theDeferredResult 并且 Spring MVC 调度请求回到 Servlet 容器,(5) 再次调用 DispatcherServlet 并使用异步生成的结果继续处理。
所以,基本上,我知道/知道单独的线程会调用过滤器......这不是让我感到困惑的事情......这是如何确定过滤器是否应该修改响应......你可以'不要查看数据的大小,因为 0 字节可能是正确的“答案”。
所以,我现在只写 DispatchType = ASYNC
不太确定长期这样做是否正确..但是,它似乎确实解决了问题。
还有其他建议/想法吗?