服务端推送技术
本节的服务端推送技术基于:当客户端向服务端发送请求,服务端会抓住这个请求不放,当有数据更新的时候才返回给客户端,当客户端接收到消息后,再向服务端发送请求,周而复始
第一种:基于SSE(Server Send Event)
1.演示控制器
package com.just.springmvc4.controller; import java.util.Random; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * 服务端推送 * 在消息体后面有两个换行符\n,代表当前消息体发送完毕,一个换行符标识当前消息并未结束, * 浏览器需要等待后面数据的到来后再触发事件; */ @RestController public class SSEController { @RequestMapping(value ="/push",produces = "text/event-stream;charset=UTF-8") public String sse(){ Random r=new Random(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } return "data:当前增加的收入:"+r.nextInt(1000)+"元"+"\n\n"; } }
注意推送的数据格式后面要有\n\n,输出的媒体类型为:text/event-stream,这是服务器端SSE的支持
2.演示页面
新建sse.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>SSE服务端推送测试</title> <style> h1{ color:red; } </style> </head> <body> <div id="msgFromPush"></div> <script src="../assets/js/jquery-3.3.1.min.js" type="text/javascript"></script> <script> /** * HTML5规范中提供了服务端事件EventSource,浏览器在实现了该规范的前提下创建一个EventSource连接后, * 便可收到服务端的发送的消息,这些消息需要遵循一定的格式, * 对于前端开发人员而言,只需在浏览器中侦听对应的事件皆可。 * 浏览器端,需要创建一个EventSource对象,并且传入一个服务端的接口URI作为参数。 */ if(!!window.EventSource){ var source=new EventSource("push"); s=''; source.addEventListener('message',function (e) { s+="<h1>"+e.data+"</h1>"; $("#msgFromPush").html(s); }); source.addEventListener('open',function (e) { console.log("连接打开"); },false); source.addEventListener('error',function (e) { if(e.readyState==EventSource.CLOSED){ console.log("连接关闭"); }else{ console.log(e.readyState); } },false); }else{ alert("当前这个渣渣浏览器不支持SSE"); } </script> </body> </html>
EventSource只有新式的浏览器才有,所以这种推送技术有局限性,且不支持跨域
至于jsp页面的ViewController配置这里就不多讲了。
3.演示效果
如下图所示:
第二种:Servlet3.0+异步方法处理
1.servlet配置文件开启异步方法支持
//注册DispatcherServlet ServletRegistration.Dynamic servlet=servletContext.addServlet("dispatcher",new DispatcherServlet(context)); servlet.addMapping("/"); servlet.setLoadOnStartup(1); servlet.setAsyncSupported(true); //开启异步方法的支持
2.异步任务控制器
package com.just.springmvc4.controller; import com.just.springmvc4.service.PushService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; @RestController public class AsyncController { @Autowired private PushService pushService; @RequestMapping(value = "/defer",produces = "text/html;charset=UTF-8") public DeferredResult<String> deferredCall(){ return pushService.getAsyncUpdate(); } }
3.定时任务
定时更新DeferredResult
package com.just.springmvc4.service; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.web.context.request.async.DeferredResult; @Service public class PushService { private DeferredResult<String> deferredResult; public DeferredResult<String> getAsyncUpdate(){ deferredResult=new DeferredResult<String>(); return deferredResult; } @Scheduled(fixedDelay = 3000) public void refresh(){ if(deferredResult!=null){ deferredResult.setResult("当前时间戳:"+System.currentTimeMillis()); } } }
4.演示页面
新建async.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>servlet async support</title> </head> <body> <div id="content"> </div> <h1 id="text"></h1> <script src="../assets/js/jquery-3.3.1.min.js" type="text/javascript"></script> <script> deferred(); function deferred() { $.get('defer',function (data) { $("#content").append("<h1>"+data+"</h1>"); deferred(); }) } </script> </body> </html>
5.MVC开启计划任务的支持
在MyMvcConfig类上加上注解
@EnableScheduling
6.演示效果