Spring使用event-stream進(jìn)行數(shù)據(jù)推送
前端使用EventSource方式向后臺發(fā)送請求,后端接收到之后使用event-stream方式流式返回。可以應(yīng)用在時鐘、逐字聊天等場景。
前端js示例代碼(向后臺請求數(shù)據(jù),并展示到“id=date”的div上)
<script type="text/javascript"> if (typeof (EventSource) !== "undefined") { var eventSource = new EventSource("${root}/test/getDate"); eventSource.onmessage = function (event) { document.getElementById("date").innerHTML = event.data; } eventSource.addEventListener('error', function (event) { console.log("錯誤:" + event); }); eventSource.addEventListener('open', function (event) { console.log("建立連接:" + event); }); } else { document.getElementById("date").innerHTML = "抱歉,您的瀏覽器不支持EventSource事件 ..."; } </script>
后端java示例
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletResponse; import java.util.Date; @Controller @RequestMapping(value = "/test") public class TestController { @ResponseBody @RequestMapping(value = "/getDate", produces = "text/event-stream;charset=UTF-8") public void getDate(HttpServletResponse response) throws Exception { System.out.println("getDate event start"); response.setContentType("text/event-stream"); response.setCharacterEncoding("UTF-8"); response.setStatus(200); for (int i = 0; i < 10; i++) { response.getWriter().write("data:" + new Date() + "\n\n"); response.getWriter().flush(); Thread.sleep(1000); } response.getWriter().close(); System.out.println("getDate event end"); } }
除了是這個方法,我們也可以使用Spring的定時器定時推送數(shù)據(jù)
定時器編寫
1.在配置文件里添加相關(guān)配置
? <!-- 定時器開關(guān) --> <task:annotation-driven /> <!-- 自動掃描的包名 --> <bean id="myTaskXml" class="定時方法所在的類的完整類名"></bean> <task:scheduled-tasks> <task:scheduled ref="myTaskXml" method="appInfoAdd" cron="*/5 * * * * ?"/> </task:scheduled-tasks> ?
上面的代碼設(shè)置的是每5秒執(zhí)行一次appInfoAdd方法,cron字段表示的是時間的設(shè)置,分為:秒,分,時,日,月,周,年。
2.定時方法的編寫
Logger log = Logger.getLogger(TimerTask.class);; public void apiInfoAdd(){ InputStream in = TimerTask.class.getClassLoader().getResourceAsStream("/system.properties"); Properties prop = new Properties(); try { prop.load(in); } catch (IOException e) { e.printStackTrace(); } String key = prop.getProperty("DLKEY"); log.info("key--" + key); //鎖數(shù)據(jù)操作 List<GbEsealInfo> list = this.esealService.loadBySendFlag("0"); if (list == null) { log.info("沒有需要推送的鎖數(shù)據(jù)"); }else{ JsonObject json = new JsonObject(); JsonArray ja = new JsonArray(); json.add("esealList", ja); for(int i = 0; i < list.size(); i++) { GbEntInfo ent = this.entService.loadByPk(list.get(i).getEntId()); JsonObject esealJson = getEsealJson(list.get(i), ent); ja.add(esealJson); } String data = json.toString(); log.info("鎖數(shù)據(jù)--" + data); HttpDeal hd = new HttpDeal(); Map<String,String> map = new HashMap<String, String>(); map.put("key",key); map.put("data", data); hd.post(prop.getProperty("ESEALURL"), map); log.info(hd.responseMsg); JsonObject returnData = new JsonParser().parse(hd.responseMsg).getAsJsonObject(); if (("\"10000\"").equals(returnData.get("code").toString())){ log.info("鎖數(shù)據(jù)推送成功"); for(int i = 0; i < list.size(); i++){ list.get(i).setSendFlag("1"); int res = this.esealService.updateSelectiveByPk(list.get(i)); if(res == 0){ log.info("第" + (i+1) + "條鎖數(shù)據(jù)的sendflag字段的狀態(tài)值修改失敗"); continue; } } } }
這個過程包括讀取配置文件里的key,從數(shù)據(jù)庫讀取數(shù)據(jù)(根據(jù)數(shù)據(jù)的字段判斷是否需要推送),使用GSON把數(shù)據(jù)拼裝成上一篇文章里的data的形式data={"esealList":[{},{},{}]},使用HttpClient執(zhí)行帶參數(shù)的POST方法,訪問POST接口,根據(jù)返回信息判斷狀態(tài)。
3.HttpClient里的帶參POST方法
public class HttpDeal { public String responseMsg; public String post(String url,Map<String, String> params){ //實(shí)例化httpClient CloseableHttpClient httpclient = HttpClients.createDefault(); //實(shí)例化post方法 HttpPost httpPost = new HttpPost(url); //處理參數(shù) List<NameValuePair> nvps = new ArrayList <NameValuePair>(); Set<String> keySet = params.keySet(); for(String key : keySet) { nvps.add(new BasicNameValuePair(key, params.get(key))); } //結(jié)果 CloseableHttpResponse response = null; String content=""; try { //提交的參數(shù) UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(nvps, "UTF-8"); //將參數(shù)給post方法 httpPost.setEntity(uefEntity); //執(zhí)行post方法 response = httpclient.execute(httpPost); if(response.getStatusLine().getStatusCode()==200){ content = EntityUtils.toString(response.getEntity(),"utf-8"); responseMsg = content; //System.out.println(content); } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return content; } public static void main(String[] args) { HttpDeal hd = new HttpDeal(); Map<String,String> map = new HashMap(); map.put("key","5c07db6e22c780e76824c88b2e65e9d9"); map.put("data", "{'esealList':[{'esealId':'1','entName':'q','entName':企業(yè),'id':'qqww','id':'123', 'customsCode':'qq','fax':'021-39297127'}]}"); hd.post("http://localhost:8080/EportGnssWebDL/api/CopInfoAPI/esealInfoAdd.json",map); } }
4.輔助類
/** * 輔助類:鎖接口需要的字段 * @param eseal * @param ent * @return */ private JsonObject getEsealJson(GbEsealInfo eseal, GbEntInfo ent){ JsonObject j = new JsonObject(); j.addProperty("esealId", eseal.getEsealId()); j.addProperty("vehicleNo", eseal.getVehicleNo()); j.addProperty("customsCode", eseal.getCustomsCode()); j.addProperty("simNo", eseal.getSimNo()); j.addProperty("entName", ent.getEntName()); j.addProperty("customsName", eseal.getCustomsName()); j.addProperty("leadingOfficial", ent.getLeadingOfficial()); j.addProperty("contact", ent.getContact()); j.addProperty("address", ent.getAddress()); j.addProperty("mail", ent.getMail()); j.addProperty("phone", ent.getPhone()); j.addProperty("fax", ent.getFax()); return j; }
以上就是Spring使用event-stream進(jìn)行數(shù)據(jù)推送的詳細(xì)內(nèi)容,更多關(guān)于Spring event-stream數(shù)據(jù)推送的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java 下執(zhí)行mysql 批量插入的幾種方法及用時
java 下執(zhí)行mysql 批量插入的幾種方法及用時,1000次插入方法的比較。2013-04-04Maven的pom.xml中resources標(biāo)簽的用法
本文主要介紹了Maven的pom.xml中resources標(biāo)簽的用法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07springboot+dynamicDataSource動態(tài)添加切換數(shù)據(jù)源方式
這篇文章主要介紹了springboot+dynamicDataSource動態(tài)添加切換數(shù)據(jù)源方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01springboot整合SSE的項(xiàng)目實(shí)踐
SSE是一種可以主動從服務(wù)端推送消息的技術(shù),本文主要介紹了springboot整合SSE的項(xiàng)目實(shí)踐,具有一定的參考價值,感興趣的可以了解一下2023-09-09實(shí)例解析觀察者模式及其在Java設(shè)計(jì)模式開發(fā)中的運(yùn)用
觀察者模式定義了一種一對多的依賴關(guān)系,讓多個觀察者對象同時監(jiān)聽某一個主題對象,這個主題對象在狀態(tài)上發(fā)生變化時,會通知所有觀察者對象,使它們能夠自動更新自己.下面就以實(shí)例解析觀察者模式及其在Java設(shè)計(jì)模式開發(fā)中的運(yùn)用2016-05-05