1. 程式人生 > >java AsyncContext printWriter 推送資料到前端 觀察者模式

java AsyncContext printWriter 推送資料到前端 觀察者模式

做了一個功能,前端檢視一些資料, 而資料在後端 是通過大量的分析 比較 得到了, 時間比較長! 假如得到這些資料(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 private
List<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>