BeanCopy框架終極指南

前言

image.png

如圖所示,在開發(fā)之中腊徙,無論是MVC式的三層架構(gòu),還是DDD領(lǐng)域驅(qū)動式的架構(gòu)简十。總會有各種DTO撬腾、DO螟蝙、PO、VO之間的轉(zhuǎn)換需求时鸵。所以我們經(jīng)常會定義兩層Object字段是保持一致的胶逢,便于防腐層Assember操作。但現(xiàn)實(shí)需求中也會遇到一些復(fù)雜映射饰潜。所以我們應(yīng)該如何基于場景選擇合適的BeanCopy框架呢初坠?

這篇博客主要整理一下BeanCopy類框架。

  • 各個(gè)框架性能表現(xiàn)
  • 如何選擇

BeanCopy框架

除了HardCopy之外(手寫set get)
常用的BeanCopy選擇有以下:

我直接給出一個(gè)performance報(bào)告
BeanCopy框架性能對比
結(jié)論圖:

image.png


框架選擇

我主要推兩大類

  • 基于MapStruct*Selma的注解式Mapper
    MapStruct和Selma都是基于注解處理器實(shí)現(xiàn)的彭雾,關(guān)于注解處理器我單獨(dú)寫一篇blog介紹碟刺,到時(shí)候在這里新增鏈接。
    MapStruct是基于JSR 269的Java注解處理器薯酝,在使用過程中需要只需要配置完成后運(yùn)行 mvn compile就會發(fā)現(xiàn) target文件夾中生成了一個(gè)mapper接口的實(shí)現(xiàn)類半沽。打開實(shí)現(xiàn)類會發(fā)現(xiàn)實(shí)體類中自動生成了字段一一對應(yīng)的get、set方法的文件吴菠。
    比如我定義一個(gè)MapStruct接口(@Mapper注解支持IOC注入方式者填、我這里沒使用)
@Mapper
public interface PersonMapper {
    PersonMapper INSTANCE = Mappers.getMapper(PersonMapper.class);

    /**
     * source -> destination
     *
     * @param car
     * @return
     */
    @Mappings({
        @Mapping(source = "middleName", target = "middle"),
        @Mapping(target = "email", ignore = true)
    })
    PersonDestination sourceToDestination(PersonSource car);
}

編譯之后你會發(fā)現(xiàn)target多了一個(gè)實(shí)現(xiàn)類


image.png

同樣的道理我們看看Selma

@Mapper
public interface SelmaPersonMapper {
    SelmaPersonMapper INSTANCE = Selma.mapper(SelmaPersonMapper.class);

    /**
     * source -> destination
     *
     * @param car
     * @return
     * @Maps(withCustomFields = {
     * @Field({"middleName", "middle"})
     * }, withIgnoreFields = {"email"})
     */
    @Maps(withCustomFields = {
        @Field({"middleName", "middle"})
    }, withIgnoreFields = {"email"})
    PersonDestination sourceToDestination(PersonSource car);
}

所以Selma和MapStruct是非常相似的,原理一樣做葵,并且在注解和用法上幾乎一樣占哟,我認(rèn)為MapStruct更好的原因主要是社區(qū)更活躍,與SpringBoot集成更好酿矢,并且生成的代碼更規(guī)范榨乎、簡潔、漂亮瘫筐。

  • 基于Orika蜜暑、JMapper的靜態(tài)工具類(Dozer性能太差舍棄)
    封裝一下以下代碼即可。
  private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        MapperFacade mapper = mapperFactory.getMapperFacade();
        PersonDestination orikaDestination = mapper.map(source, PersonDestination.class);

如果是List互相轉(zhuǎn)換

 private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        MapperFacade mapper = mapperFactory.getMapperFacade();
        List<PersonSource> sourceList = Lists.newArrayList(source);
        List<PersonDestination> personDestinations = mapper.mapAsList(sourceList, PersonDestination.class);

如果是字段名有映射的

 private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();
        mapperFactory.classMap(PersonSource.class, PersonDestination.class)
            .field("firstName", "givenName")
            .field("lastName", "sirName")
            .byDefault()
            .register();
        MapperFacade mapper = mapperFactory.getMapperFacade();
        PersonDestination destination = mapper.map(source, PersonDestination.class);


實(shí)驗(yàn)

@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
public class PersonSourceComputer {
    private String name;
    private BigDecimal price;
}

@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
public class PersonSourceSon {
    private String sonName;
    private List<PersonSourceComputer> computers;
}

@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
@ToString
public class PersonSource {
    private String firstName;
    private String middleName;
    private String lastName;
    private String email;
    List<PersonSourceSon> son;

}
public class BeanCopyTest {
    private static final Logger logger = LoggerFactory.getLogger(BeanCopyTest.class);
    private static final MapperFactory mapperFactory = new DefaultMapperFactory.Builder().build();

    //static {
    //    mapperFactory.classMap(PersonSource.class, PersonDestination.class).byDefault().register();
    //}

    public static void main(String[] args) {

        for (int i = 1; i < 11; i++) {
            beanCopyTest(i);
        }

    }

    private static void beanCopyTest(int i) {
        PersonSource source = initAndGetPersonSource();

        Stopwatch stopwatch = Stopwatch.createStarted();
        // MapStruct
        PersonDestination destination = PersonMapper.INSTANCE.sourceToDestination(source);
        System.out.println(destination);
        stopwatch.stop();
        logger.info("第" + i + "次" + "MapStruct cost:" + stopwatch.toString());

        // Selma
        stopwatch = Stopwatch.createStarted();
        PersonDestination selmaDestination = SelmaPersonMapper.INSTANCE.sourceToDestination(source);
        System.out.println(selmaDestination);
        stopwatch.stop();
        logger.info("第" + i + "次" + "Selma cost:" + stopwatch.toString());

        // BeanUtils
        stopwatch = Stopwatch.createStarted();
        PersonDestination bUtilsDestination = new PersonDestination();
        BeanUtils.copyProperties(source, bUtilsDestination);
        System.out.println(bUtilsDestination);
        stopwatch.stop();
        logger.info("第" + i + "次" + "BeanUtils cost:" + stopwatch.toString());

        // BeanCopier
        stopwatch = Stopwatch.createStarted();
        BeanCopier beanCopier = BeanCopier.create(PersonSource.class, PersonDestination.class, false);
        PersonDestination bcDestination = new PersonDestination();
        beanCopier.copy(source, bcDestination, null);
        System.out.println(bcDestination);
        stopwatch.stop();
        logger.info("第" + i + "次" + "BeanCopier cost:" + stopwatch.toString());

        // Orika
        stopwatch = Stopwatch.createStarted();
        MapperFacade mapper = mapperFactory.getMapperFacade();
        PersonDestination orikaDestination = mapper.map(source, PersonDestination.class);
        System.out.println(orikaDestination);
        stopwatch.stop();
        logger.info("第" + i + "次" + "Orika cost:" + stopwatch.toString());
    }

    private static PersonSource initAndGetPersonSource() {
        PersonSource source = new PersonSource();
        // set some field values
        source.setFirstName("firstName");
        source.setMiddleName("middleName");
        source.setLastName("lastName");
        source.setEmail("email");
        source.setSon(Lists.newArrayList(new PersonSourceSon(
            "sonName", Lists.newArrayList(new PersonSourceComputer("macBook", BigDecimal.valueOf(15000)))
        )));
        return source;
    }
}

17:56:30.029 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次MapStruct cost:4.179 ms
17:56:30.035 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次Selma cost:2.727 ms
17:56:30.095 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次BeanUtils cost:59.65 ms
17:56:30.139 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次BeanCopier cost:43.52 ms
17:56:30.306 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次Orika cost:167.1 ms
17:56:30.306 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次MapStruct cost:88.97 μs
17:56:30.306 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次Selma cost:36.72 μs
17:56:30.306 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次BeanUtils cost:68.76 μs
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次BeanCopier cost:62.75 μs
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次Orika cost:108.0 μs
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次MapStruct cost:63.29 μs
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次Selma cost:71.12 μs
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次BeanUtils cost:81.64 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次BeanCopier cost:68.01 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次Orika cost:112.4 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次MapStruct cost:54.27 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次Selma cost:37.97 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次BeanUtils cost:124.3 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次BeanCopier cost:124.9 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次Orika cost:107.3 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次MapStruct cost:43.39 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次Selma cost:50.03 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次BeanUtils cost:75.00 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次BeanCopier cost:50.83 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次Orika cost:92.18 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次MapStruct cost:34.60 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次Selma cost:61.26 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次BeanUtils cost:118.6 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次BeanCopier cost:102.7 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次Orika cost:170.5 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次MapStruct cost:65.29 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次Selma cost:52.06 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次BeanUtils cost:86.51 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次BeanCopier cost:101.3 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次Orika cost:119.0 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次MapStruct cost:56.88 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次Selma cost:35.56 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次BeanUtils cost:98.93 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次BeanCopier cost:69.25 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次Orika cost:95.27 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次MapStruct cost:33.60 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次Selma cost:31.90 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次BeanUtils cost:96.19 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次BeanCopier cost:77.15 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次Orika cost:95.17 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次MapStruct cost:45.55 μs
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次Selma cost:32.28 μs
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次BeanUtils cost:62.06 μs
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次BeanCopier cost:46.78 μs
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次Orika cost:113.6 μs

17:56:30.306 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次Orika cost:167.1 ms
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次Orika cost:108.0 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次Orika cost:112.4 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次Orika cost:107.3 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次Orika cost:92.18 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次Orika cost:170.5 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次Orika cost:119.0 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次Orika cost:95.27 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次Orika cost:95.17 μs
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次Orika cost:113.6 μs

17:56:30.029 [main] INFO com.alibaba.beancp.BeanCopyTest - 第1次MapStruct cost:4.179 ms
17:56:30.306 [main] INFO com.alibaba.beancp.BeanCopyTest - 第2次MapStruct cost:88.97 μs
17:56:30.307 [main] INFO com.alibaba.beancp.BeanCopyTest - 第3次MapStruct cost:63.29 μs
17:56:30.308 [main] INFO com.alibaba.beancp.BeanCopyTest - 第4次MapStruct cost:54.27 μs
17:56:30.309 [main] INFO com.alibaba.beancp.BeanCopyTest - 第5次MapStruct cost:43.39 μs
17:56:30.310 [main] INFO com.alibaba.beancp.BeanCopyTest - 第6次MapStruct cost:34.60 μs
17:56:30.311 [main] INFO com.alibaba.beancp.BeanCopyTest - 第7次MapStruct cost:65.29 μs
17:56:30.312 [main] INFO com.alibaba.beancp.BeanCopyTest - 第8次MapStruct cost:56.88 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第9次MapStruct cost:33.60 μs
17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次MapStruct cost:45.55 μs

17:56:30.313 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次MapStruct cost:45.55 μs
PersonDestination(firstName=firstName, middle=middleName, lastName=lastName, email=null, son=[PersonDestinationSon(sonName=sonName, computers=[PersonDestinationComputer(name=macBook, price=15000)])])
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次Selma cost:32.28 μs
PersonDestination(firstName=firstName, middle=null, lastName=lastName, email=email, son=[PersonSourceSon(sonName=sonName, computers=[PersonSourceComputer(name=macBook, price=15000)])])
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次BeanUtils cost:62.06 μs
PersonDestination(firstName=firstName, middle=null, lastName=lastName, email=email, son=[PersonSourceSon(sonName=sonName, computers=[PersonSourceComputer(name=macBook, price=15000)])])
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次BeanCopier cost:46.78 μs
PersonDestination(firstName=firstName, middle=null, lastName=lastName, email=email, son=[PersonDestinationSon(sonName=sonName, computers=[PersonDestinationComputer(name=macBook, price=15000)])])
17:56:30.314 [main] INFO com.alibaba.beancp.BeanCopyTest - 第10次Orika cost:113.6 μs

實(shí)驗(yàn)結(jié)論:

1.不管使用實(shí)驗(yàn)中的哪種框架策肝,在性能上其實(shí)絕對值相差不會太大(非第一次運(yùn)行)肛捍。
2.個(gè)別框架拷貝后引用是PersonSourceSon隐绵,個(gè)別是PersonDestinationSon,說明不同框架在深淺拷貝方案上實(shí)現(xiàn)不同拙毫。
3.有字段名映射氢橙、ignore、格式化等需求時(shí)恬偷,不同框架支持的不同悍手。

總結(jié)

1.在日常開發(fā)中,BeanCopy需求無非是三種

  • 字段相同最簡單的copy
  • 有復(fù)雜性的copy(比如字段名稱不同、有ignore需求袍患、有格式化需求)
  • 有業(yè)務(wù)邏輯的copy

那么針對以上三點(diǎn)坦康,我認(rèn)為

  • 第一種以簡單高效為主,我建議直接使用Orika工具類诡延,實(shí)現(xiàn)非常簡單滞欠,客戶端編碼非常少,基本上就是丟一個(gè)source和target type進(jìn)去即可肆良,保證了深拷貝筛璧,性能上高于Dozer等老產(chǎn)品,并且集合之間拷貝也很優(yōu)秀惹恃。像BeanUtils夭谤、BeanCopier在很多場景表現(xiàn)明顯不如Orika,會有各種問題備受吐槽巫糙。
  • 第二種建議使用功能強(qiáng)大的MapStruct框架朗儒,它的好處呢,就是既生成了代碼参淹,比較直觀方便debug醉锄。又支持非常多且強(qiáng)大的注解,可以輕松做到多層級之間字段映射浙值、字段ignore恳不、日期格式化、金額格式化等开呐。還有mapping模版繼承復(fù)用烟勋、組合等功能。還有就是天然支持Spring注入负蚊,SpringBoot集成等神妹,在這一點(diǎn)上颓哮,相比較Dozer式的xml映射家妆,注解是更符合現(xiàn)代編程方式的。

2.關(guān)于性能的取舍

我們通過性能測試可以發(fā)現(xiàn)冕茅,一旦運(yùn)行過一次之后伤极,上面幾種框架單次copy性能絕對值都非常低(個(gè)別框架主要基于Asm開始的耗時(shí)蛹找、緩存原理、jvm熱代碼優(yōu)化等原因第一次會久一點(diǎn))哨坪。所以性能取舍上的考慮庸疾,主要基于量和系統(tǒng)場景。如果是特別夸張的并發(fā)当编,或者說真的系統(tǒng)到了需要優(yōu)化類庫提升性能的瓶頸上届慈。這種低絕對值之間的相對差距才有意義,因?yàn)閱未沃g的差距是微秒級的忿偷,如果沒有一個(gè)量的乘積放大金顿,是可以忽略性能上的差異。正常大部分公司是沒有這個(gè)需求的鲤桥,沒有必要追求這種極致的性能揍拆,所以考慮的更多是既處于一個(gè)"高性能"表現(xiàn)(絕對值),其它方面讓你很滿意的類庫茶凳。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嫂拴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贮喧,更是在濱河造成了極大的恐慌筒狠,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件箱沦,死亡現(xiàn)場離奇詭異窟蓝,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)饱普,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門运挫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人套耕,你說我怎么就攤上這事谁帕。” “怎么了冯袍?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵匈挖,是天一觀的道長。 經(jīng)常有香客問我康愤,道長儡循,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任征冷,我火速辦了婚禮择膝,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘检激。我一直安慰自己肴捉,他們只是感情好腹侣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著齿穗,像睡著了一般傲隶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窃页,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天跺株,我揣著相機(jī)與錄音,去河邊找鬼脖卖。 笑死帖鸦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的胚嘲。 我是一名探鬼主播作儿,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼馋劈!你這毒婦竟也來了攻锰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤妓雾,失蹤者是張志新(化名)和其女友劉穎娶吞,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體械姻,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妒蛇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了楷拳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绣夺。...
    茶點(diǎn)故事閱讀 38,059評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖欢揖,靈堂內(nèi)的尸體忽然破棺而出陶耍,到底是詐尸還是另有隱情,我是刑警寧澤她混,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布烈钞,位于F島的核電站,受9級特大地震影響坤按,放射性物質(zhì)發(fā)生泄漏毯欣。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一臭脓、第九天 我趴在偏房一處隱蔽的房頂上張望酗钞。 院中可真熱鬧,春花似錦、人聲如沸算吩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偎巢。三九已至,卻和暖如春兼耀,著一層夾襖步出監(jiān)牢的瞬間压昼,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工瘤运, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窍霞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓拯坟,卻偏偏與公主長得像但金,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子郁季,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評論 2 345