網(wǎng)絡(luò)請求異常攔截優(yōu)化

目錄介紹

  • 01.網(wǎng)絡(luò)請求異常分類
  • 02.開發(fā)中注意問題
  • 03.原始的處理方式
  • 04.如何減少代碼耦合性
  • 05.異常統(tǒng)一處理步驟
  • 06.完成版代碼展示

給自己相個親

好消息

  • 博客筆記大匯總【16年3月到至今】耿战,包括Java基礎(chǔ)及深入知識點(diǎn)篡帕,Android技術(shù)博客漫仆,Python學(xué)習(xí)筆記等等褂萧,還包括平時開發(fā)中遇到的bug匯總,當(dāng)然也在工作之余收集了大量的面試題模暗,長期更新維護(hù)并且修正,持續(xù)完善……開源的文件是markdown格式的刮便!同時也開源了生活博客褪秀,從12年起蓄诽,積累共計N篇[近100萬字,陸續(xù)搬到網(wǎng)上]媒吗,轉(zhuǎn)載請注明出處仑氛,謝謝!
  • 鏈接地址:https://github.com/yangchong211/YCBlogs
  • 如果覺得好闸英,可以star一下锯岖,謝謝!當(dāng)然也歡迎提出建議自阱,萬事起于忽微嚎莉,量變引起質(zhì)變!

01.網(wǎng)絡(luò)請求異常分類

  • 網(wǎng)絡(luò)請求異常大概有哪些沛豌?
    • 第一種:訪問接口異常,比如404赃额,500等異常加派,出現(xiàn)這類異常,Retrofit會自動拋出異常跳芳。
    • 第二種:解析數(shù)據(jù)異常芍锦,數(shù)據(jù)體發(fā)生變化可能會導(dǎo)致這個問題。
    • 第三種:其他類型異常飞盆,比如服務(wù)器響應(yīng)超時異常娄琉,鏈接失敗異常,網(wǎng)絡(luò)未連接異常等等吓歇。
    • 第四種:網(wǎng)絡(luò)請求成功孽水,但是服務(wù)器定義了異常狀態(tài),比如token失效城看,參數(shù)傳遞錯誤女气,或者統(tǒng)一給提示(這個地方比較拗口,比如購物app测柠,你購買n件商品請求接口成功炼鞠,code為200,但是服務(wù)器發(fā)現(xiàn)沒有這么多商品轰胁,這個時候就會給你一個提示谒主,然后客戶端拿到這個進(jìn)行吐司)

02.開發(fā)中注意問題

  • 在獲取數(shù)據(jù)的流程中,訪問接口和解析數(shù)據(jù)時都有可能會出錯赃阀,我們可以通過攔截器在這兩層攔截錯誤霎肯。
    • 1.在訪問接口時,我們不用設(shè)置攔截器,因為一旦出現(xiàn)錯誤姿现,Retrofit會自動拋出異常肠仪。比如,常見請求異常404备典,500异旧,503等等。為了方便后期排查問題提佣,這個可以在debug環(huán)境下打印日志就可以油狂。
    • 2.在解析數(shù)據(jù)時貌虾,我們設(shè)置一個攔截器,判斷Result里面的code是否為成功,如果不成功亿笤,則要根據(jù)與服務(wù)器約定好的錯誤碼來拋出對應(yīng)的異常。比如嫁乘,token失效后跳轉(zhuǎn)登錄頁面杯瞻,禁用同賬號登陸多臺設(shè)備,缺少參數(shù)端圈,參數(shù)傳遞異常等等焦读。
    • 3.除此以外,為了我們要盡量避免在View層對錯誤進(jìn)行判斷舱权,處理矗晃,我們必須還要設(shè)置一個攔截器,攔截onError事件宴倍,然后使用ExceptionUtils张症,讓其根據(jù)錯誤類型來分別處理。

03.原始的處理方式

  • 最簡單的處理方式鸵贬,直接對返回的throwable進(jìn)行類型判斷處理
    //請求俗他,對throwable進(jìn)行判斷
    ServiceHelper.getInstance()
          .getModelResult(param1, param2)
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .subscribe(new Subscriber<Model>() {
                 @Override
                  public void onCompleted() {
                  
                  }
    
                  @Override
                  public void onError(Throwable e) {
                      if(e instanceof HttpException){
                          //獲取對應(yīng)statusCode和Message
                          HttpException exception = (HttpException)e;
                          String message = exception.response().message();
                          int code = exception.response().code();
                      }else if(e instanceof SSLHandshakeException){
                        //接下來就是各種異常類型判斷...
                      }else if(e instanceof ...){
    
                      }...
                  }
    
                  @Override
                  public void onNext(Model model) {
                      if(model.getCode != CODE_SUCCESS){
                            int code = model.getCode();
                            switch (code){
                                case CODE_TOKEN_INVALID:
                                    ex.setDisplayMessage("重新登陸");
                                    break;
                                case CODE_NO_OTHER:
                                    ex.setDisplayMessage("其他情況");
                                    break;
                                case CODE_SHOW_TOAST:
                                    ex.setDisplayMessage("吐司服務(wù)器返回的提示");
                                    break;
                                case CODE_NO_MISSING_PARAMETER:
                                    ex.setDisplayMessage("缺少參數(shù),用log記錄服務(wù)器提示");
                                    break;
                                default:
                                    ex.setDisplayMessage(message);
                                    break;
                            }
                      }else{
                          //正常處理邏輯
                      }
                  }
          });
    
    

04.如何減少代碼耦合性

  • 為了不改變以前的代碼結(jié)構(gòu)恭理,那么如何做才能夠徹底解耦呢拯辙?一般情況下使用Retrofit網(wǎng)絡(luò)請求框架,會有回調(diào)方法颜价,如下所示:
    package retrofit2;
    
    public interface Callback<T> {
        void onResponse(Call<T> var1, Response<T> var2);
    
        void onFailure(Call<T> var1, Throwable var2);
    }
    
  • 不管以前代碼封裝與否涯保,都希望一句代碼即可實現(xiàn)網(wǎng)絡(luò)請求攔截處理邏輯。那么這個時候周伦,我是怎么處理的呢夕春?
    public class ResponseData<T> {
    
        private int code;
        private String message;
        private T t;
    
        public int getCode() {
            return code;
        }
    
        public String getMessage() {
            return message;
        }
    
        public T getT() {
            return t;
        }
    }
    
    new Callback<ResponseData<HomeBlogEntity>>(){
        @Override
        public void onResponse(Call<ResponseData<HomeBlogEntity>> call,
                               Response<ResponseData<HomeBlogEntity>> response) {
            int code = response.body().getCode();
            String message = response.body().getMessage();
            HomeBlogEntity t = response.body().getT();
            if (code!= CODE_SUCCESS){
                //網(wǎng)絡(luò)請求成功200,不過業(yè)務(wù)層執(zhí)行服務(wù)端制定的異常邏輯
                ExceptionUtils.serviceException(code,message);
            } else {
                //網(wǎng)絡(luò)請求成功专挪,業(yè)務(wù)邏輯正常處理
            }
        }
    
        @Override
        public void onFailure(Call call, Throwable throwable) {
            ExceptionUtils.handleException(throwable);
        }
    };
    

05.異常統(tǒng)一處理步驟

  • 第一步:定義請求接口網(wǎng)絡(luò)層失敗的狀態(tài)碼
    /**
     * 對應(yīng)HTTP的狀態(tài)碼
     */
    private static final int BAD_REQUEST = 400;
    private static final int UNAUTHORIZED = 401;
    private static final int FORBIDDEN = 403;
    private static final int NOT_FOUND = 404;
    private static final int METHOD_NOT_ALLOWED = 405;
    private static final int REQUEST_TIMEOUT = 408;
    private static final int CONFLICT = 409;
    private static final int PRECONDITION_FAILED = 412;
    private static final int INTERNAL_SERVER_ERROR = 500;
    private static final int BAD_GATEWAY = 502;
    private static final int SERVICE_UNAVAILABLE = 503;
    private static final int GATEWAY_TIMEOUT = 504;
    
  • 第二步及志,接口請求成功片排,業(yè)務(wù)層失敗,服務(wù)端定義異常狀態(tài)碼
    • 比如速侈,登錄過期率寡,提醒用戶重新登錄;
    • 比如倚搬,添加商品冶共,但是服務(wù)端發(fā)現(xiàn)庫存不足,這個時候接口請求成功每界,服務(wù)端定義業(yè)務(wù)層失敗捅僵,服務(wù)端給出提示語,客戶端進(jìn)行吐司
    • 比如眨层,請求接口庙楚,參數(shù)異常或者類型錯誤趴樱,請求code為200成功狀態(tài)馒闷,不過給出提示,這個時候客戶端用log打印服務(wù)端給出的提示語叁征,方便快遞查找問題
    • 比如窜司,其他情況,接口請求成功航揉,但是服務(wù)端定義業(yè)務(wù)層需要吐司服務(wù)端返回的對應(yīng)提示語
    /**
     * 服務(wù)器定義的狀態(tài)嗎
     * 比如:登錄過期,提醒用戶重新登錄金刁;
     *      添加商品帅涂,但是服務(wù)端發(fā)現(xiàn)庫存不足,這個時候接口請求成功尤蛮,服務(wù)端定義業(yè)務(wù)層失敗媳友,服務(wù)端給出提示語,客戶端進(jìn)行吐司
     *      請求接口产捞,參數(shù)異炒济或者類型錯誤,請求code為200成功狀態(tài)坯临,不過給出提示焊唬,這個時候客戶端用log打印服務(wù)端給出的提示語,方便快遞查找問題
     *      其他情況看靠,接口請求成功赶促,但是服務(wù)端定義業(yè)務(wù)層需要吐司服務(wù)端返回的對應(yīng)提示語
     */
    /**
     * 完全成功
     */
    private static final int CODE_SUCCESS = 0;
    /**
     * Token 失效
     */
    public static final int CODE_TOKEN_INVALID = 401;
    /**
     * 缺少參數(shù)
     */
    public static final int CODE_NO_MISSING_PARAMETER = 400400;
    /**
     * 其他情況
     */
    public static final int CODE_NO_OTHER = 403;
    /**
     * 統(tǒng)一提示
     */
    public static final int CODE_SHOW_TOAST = 400000;
    
  • 第三步,自定義Http層的異常和服務(wù)器定義的異常類
    public class HttpException extends Exception {
    
        private int code;
        private String displayMessage;
    
        public HttpException(Throwable throwable, int code) {
            super(throwable);
            this.code = code;
        }
    
        public void setDisplayMessage(String displayMessage) {
            this.displayMessage = displayMessage;
        }
    
        public String getDisplayMessage() {
            return displayMessage;
        }
    
        public int getCode() {
            return code;
        }
    }
    
    public class ServerException extends RuntimeException {
    
        public int code;
        public String message;
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        @Override
        public String getMessage() {
            return message;
        }
    
        public void setMessage(String message) {
            this.message = message;
        }
    }
    
  • 第四步挟炬,統(tǒng)一處理異常邏輯如下所示
    /**
     * 這個可以處理服務(wù)器請求成功鸥滨,但是業(yè)務(wù)邏輯失敗嗦哆,比如token失效需要重新登陸
     * @param code                  自定義的code碼
     */
    public static void serviceException(int code , String content){
        if (code != CODE_SUCCESS){
            ServerException serverException = new ServerException();
            serverException.setCode(code);
            serverException.setMessage(content);
            handleException(serverException);
        }
    }
    
    /**
     * 這個是處理網(wǎng)絡(luò)異常,也可以處理業(yè)務(wù)中的異常
     * @param e                     e異常
     */
    public static void handleException(Throwable e){
        HttpException ex;
        //HTTP錯誤   網(wǎng)絡(luò)請求異常 比如常見404 500之類的等
        if (e instanceof retrofit2.HttpException){
            retrofit2.HttpException httpException = (retrofit2.HttpException) e;
            ex = new HttpException(e, ErrorCode.HTTP_ERROR);
            switch(httpException.code()){
                case BAD_REQUEST:
                case UNAUTHORIZED:
                case FORBIDDEN:
                case NOT_FOUND:
                case METHOD_NOT_ALLOWED:
                case REQUEST_TIMEOUT:
                case CONFLICT:
                case PRECONDITION_FAILED:
                case GATEWAY_TIMEOUT:
                case INTERNAL_SERVER_ERROR:
                case BAD_GATEWAY:
                case SERVICE_UNAVAILABLE:
                    //均視為網(wǎng)絡(luò)錯誤
                default:
                    ex.setDisplayMessage("網(wǎng)絡(luò)錯誤"+httpException.code());
                    break;
            }
        } else if (e instanceof ServerException){
            //服務(wù)器返回的錯誤
            ServerException resultException = (ServerException) e;
            int code = resultException.getCode();
            String message = resultException.getMessage();
            ex = new HttpException(resultException, ErrorCode.SERVER_ERROR);
            switch (code){
                case CODE_TOKEN_INVALID:
                    ex.setDisplayMessage("token失效");
                    //下面這里可以統(tǒng)一處理跳轉(zhuǎn)登錄頁面的操作邏輯
                    break;
                case CODE_NO_OTHER:
                    ex.setDisplayMessage("其他情況");
                    break;
                case CODE_SHOW_TOAST:
                    ex.setDisplayMessage("吐司");
                    break;
                case CODE_NO_MISSING_PARAMETER:
                    ex.setDisplayMessage("缺少參數(shù)");
                    break;
                default:
                    ex.setDisplayMessage(message);
                    break;
            }
        } else if (e instanceof JsonParseException
                || e instanceof JSONException
                || e instanceof ParseException){
            ex = new HttpException(e, ErrorCode.PARSE_ERROR);
            //均視為解析錯誤
            ex.setDisplayMessage("解析錯誤");
        }else if(e instanceof ConnectException){
            ex = new HttpException(e, ErrorCode.NETWORK_ERROR);
            //均視為網(wǎng)絡(luò)錯誤
            ex.setDisplayMessage("連接失敗");
        } else if(e instanceof java.net.UnknownHostException){
            ex = new HttpException(e, ErrorCode.NETWORK_ERROR);
            //網(wǎng)絡(luò)未連接
            ex.setDisplayMessage("網(wǎng)絡(luò)未連接");
        } else if (e instanceof SocketTimeoutException) {
            ex = new HttpException(e, ErrorCode.NETWORK_ERROR);
            //網(wǎng)絡(luò)未連接
            ex.setDisplayMessage("服務(wù)器響應(yīng)超時");
        }  else {
            ex = new HttpException(e, ErrorCode.UNKNOWN);
            //未知錯誤
            ex.setDisplayMessage("未知錯誤");
        }
        String displayMessage = ex.getDisplayMessage();
        //這里直接吐司日志異常內(nèi)容婿滓,注意正式項目中一定要注意吐司合適的內(nèi)容
        ToastUtils.showRoundRectToast(displayMessage);
    }
    
  • 第五步老速,如何調(diào)用
    @Override
    public void onError(Throwable e) {
        //直接調(diào)用即可
        ExceptionUtils.handleException(e);
    }
    

06.完成版代碼展示

  • 如下所示
    public class ExceptionUtils {
    
        /*
         * 在使用Retrofit+RxJava時,我們訪問接口凸主,獲取數(shù)據(jù)的流程一般是這樣的:訂閱->訪問接口->解析數(shù)據(jù)->展示橘券。
         * 如上所說,異常和錯誤本質(zhì)是一樣的秕铛,因此我們要盡量避免在View層對錯誤進(jìn)行判斷约郁,處理。
         *
         * 在獲取數(shù)據(jù)的流程中但两,訪問接口和解析數(shù)據(jù)時都有可能會出錯鬓梅,我們可以通過攔截器在這兩層攔截錯誤。
         * 1.在訪問接口時谨湘,我們不用設(shè)置攔截器绽快,因為一旦出現(xiàn)錯誤,Retrofit會自動拋出異常紧阔。
         * 2.在解析數(shù)據(jù)時坊罢,我們設(shè)置一個攔截器,判斷Result里面的code是否為成功擅耽,如果不成功活孩,則要根據(jù)與服務(wù)器約定好的錯誤碼來拋出對應(yīng)的異常。
         * 3.除此以外乖仇,為了我們要盡量避免在View層對錯誤進(jìn)行判斷憾儒,處理,我們必須還要設(shè)置一個攔截器乃沙,攔截onError事件起趾,然后使用ExceptionHandler,讓其根據(jù)錯誤類型來分別處理警儒。
         */
    
    
    
        /**
         * 對應(yīng)HTTP的狀態(tài)碼
         */
        private static final int BAD_REQUEST = 400;
        private static final int UNAUTHORIZED = 401;
        private static final int FORBIDDEN = 403;
        private static final int NOT_FOUND = 404;
        private static final int METHOD_NOT_ALLOWED = 405;
        private static final int REQUEST_TIMEOUT = 408;
        private static final int CONFLICT = 409;
        private static final int PRECONDITION_FAILED = 412;
        private static final int INTERNAL_SERVER_ERROR = 500;
        private static final int BAD_GATEWAY = 502;
        private static final int SERVICE_UNAVAILABLE = 503;
        private static final int GATEWAY_TIMEOUT = 504;
    
        /**
         * 服務(wù)器定義的狀態(tài)嗎
         * 比如:登錄過期训裆,提醒用戶重新登錄;
         *      添加商品蜀铲,但是服務(wù)端發(fā)現(xiàn)庫存不足边琉,這個時候接口請求成功,服務(wù)端定義業(yè)務(wù)層失敗蝙茶,服務(wù)端給出提示語艺骂,客戶端進(jìn)行吐司
         *      請求接口,參數(shù)異陈『唬或者類型錯誤钳恕,請求code為200成功狀態(tài)别伏,不過給出提示,這個時候客戶端用log打印服務(wù)端給出的提示語忧额,方便快遞查找問題
         *      其他情況厘肮,接口請求成功,但是服務(wù)端定義業(yè)務(wù)層需要吐司服務(wù)端返回的對應(yīng)提示語
         */
        /**
         * 完全成功
         */
        private static final int CODE_SUCCESS = 0;
        /**
         * Token 失效
         */
        public static final int CODE_TOKEN_INVALID = 401;
        /**
         * 缺少參數(shù)
         */
        public static final int CODE_NO_MISSING_PARAMETER = 400400;
        /**
         * 其他情況
         */
        public static final int CODE_NO_OTHER = 403;
        /**
         * 統(tǒng)一提示
         */
        public static final int CODE_SHOW_TOAST = 400000;
    
    
    
        /**
         * 這個可以處理服務(wù)器請求成功睦番,但是業(yè)務(wù)邏輯失敗类茂,比如token失效需要重新登陸
         * @param code                  自定義的code碼
         */
        public static void serviceException(int code , String content){
            if (code != CODE_SUCCESS){
                ServerException serverException = new ServerException();
                serverException.setCode(code);
                serverException.setMessage(content);
                handleException(serverException);
            }
        }
    
        /**
         * 這個是處理網(wǎng)絡(luò)異常,也可以處理業(yè)務(wù)中的異常
         * @param e                     e異常
         */
        public static void handleException(Throwable e){
            HttpException ex;
            //HTTP錯誤   網(wǎng)絡(luò)請求異常 比如常見404 500之類的等
            if (e instanceof retrofit2.HttpException){
                retrofit2.HttpException httpException = (retrofit2.HttpException) e;
                ex = new HttpException(e, ErrorCode.HTTP_ERROR);
                switch(httpException.code()){
                    case BAD_REQUEST:
                    case UNAUTHORIZED:
                    case FORBIDDEN:
                    case NOT_FOUND:
                    case METHOD_NOT_ALLOWED:
                    case REQUEST_TIMEOUT:
                    case CONFLICT:
                    case PRECONDITION_FAILED:
                    case GATEWAY_TIMEOUT:
                    case INTERNAL_SERVER_ERROR:
                    case BAD_GATEWAY:
                    case SERVICE_UNAVAILABLE:
                        //均視為網(wǎng)絡(luò)錯誤
                    default:
                        ex.setDisplayMessage("網(wǎng)絡(luò)錯誤"+httpException.code());
                        break;
                }
            } else if (e instanceof ServerException){
                //服務(wù)器返回的錯誤
                ServerException resultException = (ServerException) e;
                int code = resultException.getCode();
                String message = resultException.getMessage();
                ex = new HttpException(resultException, ErrorCode.SERVER_ERROR);
                switch (code){
                    case CODE_TOKEN_INVALID:
                        ex.setDisplayMessage("重新登陸");
                        break;
                    case CODE_NO_OTHER:
                        ex.setDisplayMessage("其他情況");
                        break;
                    case CODE_SHOW_TOAST:
                        ex.setDisplayMessage("吐司");
                        break;
                    case CODE_NO_MISSING_PARAMETER:
                        ex.setDisplayMessage("缺少參數(shù)");
                        break;
                    default:
                        ex.setDisplayMessage(message);
                        break;
                }
            } else if (e instanceof JsonParseException
                    || e instanceof JSONException
                    || e instanceof ParseException){
                ex = new HttpException(e, ErrorCode.PARSE_ERROR);
                //均視為解析錯誤
                ex.setDisplayMessage("解析錯誤");
            }else if(e instanceof ConnectException){
                ex = new HttpException(e, ErrorCode.NETWORK_ERROR);
                //均視為網(wǎng)絡(luò)錯誤
                ex.setDisplayMessage("連接失敗");
            } else if(e instanceof java.net.UnknownHostException){
                ex = new HttpException(e, ErrorCode.NETWORK_ERROR);
                //網(wǎng)絡(luò)未連接
                ex.setDisplayMessage("網(wǎng)絡(luò)未連接");
            } else if (e instanceof SocketTimeoutException) {
                ex = new HttpException(e, ErrorCode.NETWORK_ERROR);
                //網(wǎng)絡(luò)未連接
                ex.setDisplayMessage("服務(wù)器響應(yīng)超時");
            }  else {
                ex = new HttpException(e, ErrorCode.UNKNOWN);
                //未知錯誤
                ex.setDisplayMessage("未知錯誤");
            }
            String displayMessage = ex.getDisplayMessage();
            //這里直接吐司日志異常內(nèi)容托嚣,注意正式項目中一定要注意吐司合適的內(nèi)容
            ToastUtils.showRoundRectToast(displayMessage);
        }
    }
    

其他介紹

01.關(guān)于博客匯總鏈接

02.關(guān)于我的博客

開源代碼案例:https://github.com/yangchong211/LifeHelper

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巩检,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子示启,更是在濱河造成了極大的恐慌兢哭,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,607評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夫嗓,死亡現(xiàn)場離奇詭異迟螺,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)舍咖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評論 3 395
  • 文/潘曉璐 我一進(jìn)店門矩父,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人排霉,你說我怎么就攤上這事窍株。” “怎么了攻柠?”我有些...
    開封第一講書人閱讀 164,960評論 0 355
  • 文/不壞的土叔 我叫張陵夹姥,是天一觀的道長。 經(jīng)常有香客問我辙诞,道長,這世上最難降的妖魔是什么轻抱? 我笑而不...
    開封第一講書人閱讀 58,750評論 1 294
  • 正文 為了忘掉前任飞涂,我火速辦了婚禮,結(jié)果婚禮上祈搜,老公的妹妹穿的比我還像新娘较店。我一直安慰自己,他們只是感情好容燕,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評論 6 392
  • 文/花漫 我一把揭開白布梁呈。 她就那樣靜靜地躺著,像睡著了一般蘸秘。 火紅的嫁衣襯著肌膚如雪官卡。 梳的紋絲不亂的頭發(fā)上蝗茁,一...
    開封第一講書人閱讀 51,604評論 1 305
  • 那天,我揣著相機(jī)與錄音寻咒,去河邊找鬼哮翘。 笑死,一個胖子當(dāng)著我的面吹牛毛秘,可吹牛的內(nèi)容都是我干的饭寺。 我是一名探鬼主播,決...
    沈念sama閱讀 40,347評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼叫挟,長吁一口氣:“原來是場噩夢啊……” “哼艰匙!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起抹恳,我...
    開封第一講書人閱讀 39,253評論 0 276
  • 序言:老撾萬榮一對情侶失蹤员凝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后适秩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绊序,經(jīng)...
    沈念sama閱讀 45,702評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評論 3 336
  • 正文 我和宋清朗相戀三年秽荞,在試婚紗的時候發(fā)現(xiàn)自己被綠了骤公。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡扬跋,死狀恐怖阶捆,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情钦听,我是刑警寧澤洒试,帶...
    沈念sama閱讀 35,734評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站朴上,受9級特大地震影響垒棋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜痪宰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評論 3 330
  • 文/蒙蒙 一叼架、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧衣撬,春花似錦乖订、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至扛点,卻和暖如春哥遮,著一層夾襖步出監(jiān)牢的瞬間岂丘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評論 1 270
  • 我被黑心中介騙來泰國打工昔善, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留元潘,地道東北人。 一個月前我還...
    沈念sama閱讀 48,216評論 3 371
  • 正文 我出身青樓君仆,卻偏偏與公主長得像翩概,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子返咱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評論 2 355

推薦閱讀更多精彩內(nèi)容