JAVA开发相关代码模板(持续更新)

本文主要整理JAVA开发中的一些模板代码,作为平时参考使用。

1 MongoTemplate

版本:mongoDb4.0

1.1 写入数据

JSONObject json = new JSONObject();
json.put("userName", "张三");
json.put("age", 20);
json.put("sex", "男");
json.put("oneFlag", true);
json.put("towFlag", true);
json.put("indexNum", i + 1);
json.put("delFlag", "0");
mongoTemplate.insert(json, "t_user_info");

1.2 更新数据

// ----------[组装查询条件]----------
Query query = new Query();
query.addCriteria(Criteria.where("indexNum").is(1));

// ----------[组装更新逻辑]----------
Update update = new Update();
update.set("userName", "李四");
update.set("age", 19);

// ----------[更新数据]----------
UpdateResult updateResult = mongoTemplate.updateMulti(query, update, "t_user_info");
System.out.println("匹配数量:"+updateResult.getMatchedCount());
// 如果更新后数据和更新前一样,则getModifiedCount()返回0
System.out.println("更新数量:"+updateResult.getModifiedCount());

1.3 基本查询

Query query = new Query();
// ----------[拼接查询条件]----------
// 等于
query.addCriteria(Criteria.where("delFlag").is("0"));
// 字符串模糊查询
query.addCriteria(Criteria.where("userName").regex("^.*张三.*$"));
// 数值比较(大于)
query.addCriteria(Criteria.where("age").gte(20));
// 集合查询
query.addCriteria(Criteria.where("sex").in(Arrays.asList("男", "女")));
// 或条件
query.addCriteria(new Criteria().orOperator(Criteria.where("oneFlag").is(true), Criteria.where("towFlag").is(true)));

// ----------[排序]----------
query.with(Sort.by(new Sort.Order(Sort.Direction.DESC, "age"), new Sort.Order(Sort.Direction.ASC, "indexNum")));

// ----------[指定查询字段]----------
query.fields().include("userName").include("age").include("sex").include("indexNum");

// ----------[分页]----------
// 当前页数
int pageNumber = 1;
// 每页数量
int pageLimit = 10;
query.skip((pageNumber - 1) * pageLimit).limit(pageLimit);

// ----------[执行查询]----------
List<Document> list = mongoTemplate.find(query, Document.class, "t_user_info");
// 输出内容:【Query: { "delFlag" : "0", "userName" : { "$regex" : "^.*张三.*$", "$options" : ""}, "age" : { "$gte" : 20}, "sex" : { "$in" : ["男", "女"]}, "$or" : [{ "oneFlag" : true}, { "towFlag" : true}]}, Fields: { "indexNum" : 1, "sex" : 1, "userName" : 1, "age" : 1}, Sort: { "age" : -1, "indexNum" : 1}】
System.out.println(query.toString());

1.4 组装查询条件

(1)错误场景

mongoTemplate的query在组装查询条件时,执行query.addCriteria,不能对统一字段执行多次此操作,否则会抛出InvalidMongoDbApiUsageException异常。

错误代码,如下:

Query query = new Query();
// 对字段age,添加多个条件
query.addCriteria(Criteria.where("age").gte(20));
query.addCriteria(Criteria.where("age").lte(30));
List<Document> list = mongoTemplate.find(query, Document.class, "t_user_info");

此种情况,抛出异常信息如下:

org.springframework.data.mongodb.InvalidMongoDbApiUsageException: Due to limitations of the com.mongodb.BasicDocument, you can't add a second 'age' criteria. Query already contains '{ "age" : { "$gte" : 20}}'

(2)解决方案-1

同一个字段,拼接多个条件。

Query query = new Query();
query.addCriteria(Criteria.where("age").gte(20).lte(30));
List<Document> list = mongoTemplate.find(query, Document.class, "t_user_info");
// 输出内容:【Query: { "age" : { "$gte" : 20, "$lte" : 30}}, Fields: {}, Sort: {}】
System.out.println(query);

(3)解决方案-2(建议)

将查询条件,拼接为and模式

List<Criteria> criteriaList = new ArrayList<>();
criteriaList.add(Criteria.where("age").gte(20));
criteriaList.add(Criteria.where("age").lte(30));

Criteria[] criteriaArr= new Criteria[criteriaList.size()];
criteriaList.toArray(criteriaArr);

Criteria criteria = new Criteria();
criteria.andOperator(criteriaArr);

Query query = new Query();
query.addCriteria(criteria);

List<Document> list = mongoTemplate.find(query, Document.class, "t_user_info");
// 输出内容:【Query: { "$and" : [{ "age" : { "$gte" : 20}}, { "age" : { "$lte" : 30}}]}, Fields: {}, Sort: {}】
System.out.println(query);

1.5 游标查询

试用于海量数据查询

// ----------[组装查询条件]----------
Query query = new Query();
query.addCriteria(Criteria.where("sex").is("男"));

// ----------[游标查询]----------
try(MongoCursor<Document> cursor = mongoTemplate.getCollection("t_user_info").find(query.getQueryObject()).batchSize(1000).noCursorTimeout(true).cursor();) {
    while (cursor.hasNext()){
        Document document = cursor.next();
        // TODO 执行业务方法
    }
}catch (Exception e){
    e.printStackTrace();
}

1.6 聚合查询

// ----------[分页相关]----------
// 页数
long pageNumber = 1;
// 每页数量
long pageLimit = 10;

// ----------[查询条件相关]----------
// where
Criteria whereCriteria = new Criteria().andOperator(Criteria.where("delFlag").is("0"));
// having
Criteria havingCriteria = new Criteria().andOperator(Criteria.where("count").gte(500));

// ----------[分组查询]----------
Aggregation aggregation = Aggregation.newAggregation(
    // 条件(match在group前作为where使用)
    Aggregation.match(whereCriteria),
    // 分组条件(group by sex, userName)
    Aggregation.group("sex", "userName").max("indexNum").as("maxIndexNum").count().as("count"),
    //having(match在group后作为having使用)
    Aggregation.match(havingCriteria),
    // 映射字段到前台
    Aggregation.project("sex", "userName", "maxIndexNum", "count"),
    // 排序
    Aggregation.sort(Sort.by(new Sort.Order(Sort.Direction.ASC, "sex"))),
    // 分页
    Aggregation.skip((pageNumber - 1) * pageLimit),
    Aggregation.limit(pageLimit)
);
// Mongodb规定了aggregate管道聚合的返回数据不能超过`16M`,超过16M就会报异常错误。解决方法就是设置`allowDiskUse:true`,即允`许使用磁盘缓存`
aggregation = aggregation.withOptions(Aggregation.newAggregationOptions().allowDiskUse(true).build());

// 输出内容:【{ "aggregate" : "__collection__", "pipeline" : [{ "$match" : { "$and" : [{ "delFlag" : "0"}]}}, { "$group" : { "_id" : { "sex" : "$sex", "userName" : "$userName"}, "maxIndexNum" : { "$max" : "$indexNum"}, "count" : { "$sum" : 1}}}, { "$match" : { "$and" : [{ "count" : { "$gte" : 500}}]}}, { "$project" : { "sex" : "$_id.sex", "userName" : "$_id.userName", "maxIndexNum" : 1, "count" : 1}}, { "$sort" : { "sex" : 1}}, { "$skip" : { "$numberLong" : "0"}}, { "$limit" : { "$numberLong" : "10"}}], "allowDiskUse" : true}】
System.out.println(aggregation.toString());
List<Map> list = mongoTemplate.aggregate(aggregation, "t_user_info", Map.class).getMappedResults();

1.7 MapReduce

1.7.1 注意事项

Map注意事项:

  • 在map函数中,如果要引用当前文档自身,可以使用this
  • 在一个map函数中可以任意多次调用emit函数来输出具有key/value形式的中间数据

Reduce注意事项:

  • 如果一个key只有一个value,那么MongoDB不调用reduce函数
  • 对于同一个key,reduce函数可能会执行多次
1.7.2 mongo脚本

(1)输出结果到实际的表

输出结果到表中(以替换整张表的方式)

// 自定义map函数
var myMap = function() {
    emit(this.sex, this.age);
}
// 自定义reduce函数
var myReduce = function(key, values) {
    var totalAge = 0;
    for (var i = 0; i < values.length; i++) {
        totalAge = totalAge + values[i];
    }
    return totalAge;
}
// 执行mapReduce方法
db.t_user_info.mapReduce(
    // 自定义map函数
    myMap,
    // 自定义reduce函数
    myReduce,
    {
        // 查询条件
        query: {"delFlag" : "0"},
        // 输出方式(整个替换输出到表)(输出到内容中,可用:"out: { inline: 1 }")
        out: "map_reduce_result"
    }
)

执行后,输出内容如下:

/* 1 */
{
    // 存储数据的集合
    "result" : "map_reduce_result",
    // 执行花费的时间(毫秒)
    "timeMillis" : 138.0,
    "counts" : {
        // 满足条件被发送到map函数的文档个数
        "input" : 1500,
        // 在map函数中emit被调用的次数,也就是所有集合中的数据总量
        "emit" : 1500,
        // 满足条件被发送到reduce函数的文档个数
        "reduce" : 15,
        // 结果集合中的文档个数
        "output" : 2
    },
    // 是否成功,成功为1
    "ok" : 1.0,
    "_o" : {
        "result" : "map_reduce_result",
        "timeMillis" : 138,
        "counts" : {
            "input" : 1500,
            "emit" : 1500,
            "reduce" : 15,
            "output" : 2
        },
        "ok" : 1.0
    },
    "_keys" : [ 
        "result", 
        "timeMillis", 
        "counts", 
        "ok"
    ],
    "_db" : {
        "_mongo" : {
            "slaveOk" : true,
            "host" : "192.168.0.11:40001",
            "defaultDB" : "aaDb",
            "authStatus" : {
                "authRequired" : true,
                "isMaster" : true,
                "replSetGetStatus" : true
            },
            "_readMode" : "commands"
        },
        "_name" : "aaDb"
    },
    "_coll" : {
        "_mongo" : {
            "slaveOk" : true,
            "host" : "192.168.0.11:40001",
            "defaultDB" : "aaDb",
            "authStatus" : {
                "authRequired" : true,
                "isMaster" : true,
                "replSetGetStatus" : true
            },
            "_readMode" : "commands"
        },
        "_db" : {
            "_mongo" : {
                "slaveOk" : true,
                "host" : "192.168.0.11:40001",
                "defaultDB" : "aaDb",
                "authStatus" : {
                    "authRequired" : true,
                    "isMaster" : true,
                    "replSetGetStatus" : true
                },
                "_readMode" : "commands"
            },
            "_name" : "aaDb"
        },
        "_shortName" : "map_reduce_result",
        "_fullName" : "aaDb.map_reduce_result"
    }
}

执行结束后,表map_reduce_result中结果如下:

/* 1 */
{
    "_id" : "女",
    "value" : 12500.0
}

/* 2 */
{
    "_id" : "男",
    "value" : 19999.0
}

(2)输出到内存

如只想获取,计算结果,不想将数据结果输出到实际的表中。可以将out进行如下配置,将结果,输出到内存中

out: { inline: 1 }

这个选项只有在结果集单个文档大小在16MB限制范围内时才有效

完整脚本如下:

// 自定义map函数
var myMap = function() {
    emit(this.sex, this.age);
}
// 自定义reduce函数
var myReduce = function(key, values) {
    var totalAge = 0;
    for (var i = 0; i < values.length; i++) {
        totalAge = totalAge + values[i];
    }
    return totalAge;
}
// 执行mapReduce方法
db.t_user_info.mapReduce(
    // 自定义map函数
    myMap,
    // 自定义reduce函数
    myReduce,
    {
        // 查询条件
        query: {"delFlag" : "0"},
        // 输出方式(内存临时表)
        out: { inline: 1 }
    }
)

输出结果如下(可见results属性中,可以看到计算的最终结果)

/* 1 */
{
    "results" : [ 
        {
            "_id" : "女",
            "value" : 12500.0
        }, 
        {
            "_id" : "男",
            "value" : 19999.0
        }
    ],
    "timeMillis" : 81.0,
    "counts" : {
        "input" : 1500,
        "emit" : 1500,
        "reduce" : 15,
        "output" : 2
    },
    "ok" : 1.0,
    "_o" : {
        "results" : [ 
            {
                "_id" : "女",
                "value" : 12500.0
            }, 
            {
                "_id" : "男",
                "value" : 19999.0
            }
        ],
        "timeMillis" : 81,
        "counts" : {
            "input" : 1500,
            "emit" : 1500,
            "reduce" : 15,
            "output" : 2
        },
        "ok" : 1.0
    },
    "_keys" : [ 
        "results", 
        "timeMillis", 
        "counts", 
        "ok"
    ],
    "_db" : {
        "_mongo" : {
            "slaveOk" : true,
            "host" : "192.168.0.11:40001",
            "defaultDB" : "aaDb",
            "authStatus" : {
                "authRequired" : true,
                "isMaster" : true,
                "replSetGetStatus" : true
            },
            "_readMode" : "commands"
        },
        "_name" : "aaDb"
    }
}
1.7.3 mongoTemplate

(1)写入到内存中

// (1)定义map函数
String mapFun = "function() {\n" +
    "    emit(this.sex, this.age);\n" +
    "}";
// (2)定义reduce函数
String reduceFun = "function(key, values) {\n" +
    "    var totalAge = 0;\n" +
    "    for (var i = 0; i < values.length; i++) {\n" +
    "        totalAge = totalAge + values[i];\n" +
    "    }\n" +
    "    return totalAge;\n" +
    "}";

// (3)执行mapReduce方法
MapReduceResults<Document> mapReduceResults = mongoTemplate.mapReduce(new Query(Criteria.where("delFlag").is("0")), "t_user_info", mapFun, reduceFun, Document.class);

// (4)输出执行结果
Iterator<Document> iterator = mapReduceResults.iterator();
while (iterator.hasNext()) {
    // Document{{_id=女, value=12500.0}}
    // Document{{_id=男, value=19999.0}}
    System.out.println(iterator.next());
}

(2)写入到表

// (1)定义map函数
String mapFun = "function() {\n" +
    "    emit(this.sex, this.age);\n" +
    "}";

// (2)定义reduce函数
String reduceFun = "function(key, values) {\n" +
    "    var totalAge = 0;\n" +
    "    for (var i = 0; i < values.length; i++) {\n" +
    "        totalAge = totalAge + values[i];\n" +
    "    }\n" +
    "    return totalAge;\n" +
    "}";

// (3)定义相关属性配置
MapReduceOptions mapReduceOptions = MapReduceOptions.options().outputCollection("my_map_reduce_res");

// (4)执行mapReduce方法
MapReduceResults<Document> mapReduceResults = mongoTemplate.mapReduce(new Query(Criteria.where("delFlag").is("0")), "t_user_info", mapFun, reduceFun, mapReduceOptions, Document.class);

// (5)输出执行结果
Iterator<Document> iterator = mapReduceResults.iterator();
while (iterator.hasNext()) {
    // Document{{_id=女, value=12500.0}}
    // Document{{_id=男, value=19999.0}}
    System.out.println(iterator.next());
}

根据输出结果,可见,仍然可在对象MapReduceResults中获取执行结果,执行结束后,查询数据库,可见目标表my_map_reduce_res中,已生成我们需要的数据。

/* 1 */
{
    "_id" : "女",
    "value" : 12500.0
}

/* 2 */
{
    "_id" : "男",
    "value" : 19999.0
}

1.8 bulk

主要适用于批量更新,减少更新请求的调用次数。也可混合使用(写入、更新、删除)。

(1)写法1

// ----------[定义更新集合]----------
List<Pair<Query, Update>> updatePairList = new ArrayList<>();

// ----------[组装更新集合]----------
// 组装更新数据1
Query query1 = new Query();
query1.addCriteria(Criteria.where("indexNum").is(1));
Update update1 = new Update();
update1.set("delFlag", "11");
Pair<Query, Update> updatePair1 = Pair.of(query1, update1);
updatePairList.add(updatePair1);

// 组装更新数据2
Query query2 = new Query();
query2.addCriteria(Criteria.where("indexNum").is(2));
Update update2 = new Update();
update2.set("delFlag", "12");
Pair<Query, Update> updatePair2 = Pair.of(query2, update2);
updatePairList.add(updatePair2);

// ......

// ----------[更新数据]----------
BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "t_user_info");
operations.updateOne(updatePairList);
BulkWriteResult writeResult = operations.execute();
boolean result = writeResult.wasAcknowledged();
System.out.println("执行结果:" + result);

(2)写法2

 // ----------[定义操作对象]----------
BulkOperations operations = mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, "t_user_info");

// ----------[组装更新集合]----------
// 组装更新数据1
Query query1 = new Query();
query1.addCriteria(Criteria.where("indexNum").is(1));
Update update1 = new Update();
update1.set("delFlag", "21");
operations.updateOne(query1,update1);

// 组装更新数据2
Query query2 = new Query();
query2.addCriteria(Criteria.where("indexNum").is(2));
Update update2 = new Update();
update2.set("delFlag", "22");
operations.updateOne(query2,update2);

// ......
// operations.insert()
// operations.remove()

// ----------[更新数据]----------
BulkWriteResult writeResult = operations.execute();
boolean result = writeResult.wasAcknowledged();
System.out.println("执行结果:" + result);

1.9 切换到主库查询

默认readPreference为ReadPreference.secondaryPreferred()时,可通过如下方式,临时设置从主库读取数据

也可设置专门从主库读取数据的mongoTemplate句柄

// mongoTemplate切换到主库查询
try {
    mongoTemplate.setReadPreference(ReadPreference.primary());
    
    // TODO 执行查询操作......

}catch (Exception e){
    // 异常(处理或抛出)
    e.printStackTrace();
}finally {
    // 切换回默认的ReadPreference
    mongoTemplate.setReadPreference(ReadPreference.secondary());
}

2 Mybatis

应用数据库:mysql。测试使用建表脚本如下:

CREATE TABLE `c_m_phone` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `phone_first` varchar(20) DEFAULT NULL COMMENT '前缀号段',
  `phone_provence` varchar(20) DEFAULT NULL COMMENT '手机所在省份',
  `phone_city` varchar(20) DEFAULT NULL COMMENT '手机所在城市',
  `service` varchar(20) DEFAULT NULL COMMENT '服务商',
  `area_number` int(10) DEFAULT NULL COMMENT '区号',
  `code` varchar(10) DEFAULT NULL COMMENT '邮编',
  PRIMARY KEY (`id`),
  UNIQUE KEY `phoneFirst` (`phone_first`) USING BTREE
) ENGINE=InnoDBDEFAULT CHARSET=utf8 COMMENT='电话区域表';

2.1 批量插入

适用于海量数据插入到数据库的情况,用来提高写入速度,建议上限5000

Java方法:

int insertBatch(@Param("list") List<CMPhone> list);

xml:

<insert id="insertBatch">
    insert into c_m_phone(phone_first, phone_provence, phone_city, service, area_number, code)
    values
    <foreach collection="list" item="item" separator=",">
    (
        #{item.phoneFirst}, #{item.phoneProvence}, #{item.phoneCity},#{item.service}, #{item.areaNumber}, #{item.code}
    )
    </foreach>
</insert>

2.2 流式查询

Java方法:

/**
 * 流式查询数据
 * @param model   参数
 * @param handler 结果集
 * @return void
 */
void findByStream(@Param("model") CMPhone model, ResultHandler handler);

xml:

<resultMap id="BaseResultMap" type="com.tmp.demo.mysql.mapper.bean.CMPhone">
    <id column="id" property="id" jdbcType="INTEGER"/>
    <result column="phone_first" property="phoneFirst" jdbcType="VARCHAR"/>
    <result column="phone_provence" property="phoneProvence" jdbcType="VARCHAR"/>
    <result column="phone_city" property="phoneCity" jdbcType="VARCHAR"/>
    <result column="service" property="service" jdbcType="VARCHAR"/>
    <result column="area_number" property="areaNumber" jdbcType="INTEGER"/>
    <result column="code" property="code" jdbcType="VARCHAR"/>
</resultMap>

<select id="findByStream" resultMap="BaseResultMap" resultSetType="FORWARD_ONLY" fetchSize="-2147483648">
    select id, phone_first, phone_provence, phone_city, service, area_number, code
    from c_m_phone
    <where>
        <if test="model.phoneFirst != null and model.phoneFirst != '' ">
            AND phone_first like #{model.phoneFirst}
        </if>
    </where>
</select>

应用:

CMPhone model = new CMPhone();
model.setPhoneFirst("%37%");
cmPhoneMapper.findByStream(model, (ResultHandler<CMPhone>) resultContext -> {
    System.out.println("第几个:" + resultContext.getResultCount());
    CMPhone cmPhone = resultContext.getResultObject();
    System.out.println("查询结果:" + cmPhone);
});

2.3 自定义事务

@Autowired
private PlatformTransactionManager transactionManager;

@Autowired
private TransactionDefinition transactionDefinition;

/**
 * 自定义事务测试
 */
public void transactionTest() {
    // 开启事务
    TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
    try {
        // ----------执行数据库操作----------start
        List<CMPhone> list = new ArrayList<>();
        CMPhone cmPhone = new CMPhone();
        cmPhone.setPhoneFirst("X1");
        list.add(cmPhone);
        cmPhoneMapper.insertBatch(list);
        // 如事务写入的数据很多,且执行时间太长,可中途进行资源刷新(刷新缓存到数据库,提高速度)
        transactionStatus.flush();
        cmPhoneMapper.insertBatch(list);
        // ----------执行数据库操作----------end

        // 提交事务
        transactionManager.commit(transactionStatus);
    } catch (Exception e) {
        e.printStackTrace();
        // 回滚事务
        transactionManager.rollback(transactionStatus);
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容