springboot實戰第四章-服務端推送技術
阿新 • • 發佈:2019-02-11
服務端推送技術
本節的服務端推送技術基於:當客戶端向服務端傳送請求,服務端會抓住這個請求不放,當有資料更新的時候才返回給客戶端,當客戶端接收到訊息後,再向服務端傳送請求,周而復始
第一種:基於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.演示效果