SpringBoot集成redisson操作redis

一奈辰、配置

1.1 引入maven

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.17.0</version>
</dependency>

1.2 配置文件

spring.redis.database=0
spring.redis.password=
spring.redis.timeout=3000
#sentinel/cluster/single
spring.redis.mode=single
#連接池配置
spring.redis.pool.max-idle=16
spring.redis.pool.min-idle=8
spring.redis.pool.max-active=8
spring.redis.pool.max-wait=3000
spring.redis.pool.conn-timeout=3000
spring.redis.pool.so-timeout=3000
spring.redis.pool.size=10
#單機(jī)配置
spring.redis.single.address=192.168.60.23:6379
#集群配置
spring.redis.cluster.scan-interval=1000
spring.redis.cluster.nodes=
spring.redis.cluster.read-mode=SLAVE
spring.redis.cluster.retry-attempts=3
spring.redis.cluster.failed-attempts=3
spring.redis.cluster.slave-connection-pool-size=64
spring.redis.cluster.master-connection-pool-size=64
spring.redis.cluster.retry-interval=1500
#哨兵配置
spring.redis.sentinel.master=business-master
spring.redis.sentinel.nodes=
spring.redis.sentinel.master-onlyWrite=true
spring.redis.sentinel.fail-max=3

1.3 配置文件讀取

/**
 * @author: huangyibo
 * @Date: 2022/6/23 10:56
 * @Description: 配置文件讀取
 */

@ConfigurationProperties(prefix="spring.redis", ignoreUnknownFields = false)
@Data
@ToString
public class RedisProperties {

    private int database;

    /**
     * 等待節(jié)點(diǎn)回復(fù)命令的時(shí)間。該時(shí)間從命令發(fā)送成功時(shí)開始計(jì)時(shí)
     */
    private int timeout;

    private String password;

    private String mode;


    /**
     * 池配置
     */
    private RedisPoolProperties pool;


    /**
     * 單機(jī)信息配置
     */
    private RedisSingleProperties single;


    /**
     * 集群 信息配置
     */
    private RedisClusterProperties cluster;

    /**
     * 哨兵配置
     *
     */
    private RedisSentinelProperties sentinel;
}
/**
 * @author: huangyibo
 * @Date: 2022/6/23 11:00
 * @Description: redis 池配置
 */

@Data
@ToString
public class RedisPoolProperties {

    private int maxIdle;

    private int minIdle;

    private int maxActive;

    private int maxWait;

    private int connTimeout;

    private int soTimeout;

    /**
     * 池大小
     */
    private int size;

}
/**
 * @author: huangyibo
 * @Date: 2022/6/23 11:02
 * @Description: 單節(jié)點(diǎn)配置
 */

@Data
@ToString
public class RedisSingleProperties {

    private String address;
}
/**
 * @author: huangyibo
 * @Date: 2022/6/23 11:03
 * @Description: 集群配置
 */

@Data
@ToString
public class RedisClusterProperties {

    /**
     * 集群狀態(tài)掃描間隔時(shí)間钱豁,單位是毫秒
     */
    private int scanInterval;

    /**
     * 集群節(jié)點(diǎn)
     */
    private String nodes;

    /**
     * 默認(rèn)值: SLAVE(只在從服務(wù)節(jié)點(diǎn)里讀让蘧)設(shè)置讀取操作選擇節(jié)點(diǎn)的模式。 可用值為: SLAVE - 只在從服務(wù)節(jié)點(diǎn)里讀取挺益。
     * MASTER - 只在主服務(wù)節(jié)點(diǎn)里讀取歉糜。 MASTER_SLAVE - 在主從服務(wù)節(jié)點(diǎn)里都可以讀取
     */
    private String readMode;

    /**
     * (從節(jié)點(diǎn)連接池大小) 默認(rèn)值:64
     */
    private int slaveConnectionPoolSize;

    /**
     * 主節(jié)點(diǎn)連接池大型凇)默認(rèn)值:64
     */
    private int masterConnectionPoolSize;

    /**
     * (命令失敗重試次數(shù)) 默認(rèn)值:3
     */
    private int retryAttempts;

    /**
     *命令重試發(fā)送時(shí)間間隔现恼,單位:毫秒 默認(rèn)值:1500
     */
    private int retryInterval;

    /**
     * 執(zhí)行失敗最大次數(shù)默認(rèn)值:3
     */
    private int failedAttempts;
}
/**
 * @author: huangyibo
 * @Date: 2022/6/23 11:06
 * @Description: 哨兵配置
 */

@Data
@ToString
public class RedisSentinelProperties {

    /**
     * 哨兵master 名稱
     */
    private String master;

    /**
     * 哨兵節(jié)點(diǎn)
     */
    private String nodes;

    /**
     * 哨兵配置
     */
    private boolean masterOnlyWrite;

    /**
     *
     */
    private int failMax;

}

1.4 CacheConfiguration

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author: huangyibo
 * @Date: 2022/6/23 11:08
 * @Description:
 */

@Configuration
@EnableConfigurationProperties(RedisProperties.class)
public class CacheConfiguration {

    @Autowired
    private RedisProperties redisProperties;

    @Configuration
    @ConditionalOnClass({Redisson.class})
    @ConditionalOnExpression("'${spring.redis.mode}'=='single' or '${spring.redis.mode}'=='cluster' or '${spring.redis.mode}'=='sentinel'")
    protected class RedissonSingleClientConfiguration {

        /**
         * 單機(jī)模式 redisson 客戶端
         */

        @Bean
        @ConditionalOnProperty(name="spring.redis.mode", havingValue="single")
        public RedissonClient redissonSingle() {
            Config config = new Config();
            String node = redisProperties.getSingle().getAddress();
            node = node.startsWith("redis://") ? node : "redis://" + node;
            SingleServerConfig serverConfig = config.useSingleServer()
                    .setAddress(node)
                    .setTimeout(redisProperties.getPool().getConnTimeout())
                    .setConnectionPoolSize(redisProperties.getPool().getSize())
                    .setConnectionMinimumIdleSize(redisProperties.getPool().getMinIdle());
            if(!StringUtils.isEmpty(redisProperties.getPassword())) {
                serverConfig.setPassword(redisProperties.getPassword());
            }
            return Redisson.create(config);
        }

        /**
         * 集群模式的 redisson 客戶端
         *
         * @return
         */
        @Bean
        @ConditionalOnProperty(name = "spring.redis.mode", havingValue = "cluster")
        public RedissonClient redissonCluster() {
            System.out.println("cluster redisProperties:" + redisProperties.getCluster());

            Config config = new Config();
            String[] nodes = redisProperties.getCluster().getNodes().split(",");
            List<String> newNodes = new ArrayList<>(nodes.length);
            Arrays.stream(nodes).forEach((index) -> newNodes.add(
                index.startsWith("redis://") ? index : "redis://" + index)
            );

            ClusterServersConfig serverConfig = config.useClusterServers()
                    .addNodeAddress(newNodes.toArray(new String[0])
                    ).setScanInterval(
                        redisProperties.getCluster().getScanInterval()
                    ).setIdleConnectionTimeout(
                        redisProperties.getPool().getSoTimeout()
                    ).setConnectTimeout(
                        redisProperties.getPool().getConnTimeout()
                    ).setRetryAttempts(
                        redisProperties.getCluster().getRetryAttempts()
                    ).setRetryInterval(
                        redisProperties.getCluster().getRetryInterval()
                    ).setMasterConnectionPoolSize(
                            redisProperties.getCluster().getMasterConnectionPoolSize()
                    ).setSlaveConnectionPoolSize(
                            redisProperties.getCluster().getSlaveConnectionPoolSize()
                    ).setTimeout(
                            redisProperties.getTimeout()
                    );

            if (!StringUtils.isEmpty(redisProperties.getPassword())) {
                serverConfig.setPassword(redisProperties.getPassword());
            }
            return Redisson.create(config);
        }


        /**  
         * 哨兵模式 redisson 客戶端
         * @return
         */
        @Bean
        @ConditionalOnProperty(name = "spring.redis.mode", havingValue = "sentinel")
        public RedissonClient redissonSentinel() {
            System.out.println("sentinel redisProperties:" + redisProperties.getSentinel());
            Config config = new Config();
            String[] nodes = redisProperties.getSentinel().getNodes().split(",");
            List<String> newNodes = new ArrayList<>(nodes.length);
            Arrays.stream(nodes).forEach((index) -> newNodes.add(
                index.startsWith("redis://") ? index : "redis://" + index)
            );

            SentinelServersConfig serverConfig = config.useSentinelServers()
                    .addSentinelAddress(newNodes.toArray(new String[0]))
                    .setMasterName(redisProperties.getSentinel().getMaster())
                    .setReadMode(ReadMode.SLAVE)
                    .setTimeout(redisProperties.getTimeout())
                    .setMasterConnectionPoolSize(redisProperties.getPool().getSize())
                    .setSlaveConnectionPoolSize(redisProperties.getPool().getSize());

            if (!StringUtils.isEmpty(redisProperties.getPassword())) {
                serverConfig.setPassword(redisProperties.getPassword());
            }
            return Redisson.create(config);
        }
    }
}

二、Redisson工具類

import org.redisson.api.*;
import org.redisson.client.codec.StringCodec;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author: huangyibo
 * @Date: 2022/6/23 15:01
 * @Description:
 */

@Component
public class RedisUtils {

    /**
     * 默認(rèn)緩存時(shí)間
     */
    private static final Long DEFAULT_EXPIRED = 32000L;

    
    /**
     * 自動(dòng)裝配redisson client對(duì)象
     */
    @Resource
    private RedissonClient redissonClient;

    
    /**
     * 用于操作key
     * @return RKeys 對(duì)象
     */
    public RKeys getKeys() {
        return redissonClient.getKeys();
    }
    
    
    /**
     * 移除緩存
     *
     * @param key
     */
    public void delete(String key) {
        redissonClient.getBucket(key).delete();
    }

    
    /**
     * 獲取getBuckets 對(duì)象
     *
     * @return RBuckets 對(duì)象
     */
    public RBuckets getBuckets() {
        return redissonClient.getBuckets();
    }

    
    /**
     * 讀取緩存中的字符串黍檩,永久有效
     *
     * @param key 緩存key
     * @return 字符串
     */
    public String getStr(String key) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        return bucket.get();
    }

    
    /**
     * 緩存字符串
     *
     * @param key
     * @param value
     */
    public void setStr(String key, String value) {
        RBucket<String> bucket = redissonClient.getBucket(key);
        bucket.set(value);
    }

    
    /**
     * 緩存帶過期時(shí)間的字符串
     *
     * @param key     緩存key
     * @param value   緩存值
     * @param expired 緩存過期時(shí)間叉袍,long類型,必須傳值
     */
    public void setStr(String key, String value, long expired) {
        RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE);
        bucket.set(value, expired <= 0L ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
    }

    
    /**
     * string 操作刽酱,如果不存在則寫入緩存(string方式喳逛,不帶有redisson的格式信息)
     *
     * @param key     緩存key
     * @param value   緩存值
     * @param expired 緩存過期時(shí)間
     */
    public Boolean setIfAbsent(String key, String value, long expired) {
        RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE);
        return bucket.trySet(value, expired <= 0L ? DEFAULT_EXPIRED : expired, TimeUnit.SECONDS);
    }

    
    /**
     * 如果不存在則寫入緩存(string方式,不帶有redisson的格式信息)棵里,永久保存
     *
     * @param key   緩存key
     * @param value 緩存值
     */
    public Boolean setIfAbsent(String key, String value) {
        RBucket<String> bucket = redissonClient.getBucket(key, StringCodec.INSTANCE);
        return bucket.trySet(value);
    }

    
    /**
     * 判斷緩存是否存在
     *
     * @param key
     * @return true 存在
     */
    public Boolean isExists(String key) {
        return redissonClient.getBucket(key).isExists();
    }

    
    /**
     * 獲取RList對(duì)象
     *
     * @param key RList的key
     * @return RList對(duì)象
     */
    public <T> RList<T> getList(String key) {
        return redissonClient.getList(key);
    }

    
    /**
     * 獲取RMapCache對(duì)象
     *
     * @param key
     * @return RMapCache對(duì)象
     */
    public <K, V> RMapCache<K, V> getMap(String key) {
        return redissonClient.getMapCache(key);
    }

    
    /**
     * 獲取RSET對(duì)象
     *
     * @param key
     * @return RSET對(duì)象
     */
    public <T> RSet<T> getSet(String key) {
        return redissonClient.getSet(key);
    }

    
    /**
     * 獲取RScoredSortedSet對(duì)象
     *
     * @param key
     * @param <T>
     * @return RScoredSortedSet對(duì)象
     */
    public <T> RScoredSortedSet<T> getScoredSortedSet(String key) {
        return redissonClient.getScoredSortedSet(key);
    }
}

三润文、常用RKeys的API操作

每個(gè)Redisson對(duì)象實(shí)例都會(huì)有一個(gè)與之對(duì)應(yīng)的Redis數(shù)據(jù)實(shí)例,可以通過調(diào)用getName方法來取得redis數(shù)據(jù)實(shí)例的名稱(key)殿怜,所有于Redis key相關(guān)的操作都?xì)w納在RKeys這個(gè)接口里典蝌。

RKeys keys = client.getKeys();
//獲取所有key值
Iterable<String> allKeys = keys.getKeys();
//模糊查詢所有包含關(guān)鍵字key的值
Iterable<String> foundedKeys = keys.getKeysByPattern("key");
//刪除多個(gè)key值
long numOfDeletedKeys = keys.delete("obj1", "obj2", "obj3");
//模糊刪除key值
long deletedKeysAmount = keys.deleteByPattern("test?");
//隨機(jī)獲取key
String randomKey = keys.randomKey();
//查詢當(dāng)前有多少個(gè)key
long keysAmount = keys.count();

具體demo

private void getKeys() {
    RKeys keys = redisUtils.getRedisKeys();
    Iterable<String> allKeys = keys.getKeys();
    StringBuilder sb = new StringBuilder();
    for (String key : allKeys) {
        sb = sb.append(key).append(",");
    }
    log.info("所有的key:{}", sb.substring(0, sb.length() - 1));
    // 模糊查詢以 map 打頭的所有 key
    allKeys = keys.getKeysByPattern("map*");
    sb = new StringBuilder();
    for (String key : allKeys) {
        sb = sb.append(key).append(",");
    }
    log.info("模糊匹配到的key:{}", sb.substring(0, sb.length() - 1));
}

其中,getKeysByPattern是基于redis的scan命令實(shí)現(xiàn)头谜。

四骏掀、通用對(duì)象桶Object Bucket

Redisson的分布式RBucket Java對(duì)象是一種通用對(duì)象桶,可以用來存放任意類型的對(duì)象柱告。除了同步接口外截驮,還提供異步(Async)、反射式(Reactive)和RxJava2標(biāo)準(zhǔn)的接口际度。還可以通過RBuckets接口實(shí)現(xiàn)批量操作多個(gè)RBucket對(duì)象葵袭。

/**
 * String 數(shù)據(jù)類型
 */
private void strDemo() {
    redisUtils.setStr(DEMO_STR, "Hello, String.");
    log.info("String 測(cè)試數(shù)據(jù):{}", redisUtils.getStr(DEMO_STR));
    redisUtils.setStr("myBucket", "myBucketIsXxx");
    RBuckets buckets = redisUtils.getBuckets();
    Map<String, String> foundBuckets = buckets.get("myBucket*");
    Map<String, Object> map = new HashMap<>();
    map.put("myBucket1", "value1");
    map.put("myBucket2", 30L);

    // 同時(shí)保存全部通用對(duì)象桶。
    buckets.set(map);
    Map<String, String> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");
    log.info("跨桶String 測(cè)試數(shù)據(jù):{}", loadedBuckets);
    map.put("myBucket3", 320L);
}

五乖菱、散列 Hash

基于Redisson的分布式映射結(jié)構(gòu)的RMap Java對(duì)象實(shí)現(xiàn)了java.util.concurrent.ConcurrentMap和java.util.Map接口坡锡,與HashMap不同的是蓬网,RMap 保持了元素的插入順序。該對(duì)象的最大容量受Redis限制鹉勒,最大元素?cái)?shù)量是4294967295個(gè)帆锋。

/**
 * Hash類型
 */
private void hashDemo() {
    RMap<Object, Object> map = redisUtils.getMap("mapDemo");
    map.put("demoId1", "123");
    map.put("demoId100", "13000");
    Object demoId1Obj = map.get("demoId1");
    log.info("Hash 測(cè)試數(shù)據(jù):{}", demoId1Obj);
}

六、集合 Set

基于Redisson的分布式Set結(jié)構(gòu)的RSet Java對(duì)象實(shí)現(xiàn)了java.util.Set接口贸弥,通過元素的互相狀態(tài)比較保證了每個(gè)元素的唯一性窟坐,該對(duì)象的最大容量受Redis限制,最大元素?cái)?shù)量是4294967295個(gè)绵疲。

/**
 * Set 測(cè)試
 */
private void setDemo() {
    RSet<String> set = redisUtils.getSet("setKey");
    set.add("value777");
    log.info("Set 測(cè)試數(shù)據(jù)");
    Iterator<String> iterator = set.iterator();
    while (iterator.hasNext()) {
        String next = iterator.next();
        log.info(next);
    }
}

七哲鸳、列表 List

基于Redisson的分布式列表 List 結(jié)構(gòu)的RList Java對(duì)象在實(shí)現(xiàn)了java.util.List接口的同時(shí),確保了元素插入時(shí)的順序盔憨,該對(duì)象的最大容量受Redis限制徙菠,最大元素?cái)?shù)量是4294967295個(gè)。

/**
 * List數(shù)據(jù)類型
 */
private void listDemo() {
    RList<String> list = redisUtils.getList("listDemo");
    list.add("listValue1");
    list.add("listValue2");

    log.info("List 測(cè)試數(shù)據(jù):{}", list.get(1));
}

綜合示例

將上述demo放入一個(gè)API中郁岩,快速測(cè)試:

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping(value = "/redisson", method = RequestMethod.POST)
public class StudyRedissonController {

    @Resource
    private RedisUtils redisUtils;

    private static String DEMO_STR = "demoStr";

    @PostMapping("/learnRedisson")
    public void learnRedisson() {
        //三種數(shù)據(jù)結(jié)構(gòu)使用示例
        strDemo();
        hashDemo();
        listDemo();
        setDemo();
        getKeys();
    }

    private void getKeys() {
        RKeys keys = redisUtils.getKeys();
        Iterable<String> allKeys = keys.getKeys();
        StringBuilder sb = new StringBuilder();
        for (String key : allKeys) {
            sb = sb.append(key).append(",");
        }
        log.info("所有的key:{}", sb.substring(0, sb.length() - 1));
        // 模糊查詢以 map 打頭的所有 key
        allKeys = keys.getKeysByPattern("map*");
        sb = new StringBuilder();
        for (String key : allKeys) {
            sb = sb.append(key).append(",");
        }
        log.info("模糊匹配到的key:{}", sb.substring(0, sb.length() - 1));
    }
    /**
     * Hash類型
     */
    private void hashDemo() {
        RMap<Object, Object> map = redisUtils.getMap("mapDemo");
        map.put("demoId1", "123");
        map.put("demoId100", "13000");
        Object demoId1Obj = map.get("demoId1");
        log.info("Hash 測(cè)試數(shù)據(jù):{}", demoId1Obj);
    }

    /**
     * String 數(shù)據(jù)類型
     */
    private void strDemo() {
        redisUtils.setStr(DEMO_STR, "Hello, String.");
        log.info("String 測(cè)試數(shù)據(jù):{}", redisUtils.getStr(DEMO_STR));
        redisUtils.setStr("myBucket", "myBucketIsXxx");
        RBuckets buckets = redisUtils.getBuckets();
        Map<String, String> foundBuckets = buckets.get("myBucket*");
        Map<String, Object> map = new HashMap<>();
        map.put("myBucket1", "value1");
        map.put("myBucket2", 30L);

        // 同時(shí)保存全部通用對(duì)象桶婿奔。
        buckets.set(map);
        Map<String, String> loadedBuckets = buckets.get("myBucket1", "myBucket2", "myBucket3");
        log.info("跨桶String 測(cè)試數(shù)據(jù):{}", loadedBuckets);
        map.put("myBucket3", 320L);
    }

    /**
     * List數(shù)據(jù)類型
     */
    private void listDemo() {
        RList<String> list = redisUtils.getList("listDemo");
        list.add("listValue1");
        list.add("listValue2");

        log.info("List 測(cè)試數(shù)據(jù):{}", list.get(1));
    }
    /**
     * Set 測(cè)試
     */
    private void setDemo() {
        RSet<String> set = redisUtils.getSet("setKey");
        set.add("value777");
        log.info("Set 測(cè)試數(shù)據(jù)");
        Iterator<String> iterator = set.iterator();
        while (iterator.hasNext()) {
            String next = iterator.next();
            log.info(next);
        }
    }

}

參考:
https://blog.51cto.com/u_14028890/2308518

https://www.cnblogs.com/east7/p/16255253.html

https://www.cnblogs.com/east7/p/16255305.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市问慎,隨后出現(xiàn)的幾起案子萍摊,更是在濱河造成了極大的恐慌,老刑警劉巖如叼,帶你破解...
    沈念sama閱讀 212,599評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冰木,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡笼恰,警方通過查閱死者的電腦和手機(jī)踊沸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,629評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來社证,“玉大人逼龟,你說我怎么就攤上這事∽菲希” “怎么了腺律?”我有些...
    開封第一講書人閱讀 158,084評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)辽俗。 經(jīng)常有香客問我疾渣,道長(zhǎng),這世上最難降的妖魔是什么崖飘? 我笑而不...
    開封第一講書人閱讀 56,708評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮杈女,結(jié)果婚禮上朱浴,老公的妹妹穿的比我還像新娘吊圾。我一直安慰自己,他們只是感情好翰蠢,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,813評(píng)論 6 386
  • 文/花漫 我一把揭開白布项乒。 她就那樣靜靜地躺著,像睡著了一般梁沧。 火紅的嫁衣襯著肌膚如雪檀何。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,021評(píng)論 1 291
  • 那天廷支,我揣著相機(jī)與錄音频鉴,去河邊找鬼。 笑死恋拍,一個(gè)胖子當(dāng)著我的面吹牛垛孔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播施敢,決...
    沈念sama閱讀 39,120評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼周荐,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了僵娃?” 一聲冷哼從身側(cè)響起概作,我...
    開封第一講書人閱讀 37,866評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎默怨,沒想到半個(gè)月后讯榕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,308評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡先壕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,633評(píng)論 2 327
  • 正文 我和宋清朗相戀三年瘩扼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片垃僚。...
    茶點(diǎn)故事閱讀 38,768評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡集绰,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出谆棺,到底是詐尸還是另有隱情栽燕,我是刑警寧澤,帶...
    沈念sama閱讀 34,461評(píng)論 4 333
  • 正文 年R本政府宣布改淑,位于F島的核電站碍岔,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏朵夏。R本人自食惡果不足惜蔼啦,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,094評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望仰猖。 院中可真熱鬧捏肢,春花似錦奈籽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,850評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辩棒,卻和暖如春狼忱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背一睁。 一陣腳步聲響...
    開封第一講書人閱讀 32,082評(píng)論 1 267
  • 我被黑心中介騙來泰國打工钻弄, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卖局。 一個(gè)月前我還...
    沈念sama閱讀 46,571評(píng)論 2 362
  • 正文 我出身青樓斧蜕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親砚偶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子批销,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,666評(píng)論 2 350

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