iOS 封裝AFNetworking

1.請求配置類

//
//  SFRequestConfig.h
//  template
//
//  Created by shefeng on 2024/6/20.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface SFRequestConfig : NSObject

/**
 *  是否允許無效的證書
 */
@property (assign, nonatomic) BOOL allowInvalidCertificates;

/**
 *  超時時間
 */
@property (assign, nonatomic) NSInteger timeoutInterval;

/**
 *  是否允許無效的證書
 */
@property (assign, nonatomic) BOOL validatesDomainName;

/**
 *  可接收的ContentType類型
 */
@property (strong, nonatomic) NSSet <NSString *> *acceptableContentTypes;


/**
 *  單例
 */
+ (instancetype)sharedConfig;

@end

NS_ASSUME_NONNULL_END

//
//  SFRequestConfig.m
//  template
//
//  Created by shefeng on 2024/6/20.
//

#import "SFRequestConfig.h"

@implementation SFRequestConfig

+ (instancetype)sharedConfig{
    static dispatch_once_t onceToken;
    static SFRequestConfig *instance;
    dispatch_once(&onceToken, ^{
        instance = [[SFRequestConfig alloc] init];
    });
    return instance;
}

- (NSSet<NSString *> *)acceptableContentTypes{
    if (_acceptableContentTypes == nil) {
        _acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"image/jpeg",@"image/png",@"text/plain",@"application/json",nil];
    }
    return _acceptableContentTypes;
}

@end

2.響應配置類

//
//  SFResponseConfig.h
//  template
//
//  Created by shefeng on 2024/6/24.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface SFResponseConfig : NSObject

/**
 *  code的key
 */
@property (strong, nonatomic) NSString *codeKey;

/**
 *  data的key
 */
@property (strong, nonatomic) NSString *dataKey;

/**
 *  message的key
 */
@property (strong, nonatomic) NSString *messageKey;

/**
 *  成功的狀態(tài)碼
 */
@property (strong, nonatomic) NSNumber *successedCode;

/**
 *  失敗的狀態(tài)碼
 */
@property (strong, nonatomic) NSNumber *failedCode;

/**
 *  默認的錯誤提示語
 */
@property (strong, nonatomic) NSString *defaultMessageValue;

/**
 *  單例
 */
+ (instancetype)sharedConfig;

@end

NS_ASSUME_NONNULL_END

//
//  SFResponseConfig.m
//  template
//
//  Created by shefeng on 2024/6/24.
//

#import "SFResponseConfig.h"

#define ResponseCodeDefaultKey @"code"
#define ResponseDataDefaultKey @"data"
#define ResponseMessageDefaultKey @"message"
#define ResponseCodeSuccessedDefaultValue @0
#define ResponseCodeFailedDefaultValue @500
#define ResponseMessageDefaultValue @"請求失敗"

@implementation SFResponseConfig

+ (instancetype)sharedConfig{
    static dispatch_once_t onceToken;
    static SFResponseConfig *instance;
    dispatch_once(&onceToken, ^{
        instance = [[SFResponseConfig alloc] init];
    });
    return instance;
}

- (NSString *)codeKey{
    if (_codeKey == nil || [@"" isEqualToString:_codeKey]) {
        return ResponseCodeDefaultKey;
    }
    return _codeKey;
}

- (NSString *)dataKey{
    if (_dataKey == nil || [@"" isEqualToString:_dataKey]) {
        return ResponseDataDefaultKey;
    }
    return _dataKey;
}

- (NSString *)messageKey{
    if (_messageKey == nil || [@"" isEqualToString:_messageKey]) {
        return ResponseMessageDefaultKey;
    }
    return _messageKey;
}

- (NSNumber *)successedCode{
    if (_successedCode == nil) {
        return ResponseCodeSuccessedDefaultValue;
    }
    return _successedCode;
}

- (NSNumber *)failedCode{
    if (_failedCode == nil) {
        return ResponseCodeFailedDefaultValue;
    }
    return _failedCode;
}

- (NSString *)defaultMessageValue{
    if (_defaultMessageValue == nil || [@"" isEqualToString:_defaultMessageValue]) {
        return ResponseMessageDefaultValue;
    }
    return _defaultMessageValue;
}

@end

3.網(wǎng)絡請求基類

//
//  SFBaseRequest.h
//  template
//
//  Created by shefeng on 2024/6/20.
//

#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_ENUM(NSInteger, SFContentType){
    ApplicationJson,
    ApplicationXWwwFormUrlencoded,
    MultipartFormData 
};

@interface SFBaseRequest : NSObject

+ (AFHTTPSessionManager *)sharedManager;

/**
 *  GET請求
 *
 *  @param urlString 請求url
 *  @param params 請求參數(shù)
 *  @param headers header參數(shù)
 *  @param completionBlock 完成的block
 */
+ (void)GET:(NSString *)urlString params:(NSDictionary *)params headers:(NSDictionary *)headers completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock;

/**
 *  POST請求
 *
 *  @param urlString 請求url
 *  @param params 請求參數(shù)
 *  @param headers header參數(shù)
 *  @param completionBlock 完成的block
 */
+ (void)POST:(NSString *)urlString params:(NSDictionary *)params headers:(NSDictionary *)headers completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock;

/**
 *  POST請求
 *
 *  @param urlString 請求url
 *  @param params 請求參數(shù)
 *  @param headers header參數(shù)  
 *  @param contentType 請求Content-Type
 *  @param completionBlock 完成的block
 */
+ (void)POST:(NSString *)urlString params:(NSDictionary *)params headers:(NSDictionary *)headers contentType:(SFContentType)contentType completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock;

@end

NS_ASSUME_NONNULL_END
//
//  SFBaseRequest.m
//  template
//
//  Created by shefeng on 2024/6/20.
//

#import "SFBaseRequest.h"
#import <MJExtension/MJExtension.h>
#import "SFRequestConfig.h"
#import "SFResponseConfig.h"

#define ResponseFailedDefaultValue @{[SFResponseConfig sharedConfig].codeKey:[SFResponseConfig sharedConfig].failedCode,[SFResponseConfig sharedConfig].messageKey:[SFResponseConfig sharedConfig].defaultMessageValue}

@implementation SFBaseRequest

+ (AFHTTPSessionManager *)sharedManager {
    static AFHTTPSessionManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [AFHTTPSessionManager manager];
        
        AFSecurityPolicy *securityPolicy = [AFSecurityPolicy defaultPolicy];
        // 客戶端是否信任非法證書
        securityPolicy.allowInvalidCertificates = [SFRequestConfig sharedConfig].allowInvalidCertificates;
        // 是否在證書域字段中驗證域名
        securityPolicy.validatesDomainName = [SFRequestConfig sharedConfig].validatesDomainName;
        instance.securityPolicy = securityPolicy;
        instance.requestSerializer.timeoutInterval = [SFRequestConfig sharedConfig].timeoutInterval;
        instance.responseSerializer.acceptableContentTypes = [SFRequestConfig sharedConfig].acceptableContentTypes;
    });
    return instance;
}

/**
 *  GET請求
 *
 *  @param urlString 請求url
 *  @param params 請求參數(shù)
 *  @param headers header參數(shù)
 *  @param completionBlock 完成的block
 */
+ (void)GET:(NSString *)urlString params:(NSDictionary *)params headers:(NSDictionary *)headers completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock{
    [[SFBaseRequest sharedManager] GET:urlString parameters:params headers:headers progress:^(NSProgress * _Nonnull downloadProgress) {
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        [self handleSuccess:urlString params:params responseObject:responseObject completionBlock:completionBlock];
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [self handleError:urlString params:params errMsg:error.localizedDescription completionBlock:completionBlock];
    }];
}

/**
 *  POST請求
 *
 *  @param urlString 請求url
 *  @param params 請求參數(shù)
 *  @param headers header參數(shù)
 *  @param completionBlock 完成的block
 */
+ (void)POST:(NSString *)urlString params:(NSDictionary *)params headers:(NSDictionary *)headers completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock{
    [self POST:urlString params:params headers:headers contentType:ApplicationXWwwFormUrlencoded completionBlock:completionBlock];
}

/**
 *  POST請求
 *
 *  @param urlString 請求url
 *  @param params 請求參數(shù)
 *  @param headers header參數(shù)
 *  @param contentType 請求Content-Type
 *  @param completionBlock 完成的block
 */
+ (void)POST:(NSString *)urlString params:(NSDictionary *)params headers:(NSDictionary *)headers contentType:(SFContentType)contentType completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock{
    if (contentType == ApplicationXWwwFormUrlencoded) {
        [[self sharedManager].requestSerializer setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        
        [[SFBaseRequest sharedManager] POST:urlString parameters:params headers:headers progress:^(NSProgress * _Nonnull uploadProgress) {
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            [self handleSuccess:urlString params:params responseObject:responseObject completionBlock:completionBlock];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            [self handleError:urlString params:params errMsg:error.localizedDescription completionBlock:completionBlock];
        }];
    }else if (contentType == ApplicationJson) {
        [[self sharedManager].requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        
        NSMutableURLRequest *request = [[AFJSONRequestSerializer serializer] requestWithMethod:@"POST" URLString:urlString parameters:params error:nil];

        [request setValue:@"application/json"forHTTPHeaderField:@"Content-Type"];
        
        if(headers != nil && headers.allKeys.count != 0){
            for (NSString *key in headers.allKeys) {
                NSString *value = [headers objectForKey:key];
                [request addValue:value forHTTPHeaderField:key];
            }
        }

        NSData *body = [NSJSONSerialization dataWithJSONObject:params options:NSJSONWritingPrettyPrinted error:nil];

        [request setHTTPBody:body];
        
        [[[SFBaseRequest sharedManager] dataTaskWithRequest:request uploadProgress:^(NSProgress * _Nonnull uploadProgress) {
                    
        } downloadProgress:^(NSProgress * _Nonnull downloadProgress) {
            
        } completionHandler:^(NSURLResponse * _Nonnull response, id  _Nullable responseObject, NSError * _Nullable error) {
            if (!error) {
                [self handleSuccess:urlString params:params responseObject:responseObject completionBlock:completionBlock];
            }else{
                [self handleError:urlString params:params errMsg:error.localizedDescription completionBlock:completionBlock];
            }
        }] resume];
    }else if (contentType == MultipartFormData) {
        [[self sharedManager].requestSerializer setValue:@"multipart/form-data" forHTTPHeaderField:@"Content-Type"];
        
        [[SFBaseRequest sharedManager] POST:urlString parameters:params headers:headers constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            NSArray *keyArray = [params allKeys];
            
            for (NSString *key in keyArray) {
                id value = params[key];
                if ([value isKindOfClass:[NSString class]]) {
                   [formData appendPartWithFormData:[value dataUsingEncoding:NSUTF8StringEncoding] name:key];
                }else if ([value isKindOfClass:[NSMutableArray class]]) {
                    [formData appendPartWithFormData:[NSKeyedArchiver archivedDataWithRootObject:value requiringSecureCoding:YES error:nil] name:key];
                }else if ([value isKindOfClass:[NSArray class]]) {
                    [formData appendPartWithFormData:[NSKeyedArchiver archivedDataWithRootObject:value requiringSecureCoding:YES error:nil] name:key];
                }
                
            }
        } progress:^(NSProgress * _Nonnull uploadProgress) {
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            [self handleSuccess:urlString params:params responseObject:responseObject completionBlock:completionBlock];
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            [self handleError:urlString params:params errMsg:error.localizedDescription completionBlock:completionBlock];
        }];
    }
}

/**
 *  處理錯誤響應
 *
 *  @param url 請求地址
 *  @param params 請求參數(shù)
 *  @param errMsg 錯誤信息
 *  @param completionBlock 完成的Block
 */
+ (void)handleError:(NSString *)url params:(NSDictionary *)params errMsg:(NSString *)errMsg completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock{
    [self printLog:url params:params info:errMsg];
    completionBlock([SFResponseConfig sharedConfig].failedCode.integerValue,nil,errMsg);
}

#pragma mark - private
/**
 *  處理成功響應
 *
 *  @param url 請求地址
 *  @param params 請求參數(shù)
 *  @param responseObject 響應數(shù)據(jù)
 *  @param completionBlock 完成的Block
 */
+ (void)handleSuccess:(NSString *)url params:(NSDictionary *)params responseObject:(id)responseObject completionBlock:(void(^)(NSInteger code,id data,NSString *message))completionBlock{
    if(responseObject == nil){
        [self handleError:url params:params errMsg:@"請求無響應" completionBlock:completionBlock];
    }else {
        if ([responseObject isKindOfClass:[NSDictionary class]]) {
            NSDictionary *responseDict = (NSDictionary *)responseObject;
            if ([responseDict.allKeys containsObject:[SFResponseConfig sharedConfig].codeKey] 
                && [responseDict.allKeys containsObject:[SFResponseConfig sharedConfig].messageKey]
                && [responseDict.allKeys containsObject:[SFResponseConfig sharedConfig].dataKey]) {
                NSInteger code = [[responseDict objectForKey:[SFResponseConfig sharedConfig].codeKey] integerValue];
                id data = [responseDict objectForKey:[SFResponseConfig sharedConfig].dataKey];
                NSString *message = [responseDict objectForKey:[SFResponseConfig sharedConfig].messageKey];
                [self printLog:url params:params info:[responseDict mj_JSONString]];
                completionBlock(code,data,message);
            }else{
                [self handleError:url params:params errMsg:@"返回數(shù)據(jù)格式不正確" completionBlock:completionBlock];
            }
        }else{
            [self handleError:url params:params errMsg:@"返回數(shù)據(jù)格式不正確" completionBlock:completionBlock];
        }
    }
}

/**
 *  打印log
 *
 *  @param url 請求地址
 *  @param params 請求參數(shù)
 *  @param info 響應信息
 */
+ (void)printLog:(NSString *)url params:(NSDictionary *)params info:(NSString *)info{
#ifdef DEBUG
    NSString *urlInfo = [NSString stringWithFormat:@"請求地址:%@",url];
    NSString *paramInfo = [NSString stringWithFormat:@"請求參數(shù):%@",(params == nil ? @"" : [params mj_JSONString])];
    NSString *responseInfo = [NSString stringWithFormat:@"請求響應:%@",info];
    
    NSInteger maxLength = urlInfo.length;
    
    if (paramInfo.length > maxLength) {
        maxLength = paramInfo.length;
    }
    
    if (responseInfo.length > maxLength) {
        maxLength = responseInfo.length;
    }
    
    NSLog(@"%@",[self buildLogString:maxLength info:nil]);
    NSLog(@"%@",[self buildLogString:maxLength info:urlInfo]);
    NSLog(@"%@",[self buildLogString:maxLength info:paramInfo]);
    NSLog(@"%@",[self buildLogString:maxLength info:responseInfo]);
    NSLog(@"%@",[self buildLogString:maxLength info:nil]);
#endif
}

/**
 *  構建打印信息
 *
 *  @param maxLength 最大長度
 *  @param info 信息
 *
 */
+ (NSString *)buildLogString:(NSInteger)maxLength info:(NSString *)info{
    //非第一行和最后一行的左側(cè)*數(shù)量
    NSInteger leftStarLength = 0;
    //非第一行和最后一行的左側(cè)*后的空格數(shù)量
    NSInteger leftSpaceLength = 0;
    
    //實際最大長度
    maxLength += (leftStarLength + leftSpaceLength) * 2;
    
    NSMutableString *mutableStr = [[NSMutableString alloc] init];
    
    if(info == nil){
        for (int i = 0; i < maxLength; i++) {
            [mutableStr appendString:@"="];
        }
    }else{
        for (int i = 0; i < leftStarLength; i++) {
            [mutableStr appendString:@""];
        }
        
        for (int i = 0; i < leftSpaceLength; i++) {
            [mutableStr appendString:@""];
        }
        
        [mutableStr appendString:info];
        
        NSInteger rightSpaceLength = maxLength - leftStarLength - leftSpaceLength - info.length - leftStarLength;
        
        for (int i = 0; i < rightSpaceLength; i++) {
            [mutableStr appendString:@""];
        }
        
        for (int i = 0; i < leftStarLength; i++) {
            [mutableStr appendString:@""];
        }
    }
    
    return mutableStr;
}

@end

4.Java后臺相關代碼


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TestObj {

    private String name;
    private String address;
}

package com.geenju.bcard.modules.app.controller;

import com.geenju.bcard.common.api.CommonResult;
import com.geenju.bcard.modules.app.dto.TestObj;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
@RequestMapping("/api/test")
public class TestController {

    @RequestMapping(value = "/get", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult get(@RequestParam(value = "argsA") String argsA) {
        log.info("get - argsA=" + argsA);
        return CommonResult.success("");
    }

    @RequestMapping(value = "/postFormData", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult postFormData(@RequestParam(value = "argsA") String argsA) {
        log.info("postFormData - argsA=" + argsA);
        return CommonResult.success("");
    }

    @RequestMapping(value = "/postXWwwFormUrlencoded", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult postXWwwFormUrlencoded(@RequestParam(value = "argsA") String argsA) {
        log.info("postXWwwFormUrlencoded - argsA=" + argsA);
        return CommonResult.success("");
    }

    @RequestMapping(value = "/postJson", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult postJson(@RequestBody TestObj testObj) {
        log.info("postJson - testObj.name=" + testObj.getName() + " testObj.address=" + testObj.getAddress());
        return CommonResult.success("");
    }
}

5.使用

配置相關參數(shù)

[SFRequestConfig sharedConfig].timeoutInterval = 30;
[SFRequestConfig sharedConfig].allowInvalidCertificates = YES;
[SFRequestConfig sharedConfig].validatesDomainName = NO;
[SFRequestConfig sharedConfig].acceptableContentTypes = [NSSet setWithObjects:@"text/html",@"image/jpeg",@"image/png",@"text/plain",@"application/json",nil];
    
[SFResponseConfig sharedConfig].codeKey = @"code";
[SFResponseConfig sharedConfig].dataKey = @"data";
[SFResponseConfig sharedConfig].messageKey = @"msg";
[SFResponseConfig sharedConfig].successedCode = @0;
[SFResponseConfig sharedConfig].failedCode = @500;
[SFResponseConfig sharedConfig].defaultMessageValue = @"請求失敗";

調(diào)用

[self testGet:@"value of args"];
[self testPostFormData:@"value of args"];
[self testPostFormUrlencoded:@"value of args"];
[self testPostJson:@"hello" address:@"world"];

- (void)testGet:(NSString *)argsA{
    [SFBaseRequest GET:@"http://192.168.0.121:9000/api/test/get" params:@{@"argsA":argsA} headers:@{} completionBlock:^(NSInteger code, id  _Nonnull data, NSString * _Nonnull message) {
   
    }];
}

- (void)testPostFormData:(NSString *)argsA{
    [SFBaseRequest POST:@"http://192.168.0.121:9000/api/test/postFormData" params:@{@"argsA":argsA} headers:@{} completionBlock:^(NSInteger code, id  _Nonnull data, NSString * _Nonnull message) {
   
    }];
}

- (void)testPostFormUrlencoded:(NSString *)argsA{
    [SFBaseRequest POST:@"http://192.168.0.121:9000/api/test/postXWwwFormUrlencoded" params:@{@"argsA":argsA} headers:@{} contentType:ApplicationXWwwFormUrlencoded completionBlock:^(NSInteger code, id  _Nonnull data, NSString * _Nonnull message) {
 
    }];
}

- (void)testPostJson:(NSString *)name address:(NSString *)address{
    [SFBaseRequest POST:@"http://192.168.0.121:9000/api/test/postJson" params:@{@"name":name,@"address":address} headers:@{} contentType:ApplicationJson completionBlock:^(NSInteger code, id  _Nonnull data, NSString * _Nonnull message) {

    }];
}

6.調(diào)試

==============================================================
請求地址:http://192.168.0.121:9000/api/test/postXWwwFormUrlencoded
請求參數(shù):{"argsA":"value of args"}
請求響應:{"msg":"操作成功","data":"","code":200}
==============================================================
===========================================
請求地址:http://192.168.0.121:9000/api/test/get
請求參數(shù):{"argsA":"value of args"}
請求響應:{"msg":"操作成功","data":"","code":200}
===========================================
================================================
請求地址:http://192.168.0.121:9000/api/test/postJson
請求參數(shù):{"name":"hello","address":"world"}
請求響應:{"msg":"操作成功","data":"","code":200}
================================================
====================================================
請求地址:http://192.168.0.121:9000/api/test/postFormData
請求參數(shù):{"argsA":"value of args"}
請求響應:{"msg":"操作成功","data":"","code":200}
====================================================
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末炮车,一起剝皮案震驚了整個濱河市亮隙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異南窗,居然都是意外死亡,警方通過查閱死者的電腦和手機郎楼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門万伤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人呜袁,你說我怎么就攤上這事敌买。” “怎么了傅寡?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵放妈,是天一觀的道長北救。 經(jīng)常有香客問我荐操,道長芜抒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任托启,我火速辦了婚禮宅倒,結果婚禮上,老公的妹妹穿的比我還像新娘屯耸。我一直安慰自己拐迁,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布疗绣。 她就那樣靜靜地躺著线召,像睡著了一般。 火紅的嫁衣襯著肌膚如雪多矮。 梳的紋絲不亂的頭發(fā)上缓淹,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音塔逃,去河邊找鬼讯壶。 笑死,一個胖子當著我的面吹牛湾盗,可吹牛的內(nèi)容都是我干的伏蚊。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼格粪,長吁一口氣:“原來是場噩夢啊……” “哼躏吊!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起帐萎,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤比伏,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吓肋,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凳怨,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年是鬼,在試婚紗的時候發(fā)現(xiàn)自己被綠了肤舞。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡均蜜,死狀恐怖李剖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情囤耳,我是刑警寧澤篙顺,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布偶芍,位于F島的核電站,受9級特大地震影響德玫,放射性物質(zhì)發(fā)生泄漏匪蟀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一宰僧、第九天 我趴在偏房一處隱蔽的房頂上張望材彪。 院中可真熱鬧,春花似錦琴儿、人聲如沸段化。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽显熏。三九已至,卻和暖如春晒屎,著一層夾襖步出監(jiān)牢的瞬間喘蟆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工夷磕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留履肃,地道東北人。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓坐桩,卻偏偏與公主長得像尺棋,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子绵跷,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

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