2013-11-29 57 views
16

我使用spring mvc 3.2.4和jquery 1.9.0进行长轮询。我的应用程序部署在Tomcat 7.0.42上。我的spring配置文件如下:Spring MVC中的延迟结果返回不正确的响应

应用的web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee" 
    version="3.0"> 

    <welcome-file-list> 
     <welcome-file>index.html</welcome-file> 
    </welcome-file-list> 

    <servlet> 
     <servlet-name>app</servlet-name> 

     <servlet-class> 
      org.springframework.web.servlet.DispatcherServlet 
     </servlet-class> 

     <load-on-startup>1</load-on-startup> 
     <async-supported>true</async-supported> 
    </servlet> 

    <servlet-mapping> 
     <servlet-name>app</servlet-name> 
     <url-pattern>/</url-pattern> 
    </servlet-mapping> 

    <listener> 
     <listener-class> 
      org.springframework.web.context.ContextLoaderListener 
     </listener-class> 
    </listener> 

    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/app-servlet.xml 
     </param-value> 
    </context-param> 

</web-app> 

春CONFIGRATION XML为: -

<?xml version="1.0" encoding="UTF-8"?> 
<beans xmlns="http://www.springframework.org/schema/beans" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:p="http://www.springframework.org/schema/p" 
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:context="http://www.springframework.org/schema/context" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.2.xsd 
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd 
    http://www.springframework.org/schema/context 
    http://www.springframework.org/schema/context/spring-context-3.2.xsd"> 
     <context:annotation-config/> 
     <mvc:annotation-driven/> 
     <mvc:default-servlet-handler/> 
     <context:component-scan base-package="com.webchat"/> 
     <bean id="defferedResult" class="com.exp.DeferredResultContainer"></bean> 
</beans> 

控制器发布的数据看起来

@RequestMapping(value = "/postComment", method = RequestMethod.POST) 
public @ResponseBody String postComment(HttpServletRequest request) { 
    deferredResultContainer.updateAllResults(request.getParameter("comment")); 
    return "success"; 
} 

递延结果集装箱分类

public class DeferredResultContainer { 
    private final Set<DeferredResult<String>> deferredResults = Collections.synchronizedSet(new HashSet<DeferredResult<String>>()); 

    public void put(DeferredResult<String> deferredResult){ 
     deferredResults.add(deferredResult); 
    } 

    public void updateAllResults(String value){ 
     for (DeferredResult<String> deferredResult : deferredResults){ 
      deferredResult.setResult(value); 
     } 
    } 

    public void remove(DeferredResult<String> deferredResult){ 
     deferredResults.remove(deferredResult); 
    } 

    public int determineSize(){ 
     return deferredResults.size(); 
    } 
} 

控制器递延结果看起来

@RequestMapping(value = "/getComments", method = RequestMethod.GET) 
@ResponseBody 
public DeferredResult<String> getComments() throws Exception{ 
    final DeferredResult<String> deferredResult= new DeferredResult<String>(); 
    deferredResultContainer.put(deferredResult); 
    deferredResult.onTimeout(new Runnable() { 

     @Override public void run() { 
      deferredResultContainer.remove(deferredResult); 
     } 
    }); 

    deferredResult.onCompletion(new Runnable() { 
     @Override public void run() { 
      deferredResultContainer.remove(deferredResult); 
     } 
    }); 
    return deferredResult; 
} 

当我通过Ajax试图长轮询它我得到如下回应: -

也没有得到执行
{"setOrExpired":false} 

而且onCompletion方法。

简单地低于控制器东西给作为 完美响应{“1”:“2”}

@RequestMapping(value = "/test1", method = RequestMethod.GET) 
@ResponseBody 
public Map test1() throws Exception{ 
    Map m1 = new HashMap<String, Object>(); 
    m1.put("1", "2"); 
    return m1; 
} 

一旦我将其更改为以下并添加递延结果我得到响应, {“setOrExpired”:真正}

@RequestMapping(value = "/test", method = RequestMethod.GET) 
@ResponseBody 
public DeferredResult<Map> test() throws Exception{ 
    DeferredResult<Map> result = new DeferredResult<Map>(); 
    Map m1 = new HashMap<String, Object>(); 
    m1.put("1", "2"); 
    result.setResult(m1); 
    return result; 
} 

投票代码

$(document).ready(function() { 
    longPoll(); 

    function longPoll(){ 
     $.support.cors = true; 
     var path = "http://localhost:8080/WebChatExp/rest"; 
     $.ajax({ 
      url: path + "/getComments", 
      cache:false, 
      success: function(data){ 
       //To Do 
          alert("Data" + JSON.stringify(data)); 
      }, 
      error: function(err, status, errorThrown) { 

      }, 
      type: "GET", 
      dataType: "json", 
      complete: longPoll, 
      timeout: 60000 // timeout every one minute 
     }); 
    } 

我搜索了各种示例,但无法确定是否需要对延期结果进行额外配置。请指教。

+0

您是否尝试过调试?并检查请求是否来'getComments()'?什么是响应类型?它是json还是? – Jayasagar

+1

您可以使用其他客户端进行调试(https://addons.mozilla.org/en-US/firefox/addon/restclient/),并告诉我们您得到了什么。 –

+0

Firebug也是另外一个:) – Keerthivasan

回答

2

你得到

{"setOrExpired":true} 

响应正文表明春天连载您DeferredResult(其具有多种特性,包括setOrExpired)到JSON,而不是用DeferredResultMethodReturnValueHandler处理它。换句话说,它使用另一个HandlerMethodReturnValueHandler,很可能是RequestResponseBodyMethodProcessor(它处理@ResponseBody)来处理从@RequestMapping注释的处理程序方法返回的值。 (测试这种最简单的方法就是看看会发生什么,当你删除@ResponseBody注解。)

3.2.x source code of RequestMappingHandlerAdapter,其注册缺省HandlerMethodReturnValueHandler情况来看,该DeferredResultMethodReturnValueHandlerRequestResponseBodyMethodProcessor之前注册的,因此将处理DeferredResult返回值第一。

由于您看到不同的行为,因此我们必须假定您的配置不是您在此显示的内容。 (请注意,<mvc:annotation-driven/>注册了RequestMappingHandlerAdapter。)


另外请注意,您正在加载配置在/WEB-INF/app-servlet.xml两次,一次是由ContextLoaderListener,一旦由DispatcherServlet

彻底摆脱您的ContextLoaderListener和相应的context-param。在你的例子中它们不是必需的。