范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

废弃fastjson!大型项目迁移Gson保姆级实战

  前言
  大家好,又双叒叕见面了,我是天天放大家鸽子的蛮三刀。
  在被大家取关之前,我立下一个"远大的理想",一定要在这周更新文章。现在看来,flag有用了…
  本篇文章是我这一个多月来帮助组内废弃fastjson框架的总结,我们将大部分Java仓库从fastjson迁移至了Gson。
  这么做的主要的原因是公司受够了fastjson频繁的安全漏洞问题,每一次出现漏洞都要推一次全公司的fastjson强制版本升级,很令公司头疼。
  文章的前半部分,我会简单分析各种json解析框架的优劣,并给出企业级项目迁移json框架的几种解决方案。
  在文章的后半部分,我会结合这一个月的经验,总结下Gson的使用问题,以及fastjson迁移到Gson踩过的深坑。
  文章目录:
  为何要放弃fastjson?
  fastjson替代方案
  三种json框架的特点
  性能对比
  最终选择方案
  替换依赖时的注意事项
  谨慎,谨慎,再谨慎
  做好开发团队和测试团队的沟通
  做好回归/接口测试
  考虑迁移前后的性能差异
  使用Gson替换fastjson
  Json反序列化
  范型处理
  List/Map写入
  驼峰与下划线转换
  迁移常见问题踩坑
  Date序列化方式不同
  SpringBoot异常
  Swagger异常
  @Mapping JsonObject作为入参异常
  注意:是否使用fastjson是近年来一个争议性很大的话题,本文无意讨论框架选型的对错,只关注迁移这件事中遇到的问题进行反思和思考。大家如果有想发表的看法,可以在评论区 理 性 讨论。本文阅读大概需要:5分钟
  码字不易,欢迎关注我的个人公众号:后端技术漫谈(二维码见文章底部)
  为何要放弃fastjson?
  究其原因,是fastjson漏洞频发,导致了公司内部需要频繁的督促各业务线升级fastjson版本,来防止安全问题。
  fastjson在2020年频繁暴露安全漏洞,此漏洞可以绕过autoType开关来实现反序列化远程代码执行并获取服务器访问权限。
  从2019年7月份发布的v1.2.59一直到2020年6月份发布的 v1.2.71 ,每个版本的升级中都有关于AutoType的升级,涉及13个正式版本。
  fastjson中与AutoType相关的版本历史:1.2.59发布,增强AutoType打开时的安全性 fastjson
  1.2.60发布,增加了AutoType黑名单,修复拒绝服务安全问题 fastjson
  1.2.61发布,增加AutoType安全黑名单 fastjson
  1.2.62发布,增加AutoType黑名单、增强日期反序列化和JSONPath fastjson
  1.2.66发布,Bug修复安全加固,并且做安全加固,补充了AutoType黑名单 fastjson
  1.2.67发布,Bug修复安全加固,补充了AutoType黑名单 fastjson
  1.2.68发布,支持GEOJSON,补充了AutoType黑名单
  1.2.69发布,修复新发现高危AutoType开关绕过安全漏洞,补充了AutoType黑名单
  1.2.70发布,提升兼容性,补充了AutoType黑名单
  1.2.71发布,补充安全黑名单,无新增利用,预防性补充
  相比之下,其他的json框架,如Gson和Jackson,漏洞数量少很多,高危漏洞也比较少,这是公司想要替换框架的主要原因。
  fastjson替代方案
  本文主要讨论Gson替换fastjson框架的实战问题,所以在这里不展开详细讨论各种json框架的优劣,只给出结论。
  经过评估,主要有Jackson和Gson两种json框架放入考虑范围内,与fastjson进行对比。
  三种json框架的特点FastJson速度快
  fastjson相对其他JSON库的特点是快,从2011年fastjson发布1.1.x版本之后,其性能从未被其他Java实现的JSON库超越。
  使用广泛
  fastjson在阿里巴巴大规模使用,在数万台服务器上部署,fastjson在业界被广泛接受。在2012年被开源中国评选为最受欢迎的国产开源软件之一。
  测试完备
  fastjson有非常多的testcase,在1.2.11版本中,testcase超过3321个。每次发布都会进行回归测试,保证质量稳定。
  使用简单
  fastjson的API十分简洁。
  Jackson容易使用 - jackson API提供了一个高层次外观,以简化常用的用例。
  无需创建映射 - API提供了默认的映射大部分对象序列化。
  性能高 - 快速,低内存占用,适合大型对象图表或系统。
  干净的JSON - jackson创建一个干净和紧凑的JSON结果,这是让人很容易阅读。
  不依赖 - 库不需要任何其他的库,除了JDK。
  Gson提供一种机制,使得将Java对象转换为JSON或相反如使用toString以及构造器(工厂方法)一样简单。
  允许预先存在的不可变的对象转换为JSON或与之相反。
  允许自定义对象的表现形式
  支持任意复杂的对象
  输出轻量易读的JSON
  性能对比
  同事撰写的性能对比源码:
  https://github.com/zysrxx/json-comparison
  本文不详细讨论性能的差异,毕竟这其中涉及了很多各个框架的实现思路和优化,所以只给出结论:1.序列化单对象性能Fastjson > Jackson > Gson,其中Fastjson和Jackson性能差距很小,Gson性能较差
  2.序列化大对象性能Jackson> Fastjson > Gson ,序列化大Json对象时Jackson> Gson > Fastjson,Jackson序列化大数据时性能优势明显
  3.反序列化单对象性能 Fastjson > Jackson > Gson , 性能差距较小
  4.反序列化大对象性能 Fastjson > Jackson > Gson , 性能差距较很小
  最终选择方案
  Jackson适用于高性能场景,Gson适用于高安全性场景
  对于新项目仓库,不再使用fastjson。对于存量系统,考虑到Json更换成本,由以下几种方案可选:
  项目未使用autoType功能,建议直接切换为非fastjson,如果切换成本较大,可以考虑继续使用fastjson,关闭safemode。
  业务使用了autoType功能,建议推进废弃fastjson。
  替换依赖注意事项
  企业项目或者说大型项目的特点:
  代码结构复杂,团队多人维护。
  承担重要线上业务,一旦出现严重bug会导致重大事故。
  如果是老项目,可能缺少文档,不能随意修改,牵一发而动全身。
  项目有很多开发分支,不断在迭代上线。
  所以对于大型项目,想要做到将底层的fastjson迁移到gson是一件复杂且痛苦的事情,其实对于其他依赖的替换,也都一样。
  我总结了如下几个在替换项目依赖过程中要特别重视的问题。
  谨慎,谨慎,再谨慎
  再怎么谨慎都不为过,如果你要更改的项目是非常重要的业务,那么一旦犯下错误,代价是非常大的。并且,对于业务方和产品团队来说,没有新的功能上线,但是系统却炸了,是一件"无法忍受"的事情。尽管你可能觉得很委屈,因为只有你或者你的团队知道,虽然业务看上去没变化,但是代码底层已经发生了翻天覆地的变化。
  所以,谨慎点!
  做好开发团队和测试团队的沟通
  在依赖替换的过程中,需要做好项目的规划,比如分模块替换,严格细分排期。
  把前期规划做好,开发和测试才能有条不紊的进行工作。
  开发之间,需要提前沟通好开发注意事项,比如依赖版本问题,防止由多个开发同时修改代码,最后发现使用的版本不同,接口用法都不同这种很尴尬,并且要花额外时间处理的事情。
  而对于测试,更要事先沟通好。一般来说,测试不会太在意这种对于业务没有变化的技术项目,因为既不是优化速度,也不是新功能。但其实迁移涉及到了底层,很容易就出现BUG。要让测试团队了解更换项目依赖,是需要大量的测试时间投入的,成本不亚于新功能,让他们尽量重视起来。
  做好回归/接口测试
  上面说到测试团队需要投入大量工时,这些工时主要都用在项目功能的整体回归上,也就是回归测试。
  当然,不只是业务回归测试,如果有条件的话,要做接口回归测试。
  如果公司有接口管理平台,那么可以极大提高这种项目测试的效率。
  打个比方,在一个模块修改完成后,在测试环境(或者沙箱环境),部署一个线上版本,部署一个修改后的版本,直接将接口返回数据进行对比。一般来说是Json对比,网上也有很多的Json对比工具:
  https://www.sojson.com/
  考虑迁移前后的性能差异
  正如上面描述的Gson和Fastjson性能对比,替换框架需要注意框架之间的性能差异,尤其是对于流量业务,也就是高并发项目,响应时间如果发生很大的变化会引起上下游的注意,导致一些额外的后果。
  使用Gson替换Fastjson
  这里总结了两种json框架常用的方法,贴出详细的代码示例,帮助大家快速的上手Gson,无缝切换!
  Json反序列化String jsonCase = "[{"id":10001,"date":1609316794600,"name":"小明"},{"id":10002,"date":1609316794600,"name":"小李"}]";
  // fastjson
  JSONArray jsonArray = JSON.parseArray(jsonCase);
  System.out.println(jsonArray);
  System.out.println(jsonArray.getJSONObject(0).getString("name"));
  System.out.println(jsonArray.getJSONObject(1).getString("name"));
  // 输出:
  // [{"date":1609316794600,"name":"小明","id":10001},{"date":1609316794600,"name":"小李","id":10002}]
  // 小明
  // 小李
  // Gson
  JsonArray jsonArrayGson = gson.fromJson(jsonCase, JsonArray.class);
  System.out.println(jsonArrayGson);
  System.out.println(jsonArrayGson.get(0).getAsJsonObject.get("name").getAsString);
  System.out.println(jsonArrayGson.get(1).getAsJsonObject.get("name").getAsString);
  // 输出:
  // [{"id":10001,"date":1609316794600,"name":"小明"},{"id":10002,"date":1609316794600,"name":"小李"}]
  // 小明
  // 小李
  看得出,两者区别主要在get各种类型上,Gson调用方法有所改变,但是变化不大。
  那么,来看下空对象反序列化会不会出现异常:String jsonObjectEmptyCase = "{}";
  // fastjson
  JSONObject jsonObjectEmpty = JSON.parseObject(jsonObjectEmptyCase);
  System.out.println(jsonObjectEmpty);
  System.out.println(jsonObjectEmpty.size);
  // 输出:
  // {}
  // 0
  // Gson
  JsonObject jsonObjectGsonEmpty = gson.fromJson(jsonObjectEmptyCase, JsonObject.class);
  System.out.println(jsonObjectGsonEmpty);
  System.out.println(jsonObjectGsonEmpty.size);
  // 输出:
  // {}
  // 0
  没有异常,开心。
  看看空数组呢,毕竟感觉比{}更加容易出错。String jsonArrayEmptyCase = "";
  // fastjson
  JSONArray jsonArrayEmpty = JSON.parseArray(jsonArrayEmptyCase);
  System.out.println(jsonArrayEmpty);
  System.out.println(jsonArrayEmpty.size);
  // 输出:
  //
  // 0
  // Gson
  JsonArray jsonArrayGsonEmpty = gson.fromJson(jsonArrayEmptyCase, JsonArray.class);
  System.out.println(jsonArrayGsonEmpty);
  System.out.println(jsonArrayGsonEmpty.size);
  // 输出:
  //
  // 0
  两个框架也都没有问题,完美解析。
  范型处理
  解析泛型是一个非常常用的功能,我们项目中大部分fastjson代码就是在解析json和Java Bean。// 实体类
  User user = new User;
  user.setId(1L);
  user.setUserName("马云");
  // fastjson
  List userListResultFastjson = JSONArray.parseArray(JSON.toJSONString(userList), User.class);
  List userListResultFastjson2 = JSON.parseObject(JSON.toJSONString(userList), new TypeReference>{});
  System.out.println(userListResultFastjson);
  System.out.println("userListResultFastjson2" + userListResultFastjson2);
  // 输出:
  // userListResultFastjson[User [Hash = 483422889, id=1, userName=马云], ]
  // userListResultFastjson2[User [Hash = 488970385, id=1, userName=马云], ]
  // Gson
  List userListResultTrue = gson.fromJson(gson.toJson(userList), new TypeToken>{}.getType);
  System.out.println("userListResultGson" + userListResultGson);
  // 输出:
  // userListResultGson[User [Hash = 1435804085, id=1, userName=马云], ]
  可以看出,Gson也能支持泛型。
  List/Map写入
  这一点fastjson和Gson有区别,Gson不支持直接将List写入value,而fastjson支持。
  所以Gson只能将List解析后,写入value中,详见如下代码:// 实体类
  User user = new User;
  user.setId(1L);
  user.setUserName("马云");
  // fastjson
  JSONObject jsonObject1 = new JSONObject;
  jsonObject1.put("user", user);
  jsonObject1.put("userList", userList);
  System.out.println(jsonObject1);
  // 输出:
  // {"userList":[{"id":1,"userName":"马云"},],"user":{"id":1,"userName":"马云"}}
  // Gson
  JsonObject jsonObject = new JsonObject;
  jsonObject.add("user", gson.toJsonTree(user));
  System.out.println(jsonObject);
  // 输出:
  // {"user":{"id":1,"userName":"马云"},"userList":[{"id":1,"userName":"马云"},]}
  如此一来,Gson看起来就没有fastjson方便,因为放入List是以gson.toJsonTree(user)的形式放入的。这样就不能先入对象,在后面修改该对象了。(有些同学比较习惯先放入对象,再修改对象,这样的代码就得改动)
  驼峰与下划线转换
  驼峰转换下划线依靠的是修改Gson的序列化模式,修改为LOWER_CASE_WITH_UNDERSCORESGsonBuilder gsonBuilder = new GsonBuilder;
  gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
  Gson gsonUnderScore = gsonBuilder.create;
  System.out.println(gsonUnderScore.toJson(user));
  // 输出:
  // {"id":1,"user_name":"马云"}
  常见问题排雷
  下面整理了我们在公司项目迁移Gson过程中,踩过的坑,这些坑现在写起来感觉没什么技术含量。但是这才是我写这篇文章的初衷,帮助大家把这些很难发现的坑避开。
  这些问题有的是在测试进行回归测试的时候发现的,有的是在自测的时候发现的,有的是在上线后发现的,比如Swagger挂了这种不会去测到的问题。
  Date序列化方式不同
  不知道大家想过一个问题没有,如果你的项目里有缓存系统,使用fastjson写入的缓存,在你切换Gson后,需要用Gson解析出来。所以就一定要保证两个框架解析逻辑是相同的,但是,显然这个愿望是美好的。
  在测试过程中,发现了Date类型,在两个框架里解析是不同的方式。
  fastjson:Date直接解析为Unix
  Gson:直接序列化为标准格式Date
  导致了Gson在反序列化这个json的时候,直接报错,无法转换为Date。
  解决方案:
  新建一个专门用于解析Date类型的类:import com.google.gson.TypeAdapter;
  import com.google.gson.stream.JsonReader;
  import com.google.gson.stream.JsonWriter;
  import java.io.IOException;
  import java.util.Date;
  public class MyDateTypeAdapter extends TypeAdapter {
  @Override
  public void write(JsonWriter out, Date value) throws IOException {
  if (value == ) {
  out.Value;
  } else {
  out.value(value.getTime);
  }
  }
  @Override
  public Date read(JsonReader in) throws IOException {
  if (in != ) {
  return new Date(in.nextLong);
  } else {
  return ;
  }
  }
  }
  接着,在创建Gson时,把他放入作为Date的专用处理类:Gson gson = new GsonBuilder.registerTypeAdapter(Date.class,new MyDateTypeAdapter).create;
  这样就可以让Gson将Date处理为Unix。
  当然,这只是为了兼容老的缓存,如果你觉得你的仓库没有这方面的顾虑,可以忽略这个问题。
  SpringBoot异常
  切换到Gson后,使用SpringBoot搭建的Web项目的接口直接请求不了了。报错类似:org.springframework.http.converter.HttpMessageNotWritableException
  因为SpringBoot默认的Mapper是Jackson解析,我们切换为了Gson作为返回对象后,Jackson解析不了了。
  解决方案:
  application.properties里面添加:#Preferred JSON mapper to use for HTTP message conversion
  spring.mvc.converters.preferred-json-mapper=gson
  Swagger异常
  这个问题和上面的SpringBoot异常类似,是因为在SpringBoot中引入了Gson,导致 swagger 无法解析 json。
  采用类似下文的解决方案(添加Gson适配器):
  http://yuyublog.top/2018/09/03/springboot%E5%BC%95%E5%85%A5swagger/
  GsonSwaggerConfig.java@Configuration
  public class GsonSwaggerConfig {
  //设置swagger支持gson
  @Bean
  public IGsonHttpMessageConverter IGsonHttpMessageConverter {
  return new IGsonHttpMessageConverter;
  }
  }
  IGsonHttpMessageConverter.javapublic class IGsonHttpMessageConverter extends GsonHttpMessageConverter {
  public IGsonHttpMessageConverter {
  //自定义Gson适配器
  super.setGson(new GsonBuilder
  .registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter)
  .serializes//空值也参与序列化
  .create);
  }
  }
  SpringfoxJsonToGsonAdapter.javapublic class SpringfoxJsonToGsonAdapter implements JsonSerializer {
  @Override
  public JsonElement serialize(Json json, Type type, JsonSerializationContext jsonSerializationContext) {
  return new JsonParser.parse(json.value);
  }
  }
  @Mapping JsonObject作为入参异常
  有时候,我们会在入参使用类似:public ResponseResult submitAudit(@RequestBody JsonObject jsonObject) {}
  如果使用这种代码,其实就是使用Gson来解析json字符串。但是这种写法的风险是很高的,平常请大家尽量避免使用JsonObject直接接受参数。
  在Gson中,JsonObject若是有数字字段,会统一序列化为double,也就是会把count = 0这种序列化成count = 0.0。
  为何会有这种情况?简单的来说就是Gson在将json解析为Object类型时,会默认将数字类型使用double转换。
  如果Json对应的是Object类型,最终会解析为Map类型;其中Object类型跟Json中具体的值有关,比如双引号的""值翻译为STRING。我们可以看下数值类型(NUMBER)全部转换为了Double类型,所以就有了我们之前的问题,整型数据被翻译为了Double类型,比如30变为了30.0。
  可以看下Gson的ObjectTypeAdaptor类,它继承了Gson的TypeAdaptor抽象类:
  具体的源码分析和原理阐述,大家可以看这篇拓展阅读:
  https://www.jianshu.com/p/eafce9689e7d
  解决方案:
  第一个方案:把入参用实体类接收,不要使用JsonObject
  第二个方案:与上面的解决Date类型问题类似,自己定义一个Adaptor,来接受数字,并且处理。这种想法我觉得可行但是难度较大,可能会影响到别的类型的解析,需要在设计适配器的时候格外注意。
  总结
  这篇文章主要是为了那些需要将项目迁移到Gson框架的同学们准备的。
  一般来说,个人小项目,是不需要费这么大精力去做迁移,所以这篇文章可能目标人群比较狭窄。
  但文章中也提到了不少通用问题的解决思路,比如怎么评估迁移框架的必要性。其中需要考虑到框架兼容性,两者性能差异,迁移耗费的工时等很多问题。
  希望文章对你有所帮助。
  参考
  《如何从Fastjson迁移到Gson》
  https://juejin.im/post/6844904089281626120
  《FastJson迁移至Jackson》此文作者自己封装了工具类来完成迁移
  https://mxcall.github.io/posts/%E5%B7%A5%E4%BD%9C/%E7%A8%8B%E5%BA%8F%E5%91%98/javaSE/FastJson%E8%BF%81%E7%A7%BB%E8%87%B3Jackson/
  《你真的会用Gson吗?Gson使用指南》
  https://www.jianshu.com/p/e740196225a4
  json性能对比
  https://github.com/zysrxx/json-comparison/tree/master/src/main/java/json/comparison
  fastjson官方文档
  https://github.com/alibaba/fastjson/wiki
  易百教程
  https://www.yiibai.com/jackson
  关注我
  我是一名奋斗在一线的互联网后端开发工程师。
  主要关注后端开发,数据安全,边缘计算等方向,欢迎交流。
  各大平台都能找到我
  微信公众号:后端技术漫谈
  Github:@qqxx6661
  CSDN:@蛮三刀把刀
  知乎:@后端技术漫谈
  掘金:@蛮三刀把刀
  腾讯云+社区:@后端技术漫谈
  博客园:@后端技术漫谈
  BiliBili:@蛮三刀把刀
  原创文章主要内容
  后端开发实战(Java为主)
  技术面试
  算法题解/数据结构/设计模式
  我的生活趣事
  个人公众号:后端技术漫谈

科学家探究发现吸烟与新生儿男女比例有关最近,科学家探究出了一些影响生儿育女的外部条件。据丹麦和日本几位科学家进行的一项调查发现,想要生下男孩的夫妇最好不要吸烟,这些科学家表示,那些在孕育下一代期间仍然吸烟的夫妇得到男孩有的孩子越长越丑,有的孩子越长越好看,有迹可循,父母可干涉我是一个全职妈妈,一个不断实现自我价值的全职妈妈。拒绝焦虑,拒绝内卷,轻松育儿,理性对待婚姻生活,宽容应对婆媳关系,希望我的一些观点能够让你豁然开朗,能够带给你正能量,解决你的现实牛姓男子给二胎取名牛成群,妻子不满意要改名牛姓男子给二胎取名牛成群,妻子不满意要改名,她说这是老公擅自做主取的名,她还说她已经想好了名字。夫妻两个人为了取名也是吵架了很多次。夫妻孩子的出生证上显示,哥哥名叫牛犇犇,父亲就想如何布局文昌位去催旺孩子的学业现代社会科技领先,读书为尚,望子成龙,望女成凤是每个做父母的理想,在未成龙之前,必先有好学业。好的学业,除了要具备先天的资质外,后天的培养亦是相当重要。购买房屋,都得考虑儿女读书之长大后能挣大钱的孩子,小时候就有这三个特征,你家娃占几个追求创造财富是我们的权利,没有人愿意一贫如洗,过着拮据的生活,有足够的金钱,我们可以生活得更好,也可以帮助更多的人,捐助慈善等等,更好地为社会服务。大部分父母还是希望孩子长大后能够亲子阅读儿童文学儒林外史(下)每个人都是自己的老师!作者大大长期更新文章,愿阅读可以点亮每个人的生活。点击阅读全文,获取作者更多文章。今天我们接着分享吴敬梓的儒林外史。之前我们曾经分享过,在儒林外史这本书里,作幼儿园识字与不识字的娃,上小学后,4方面的差距会很大文开心果妈妈(原创文章,欢迎个人转载分享)你家娃在上幼儿园的时候,有没有教她识字呢?果妈的一个亲戚,娃在上幼儿园的时候,学校不教识字。亲戚觉得,学校这样做是有道理的,不要超前教育,解决孩子写作业拖延的绝招(百试百灵)1。家长在旁边看书,营造学习氛围。试想如果你在旁边玩游戏玩手机孩子肯定会分心。2。平静的说孩子,学习是你自己的事。你要对你自己负责,如果你不想写,你明天自己去跟老师解释3。如果孩子身残意志坚定,我们要把孩子培育成坚强的好男孩当他一出生时,腿就是畸形。医学上称为先天性骶骨发育不全。他没有肛门(医生只好给他割了道深口,让他能痛苦地排便),而且他的膀胱和肠也不正常。由于腿部完全没有发育,刚刚出生的小约翰看起钢琴学多久买琴比较好?我的建议是条件允许的情况下一学琴就买钢琴。第一可以节省很多时间成本,比如往返琴行的时间,如果你家里有琴,这些时间都可以用来练习。第二杜绝放弃的诱惑,比如天太冷天太热下大雨手指疼等客自律就是克制自从用电脑手机来辅助学习之后,感觉电子产品为我打开了一扇新世界的大门。它们的功能太强大了,让我很容易就着迷了,甚至顾不上学习吃饭和睡觉。因为这个,还经常跟爸爸妈妈发生争执,我也意识
写妓女感动千万人她的爱情不下流,反而让人觉得纯洁高贵让我落泪的一本书叫茶花女,这也是我最喜欢的一部西方小说之一,那是在七八年前了读的吧,自己还是一个单纯青涩的学生。这部书感染力太强了,我看了第一章节,便忍不住读下去,每每读到让人感动成都海王被曝,拿高仿lv勾引十几个美女上床,屡试不爽小倩是重庆人,今年25岁,在成都一家上市公司做平面设计师,月薪8k,喜欢电影,逛街,买奢侈品,酒吧蹦迪。正是因为小倩喜欢奢侈品,让她的命运和海王有了交集。半年前,小倩看上了一款Ch感动她77次又一部狗血爱情片,观众说看到一半吐了继你的婚礼骗了观众一把眼泪后,由陈柏豪与蔡卓妍主要的电影感动她77次上映,5。14日上映首日票房1000万多一点点,第二天便少了几倍票房。目前为止,今天只有299万票房。第一天排片外卖小哥工作多年后高考623分被社会毒打过,才懂读书好处2013年,湖北襄阳的王威考上了中国农业大学,报考专业是食品科学与工程专业。但是刚入学第一年他就想退学,北京与襄阳,南北差异大,不论是气候环境还是生活习惯他都不适应。但考上一所大学怎样让男人越来越爱你?学会爱情3计,刺激他的主动性女人学会这3点,就会让男人更加爱你,别不信前言爱情是一件很奇妙的事情,我们原本对另一半有很多要求,比如长相身材工作学历等等,但是往往在一些时候我们喜欢上一个人只是一瞬间的事情,这时爱情中,无论男人多爱你,女人也要牢牢守住这3张底牌男人再爱你,也要保留这些底牌,不然自讨没趣前言一段感情中往往爱的越深最后会被伤害的越深,一个人在一段感情中付出得太多就会慢慢变得不平等,最后被伤害的人也是最惨的,慢慢感情失去了平衡13张花絮照片菲律宾贫民窟的孩子,廉价手机拍出大片效果来自菲律宾的CijanCimagala证明,你不需要昂贵的设备也可拍出精美的照片。这位脑洞大开的摄影爱好者仅使用普通的家用物品,成本几乎为0的拍摄出这些照片,并获得了如此出色的图像越南这样收获百合花,全靠洪水来帮忙,每一张照片都是一道风景越南摄影师TrungHuyPham将自然与文化和传统融为一体,创作了一系列引人入胜的题为LiliesHarvest的照片。这些照片纪录了湄公河三角洲,当地人正忙着收集五颜六色的百合20张冠状病毒幸存者照片,硬汉确诊6周后,根本看不出是同一人2020年是艰难的一年,但还远远没有结束,全人类正经一个又一个的严峻的里程碑。目前,全球有超过3360万例确诊的Covid19病例,有超100万例与冠状病毒相关的死亡。但是,人类仍14张罕见奥黛丽赫本剧照卖出天价,女神也有缺点,侧面看得出20日,由奥黛丽赫本(AudreyHepburn)主演的2部电影中的罕见剧照已经以6,000英镑的价格出售。这14张照片是这位传奇的英国女演员,在1956年拍摄的战争与和平以及三年英国老太太50岁才ampampquot认真ampampquot开始画画,这水平,早点认真就没谁了人们只要做自己喜欢的事情,任何时候都不会晚。英国一位半退休的艺术家范妮菲尔丁(FannyFielding),50几岁才开始认真的画画,但在短短的几年中,她不仅创办了她的个人网站,还