7、Comet的服务器推送技术,基于Ajax,DeferredResult实现长轮询

注:源代码来自享学课堂,略有修改,学习之后所做笔记,方便回顾,也给大家一个参考

DeferredResult实现长轮询

页面每次调用请求之后,在方法结束的时候,再次自我调用

<%@ page language = "java" contentType= "text/html; charset=UTF-8" pageEncoding= "UTF-8" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>测试</title>
</head>
<body>
<h1>新闻</h1>
<div>
    <div>
        <h2实时变化的新闻</h2>
        <div style="color:#F00"><b><p id="realTimeNews">  </p></b></div>
    </div>
</div>
<script type="text/javascript" src="assets/js/jquery-1.9.1.min.js"></script>
<script type="text/javascript">

    longLoop();

    function longLoop() {
        $.get("realTimeNews",function (data) {
            console.log(data);
            $("#realTimeNews").html(data);
            //马上再发起请求
            longLoop();
        })
    }


</script>
</body>
</html>

服务器要开启异步调用, servlet.setAsyncSupported(true);这里的WebApplicationInitializer相当于web.xml配置修改

public class WebInit implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext)
            throws ServletException {

        AnnotationConfigWebApplicationContext ctx
                = new AnnotationConfigWebApplicationContext();
        ctx.register(CometMvcConfig.class);
        ctx.setServletContext(servletContext);
        
        ServletRegistration.Dynamic servlet = servletContext.addServlet("dispatcher",
                new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
        //启用异步
        servlet.setAsyncSupported(true);

    }
}

服务器基本配置

@Configuration
@EnableWebMvc
@EnableScheduling
@ComponentScan("cn.gg")
public class CometMvcConfig extends WebMvcConfigurerAdapter{

    @Bean
    public InternalResourceViewResolver viewResolver(){
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        viewResolver.setViewClass(JstlView.class);
        return viewResolver;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/assets/**")
        		.addResourceLocations("/assets/");
    }
}

生成任意消息的对象

public class Const {
    public static final String[] NEWS = {
            "床前明月光",
            "疑是地上霜",
            "举头望明月",
            "低头思故乡"
};
}

使用DeferredResult实现长轮询

@Controller
@RequestMapping(produces="text/html;charset=UTF-8")
/*记得要在WebInitializer中增加servlet.setAsyncSupported(true);*/
public class PushNewsController {

    private ExecutorService executorService
            = Executors.newFixedThreadPool(1);

    @RequestMapping("/pushnews")
    public String news(){
        return "pushNews";
    }

    @RequestMapping(value="/realTimeNews")
    @ResponseBody
    /*在WebInitializer中要加上servlet.setAsyncSupported(true);*/
    public DeferredResult<String> realtimeNews(HttpServletRequest request){
        final DeferredResult<String> dr = new DeferredResult<String>();

        executorService.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                int index = new Random().nextInt(Const.NEWS.length);
                //setResult会刷新页面的数据
                dr.setResult(Const.NEWS[index]);
            }
        });
        return dr;
    }

}

访问页面的时候,新闻会不断自动刷新

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章