java AsyncContext printWriter 推送資料到前端 觀察者模式
阿新 • • 發佈:2019-01-23
做了一個功能,前端檢視一些資料, 而資料在後端 是通過大量的分析 比較 得到了, 時間比較長! 假如得到這些資料(List<Object>)需要10分鐘, 所以現在只要後端得到一條資料 <Object>就直接推送到前端;
使用觀察者模式, 和 AsyncContext 非同步處理
檢視大概是這樣
OK,如圖所示貼上程式碼
1.被觀察者
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.Observable; 4 5 import org.apache.commons.lang3.StringUtils;6 7 import com.data2wisdom.res.dsmgr.common.StringUtil; 8 9 public class ForginRelation extends Observable { 10 private int total; 11 private int stepNum; //比對到第N個 12 private String relationId; 13 private int status = 0; //比對狀態 0:初始化 , 1 :正在比對, 2:比對完成 , 3:異常 14 15 privateList<ForginRelationObj> ffos = new ArrayList<>(); 16 17 18 19 //這裡是通知觀察者 20 public void addOneFr(ForginRelationObj relationObj) { 21 System.out.println("執行了新增操作"); 22 this.ffos.add(relationObj); 23 setChanged(); 24 notifyObservers(); 25} 26
2,,觀察者
2 3 import java.io.IOException; 4 import java.io.PrintWriter; 5 import java.util.ArrayList; 6 import java.util.List; 7 import java.util.Observable; 8 import java.util.Observer; 9 10 import javax.servlet.AsyncContext; 11 12 import org.apache.log4j.Logger; 13 14 import com.google.gson.Gson; 15 16 public class FindRelationObserver implements Observer{ 17 private static Logger log = Logger.getLogger(FindRelationObserver.class); 18 private AsyncContext async; 19 private int num ; 20 21 public FindRelationObserver(AsyncContext async,ForginRelation forginRelation) { 22 super(); 23 this.async = async; 24 forginRelation.addObserver(this);//新增被觀察者 25 } 26 27 @Override 28 public void update(Observable fr, Object arg) { 29 try { 30 PrintWriter printWriter = null; 31 try { 32 printWriter = async.getResponse().getWriter(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 log.info("非同步獲取資料異常:"+e); 36 } 37 //業務邏輯可以不看 38 ForginRelation forginRelation = (ForginRelation)fr; 39 List<ForginRelationObj> ffos = forginRelation.getFfos(); 40 List<ForginRelationObj> tempData = new ArrayList<>(); 41 int temp = num; 42 num = ffos.size(); 43 for (int i = temp; i < num ; i++) { 44 tempData.add(ffos.get(i)); 45 } 46 Gson gson = new Gson(); 47 String json = gson.toJson(tempData);
//這裡是資料輸出到前端, flush一下 48 printWriter.write("<script> parent.dataRender('"+json+"'); </script>"); //parent中開啟, 看最後面的頁面請求方式 49 printWriter.flush(); 50 51 if(forginRelation.getStatus() == 2 || forginRelation.getStatus() == 3) { 52 printWriter.close(); 53 forginRelation.deleteObserver(this);//非同步結束,移除觀察者 54 async.complete();//非同步結束 55 } 56 } catch (Exception e) { 57 58 e.printStackTrace(); 59 } 60 } 61 62 }
3.請求介面
1 @RequestMapping(value = "/result", method = { RequestMethod.GET }) 2 public void index(HttpServletResponse response,HttpServletRequest request,String relationId) { 3 response.setContentType("text/html;charset=UTF-8"); 4 response.setCharacterEncoding("UTF-8"); 5 AsyncContext async = null; 6 PrintWriter writer = null; 7 ForginRelation relation = null; 8 9 try { 10 async = request.startAsync(request,response); 11 async.setTimeout(0); //超時設定 34 relation = relationMap.getForginRelationById(relationId); 35 async.addListener(new ForginRelationAsyncListener()); 36 async.start(new AsyncResult(async, relation)); //這裡由於資料傳遞需要實現runnable 所以包裝了個物件AsyncResult 39 }catch (Exception e) { 40 41 e.printStackTrace(); 42 logger.info(e); 43 44 }finally { 45 46 }
1 import javax.servlet.AsyncContext; 2 3 public class AsyncResult implements Runnable{ 4 private AsyncContext async; 5 6 private ForginRelation relation; 7 8 public AsyncResult(AsyncContext async,ForginRelation relation){ 9 this.async = async; 10 this.relation = relation; 11 } 12 13 14 @Override 15 public void run() { 16 new FindRelationObserver(async, relation); 17 }
4.前端請求 沒理解,需要form表單請求 不然會出問題,我也不理解啥原因
1 <body> 2 3 <div class="form-body layer-content"> 4 5 <div> 6 7 <div style="padding:20px;"> 8 <div class="form-group"> 9 <!-- <h3 class="margin-bottom-10 sub">新增表</h3> --> 10 <table class="layui-table" id="forginRelation"></table> 11 </div> 12 </div> 13 14 </div> 15 16 17 </div> 18 19 20 <div id="content" class="display_none" > 21 <form id="queryForm" name="queryForm" action="/rest/combing/findr/result" method="get"> 22 <input type="text" id="relationId" name="relationId" /> 23 </form> 24 </div> 25 26 <iframe id="dataCometFrame" src="" name="dataCometFrame" width="0" height="0" ></iframe>
<script type="text/javascript">
$("#queryForm").attr("target", "dataCometFrame"); //需要在iframe中開啟
$("#relationId").val($("base").attr("relationId")) //我的業務請求引數
$("#queryForm").submit(); //提交表單
function dataRender(data){
console.log("dataRender:");
console.log(data);
}
</script>
27 </body>