ajaxによるサービス側非同期タスクステータスリスニングの実現


プロジェクトでは、ユーザー体験を改善するために、時間のかかる操作は非同期で実行されることが多いが、タスクをバックグラウンドに入れると、ユーザーはタスク実行の結果をタイムリーに得ることができない.したがって、タスクの進行状況を継続的に追跡できる方法が必要である.各リスニングタスクには、タスクIDが割り当てられ、タスクリスニングが終了した後に解放されます.
グローバルリスナーの実装
一例のモードに基づいて、任意のタスクを格納するためにシステムによってグローバルにアクセス可能なリスニングデータを設定する.同時にValue部分は特殊特殊な構造を使用します.
こうぞうせっけい
つまり、HashMapのValueに格納されている部分です.
public class ValueStruc {

    private boolean expireable;
    private Date expireTime;
    private Object value;
    private int readCount;

    public ValueStruc(){}
    public ValueStruc(Object value, Date expireTime){
        this.value = value;
        this.expireable = true;
        this.expireTime = expireTime;
        this.readCount = 0;
    }
    public ValueStruc(Object value){
        this.value = value;
        this.readCount = 0;
    }

    public Object readValue(){
        readCount = readCount +1;
        return this.value;
    }

    public boolean expired(){
        if(expireable){
            return new Date().after(expireTime);
        } else {
            return false;
        }
    }

    public boolean isExpireable(){
        return this.expireable;
    }

    public void setExpireable(boolean exb){
        this.expireable = exb;
    }

    public Date getExpireTime(){
        return expireTime;
    }

    public void setExpireTime(Date exd){
        this.expireTime = exd;
    }

    public Object getValue(){
        return value;
    }

    public void setValue(Object v){
        this.value = v;
    }

    public int getReadCount(){
        return readCount;
    }

    public void setReadCount(int readCount){
        this.readCount = readCount;
    }

}

リスナー
プログラムの任意の場所に傍受IDを登録し、IDに対応する情報を更新、読み出しするためのものである.同時にIDの期限切れクリア、行為記録の読み取りなどをサポートすべきである.コードは次のとおりです.

public class DataObserver {

    private HashMap<String, ValueStruc> map;
    private volatile static DataObserver instance;
    private DataObserver(){
        map = new HashMap<String, ValueStruc>();
    }
    public static DataObserver getInstance(){
        if(instance == null){
            synchronized(DataObserver.class){
                if(instance == null){
                    instance = new DataObserver();
                }
            }
        }
        return instance;
    }

    /** *   Key<br> *   :     ,key, value<br> *   :         ,     ,                  ,0    <br> * Function: register * *  @author wengshengyuan DateTime 2015-10-12   9:16:01 *  @param key *  @param value *  @param Sec *  @return ValueStruc,    key   null */
    public ValueStruc register(String key, Object value, int Sec) {
        if(map.containsKey(key))
            return null;
        Date now = new Date();
        if(Sec > 0){
            Date expireTime = DateUtils.addSeconds(now, Sec);
            ValueStruc v = new ValueStruc(value, expireTime);
            map.put(key, v);
            return v;
        } else {
            ValueStruc v = new ValueStruc(value);
            map.put(key, v);
            return v;
        }
    }

    /** *         * Function: update * *  @author wengshengyuan DateTime 2015-10-12   1:45:46 *  @param key *  @param value *  @return      ,    Key,   null */
    public ValueStruc update(String key, Object value){
        if(map.containsKey(key)){
            ValueStruc v = map.get(key);
            v.setValue(value);
            map.put(key, v);
            return v;
        } else {
            return null;
        }
    }

    /** *   key<br> * Function: read * *  @author wengshengyuan DateTime 2015-10-12   9:29:48 *  @param key *  @return    Object,          null */
    public Object read(String key){
        ValueStruc v = map.get(key);
        if(v == null)
            return null;
        if(v.expired()){
            map.remove(key);
            return null;
        }
        return v.readValue();
    }

    /** *     Key  <br> *      ,       ,      ,   null * Function: remove * *  @author wengshengyuan DateTime 2015-10-12   11:09:39 *  @param key *  @return */
    public ValueStruc remove(String key){
        return map.remove(key);
    }

    /** *   map * Function: clear * *  @author wengshengyuan DateTime 2015-10-12   11:10:23 */
    public void clear(){
        map = new HashMap<String, ValueStruc>();
    }
}

使用方法
登録
非同期メソッドを実行する前に、リスニングIDが生成され、非同期実行体に入力される.実行ステータスの更新は非同期タスクによって更新されます.
String observerID = "taskName_"+UUIDUtils.getUUID32();
DataObserver.getInstance().register(observerID,value,-1);
AsyncTask task = new AsyncTask(String observerID);
task.start();

更新
非同期タスクでいつでも呼び出す
DataObserver.getInstance().update(observerID, value);

読み取り
DataObserver.getInstance().read(observerID);

Controllerレイヤインタフェース
JAVAサービス側API実現
Controllerでデータ転送インタフェースを定義します.追加、削除、変更、検索、消去などの機能が含まれています.ここではクエリーを例に挙げます.Controllerコードは次のとおりです.
@Controller
@RequestMapping(value="/api/observer")
public class DataObserverAPI {

    @ResponseBody
    @RequestMapping(value = "observe/{key}", method = RequestMethod.GET)
    public ResultInfo observe(HttpServletRequest request, @PathVariable("key") String key){
        ResultInfo result = new ResultInfo();
        Object o = DataObserver.getInstance().read(key);
        if(o == null){
            result.setStateId(-1);
            result.setErrorMsg("      ");
        } else {
            result.addObj2Map("value", o);
        }
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "regester/{key}/{value}/{timeout}", method = RequestMethod.GET)
    public ResultInfo testObserver(HttpServletRequest request, @PathVariable("key") String key, @PathVariable("value") String value
            , @PathVariable("timeout") int timeout){
        ResultInfo result = new ResultInfo();
        ValueStruc v =  DataObserver.getInstance().regester(key, value, timeout);
        if(v == null){
            result.setStateId(-1);
            result.setErrorMsg("    ");
        } else {
            result.addObj2Map("value", v);
        }
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "update/{key}/{value}", method = RequestMethod.GET)
    public ResultInfo update(HttpServletRequest request, @PathVariable("key") String key, @PathVariable("value") String value){
        ResultInfo result = new ResultInfo();
        ValueStruc v =  DataObserver.getInstance().update(key, value);
        if(v == null){
            result.setStateId(-1);
            result.setErrorMsg("    ");
        } else {
            result.addObj2Map("value", v);
        }
        return result;
    }

    @ResponseBody
    @RequestMapping(value="remove/{key}", method = RequestMethod.GET)
    public ResultInfo clear(HttpServletRequest request, @PathVariable("key") String key){
        ResultInfo result = new ResultInfo();
        ValueStruc v = DataObserver.getInstance().remove(key);
        result.addObj2Map("value", v);
        return result;
    }

    @ResponseBody
    @RequestMapping(value = "clear", method = RequestMethod.GET)
    public void clear(){
        DataObserver.getInstance().clear();
    }

}

フロントエンドjs実装
インタフェースを介してサーバを呼び出してpingコマンドを実行し、pingをリスニングした結果を例にとると、jsコードは次のようになります(以下、AngularJsと組み合わせて、他のスクリプトも同様です).
ステップ1:非同期サービスを呼び出し、リスニングIDを取得する
約束により、非同期タスクの開始が呼び出された後に登録されたリスニングIDが返される.
//    
this.ping = function($scope){
        var url = ctx + 'godmode/ping';
        var data = {
            ip : $scope.pingIP
        };
        $.ajax({
            type:"post",
            url:url,
            async:false,
            data :data,
            success: function(r){
                console.log(r);
                $scope.observerID = r.map.observerID[0];
            },
            error:function(){
                $interva
            }
        });
    }

ステップ2:IDデータの傍受

    //      
    var timer = $interval(function(){
        myService.observePing($scope,$interval);
    },1000);

    //    
    this.observePing = function($scope,$interval){
        console.log('observing:'+$scope.observerID);
        $.ajax({
                type : "get",
                url: ctx + "api/observer/observe/"+$scope.observerID,
                dataType: "json",
                async: true,
                timeout: 10000,
                error: function(r) {
                    console.log('canceling observer');
                    $interval.cancel(timer);
                },
                success: function(r) {
                    if (r.stateId == 0) {
                        var text = "";
                        $.each(r.map.value[0], function(index, item) {
                            text = text + item + "
"
; }); $scope.pingResults = text; } else { // , interval console.log('canceling observer'); $interval.cancel(timer); } } }); }