项目框架图

分布式基础概念

• 微服务、注册中心、配置中心、远程调用、Feign、网关
• 2、基础开发
• SpringBoot2.0、SpringCloud、Mybatis-Plus、Vue组件化、阿里云对象存储
• 3、环境
• Vagrant、Linux、Docker、MySQL、Redis、逆向工程&人人开源
• 4、开发规范
• 数据校验JSR303、全局异常处理、全局统一返回、全局跨域处理
• 枚举状态、业务状态码、VO与TO与PO划分、逻辑删除
• Lombok:@Data、@Slf4j

前情提要

本项目全部都采用了最新配置,和视频版本不一样。报错改了好久。

技巧

将一个实体的值复制到另一个实体,不需要单独一个个get,set了
BeanUtils.copyProperties(attr,attrEntity);

大数据情况下不建议联表查询,笛卡尔积,应分开查询

日期格式化 统一设置
spring
jackson:
date-format: yyyy-MM-dd HH:mm:ss

ge >=
gt >
le <=

如果传过来的数据可能为空,用包装类

对于不重要查询失败错误,不要回滚事务,直接trycatch不进行处理

对于部分数据可能有取消原有信息的处理:直接先全部删除所有数据,再依次添加新数据,不用依次判断是否删除数据。

parentPath.toArray(new Long[0]);
区别(new Long[])parentPath.toArray()

循环查库
循环依赖

复杂的json网上可以直接生成java实体类 bejson.com

stream.map和ForEach区别

BigDecimal的比较
skuReductionTo.getFullPrice().compareTo(new BigDecimal(“0”)) == 1

  • 排除数据源相关的配置
    @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

  • 熟悉流式编程
    过滤、排序、统计分组
    多线程高效

Lambda 表达式中访问的局部变量不能为变量

        Long purchaseId = mergeVo.getPurchaseId();if(purchaseId == null){//...purchaseId = purchaseEntity.getId();}Long finalPurchaseId = purchaseId;
  • 这里finalPurchaseId和purchaseId没区别,final是因为lambda表达式的机制要求使用的局部变量不能为变量
  • Java 8 之后,在匿名类或 Lambda 表达式中访问的局部变量,如果不是 final 类型的话,编译器自动加上 final 修饰符,即Java8新特性:effectively final

配置

  • 设置容器自动启动
    docker update redis --restart=always

  • linux的mysql和docker中的mysql端口碰撞
    3306: bind: address already in use
    netstat -tanlp # 查看所有已被占用端口和所在进程ID
    kill 101427 # 杀死当前进程

  • ctrl+alt+shift+u 查看Pom依赖冲突

整合MyBatis-Plus

需要看文档熟悉

1)、导入依赖

<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.2.0</version>
</dependency>

2)、配置
1、配置数据源;
1)、导入数据库的驱动。https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-versions.html
2)、在application.yml配置数据源相关信息
2、配置MyBatis-Plus;
1)、使用@MapperScan
2)、告诉MyBatis-Plus,sql映射文件位置

service中不需要手动注入dao

public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity>//继承的ServiceImpl已经自动注入了baseMapper就是CategoryDao
public class ServiceImpl<M extends BaseMapper<T>, T> implements IService<T> {protected Log log = LogFactory.getLog(this.getClass());@Autowiredprotected M baseMapper;

自定义属性

@TableField(exist = false)
private List childrean;

只有当该字段不为空时,才返回

@JsonInclude(JsonInclude.Include.NON_EMPTY)
应用场景:三级分类最后一个分类的子分类children字段不需要置为空,而是直接不需要

逻辑删除

1)、配置全局的逻辑删除规则(省略)

 mybatis-plus:mapper-locations: classpath:/mapper/**/*.xmlglobal-config:db-config:id-type: autologic-delete-value: 1logic-not-delete-value: 0

2)、配置逻辑删除的组件Bean(低版本)
3)、给Bean加上逻辑删除注解@TableLogic

批量删除

<delete id="deleteBatchRelation">DELETE FROM `pms_attr_attrgroup_relation` WHERE<foreach collection="entities" item="item" separator=" OR ">(attr_id=#{item.attrId} AND attr_group_id=#{item.attrGroupId})</foreach></delete>

非自增主键

public enum IdType {//数据库ID自增AUTO(0),// 该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT)NONE(1),//用户输入ID:该类型可以通过自己注册自动填充插件进行填充INPUT(2),@TableId(type = IdType.INPUT)
private Long spuId;

springcloud

结合 SpringCloud Alibaba 我们最终的技术搭配方案:
SpringCloud Alibaba - Nacos:注册中心(服务发现/注册)
SpringCloud Alibaba - Nacos:配置中心(动态配置管理)
SpringCloud - Ribbon:负载均衡
SpringCloud - Feign:声明式 HTTP 客户端(调用远程服务)
SpringCloud Alibaba - Sentinel:服务容错(限流、降级、熔断)
SpringCloud - Gateway:API 网关(webflux 编程模式)
SpringCloud - Sleuth:调用链监控
SpringCloud Alibaba - Seata:原 Fescar,即分布式事务解决方案

feign

1、想要远程调用别的服务
1)、引入open-feign

        <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>//一定要加<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-loadbalancer</artifactId></dependency>

2)、编写一个接口,告诉SpringCloud这个接口需要调用远程服务
1、声明接口的每一个方法都是调用哪个远程服务的那个请求

@FeignClient("gulimall-coupon")
public interface CouponFeignService {@GetMapping("/coupon/coupon/member/list") //地址要写全public R memberCoupons();
}

3)、开启远程调用功能
@EnableFeignClients(basePackages = “com.vinson.gulimall.member.feign”)

两种请求模式

1)、让所有请求过网关;
1、@FeignClient(“gulimall-gateway”):给gulimall-gateway所在的机器发请求
2、/api/product/skuinfo/info/{skuId}
2)、直接让后台指定服务处理
1、@FeignClient(“gulimall-product”)
2、/product/skuinfo/info/{skuId}

实体类无需一致

1、CouponFeignService.saveSpuBounds(spuBoundTo);
1)、@RequestBody将这个对象转为json。
2)、找到gulimall-coupon服务,给/coupon/spubounds/save发送请求。
将上一步转的json放在请求体位置,发送请求;
3)、对方服务收到请求。请求体里有json数据。
(@RequestBody SpuBoundsEntity spuBounds);将请求体的json转为SpuBoundsEntity;
只要json数据模型是兼容的。双方服务无需使用同一个to

Nacos

使用

1)、引入依赖,

 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency>//一定要加<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-bootstrap</artifactId></dependency>

2)、创建一个bootstrap.properties。
spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848
3)、需要给配置中心默认添加一个叫 数据集(Data Id)gulimall-coupon.properties。默认规则,应用名.properties
4)、给 应用名.properties 添加任何配置
5)、动态获取配置。
@RefreshScope:动态获取并刷新配置
@Value(“${配置项的名}”):获取到配置。
如果配置中心和当前应用的配置文件中都配置了相同的项,优先使用配置中心的配置。

细节

1)、命名空间:配置隔离;
默认:public(保留空间);默认新增的所有配置都在public空间。
1、开发,测试,生产:利用命名空间来做环境隔离。
注意:在bootstrap.properties;配置上,需要使用哪个命名空间下的配置,
spring.cloud.nacos.config.namespace=9de62e44-cd2a-4a82-bf5c-95878bd5e871
2、每一个微服务之间互相隔离配置,每一个微服务都创建自己的命名空间,只加载自己命名空间下的所有配置

2)、配置集:所有的配置的集合

3)、配置集ID:类似文件名。
Data ID:类似文件名

4)、配置分组:
默认所有的配置集都属于:DEFAULT_GROUP;
1111,618,1212
spring.cloud.nacos.config.group=1111

项目中的使用:每个微服务创建自己的命名空间,使用配置分组区分环境,dev,test,prod

3、同时加载多个配置集
1)、微服务任何配置信息,任何配置文件都可以放在配置中心中
2)、只需要在bootstrap.properties说明加载配置中心中哪些配置文件即可
3)、@Value,@ConfigurationProperties。。。
以前SpringBoot任何方法从配置文件中获取值,都能使用。
配置中心有的优先使用配置中心中的,

spring.application.name=gulimall-coupon
spring.cloud.nacos.config.server-addr=127.0.0.1:8848spring.cloud.nacos.config.namespace=d5c78392-5fd3-4737-ab6e-3d3038f7bd82
# 默认的配置分组
spring.cloud.nacos.config.group=prodspring.cloud.nacos.config.extension-configs[0].data-id=datasource.yml
spring.cloud.nacos.config.extension-configs[0].group=dev
spring.cloud.nacos.config.extension-configs[0].refresh=truespring.cloud.nacos.config.extension-configs[1].data-id=mybatis.yml
spring.cloud.nacos.config.extension-configs[1].group=dev
spring.cloud.nacos.config.extension-configs[1].refresh=truespring.cloud.nacos.config.extension-configs[2].data-id=other.yml
spring.cloud.nacos.config.extension-configs[2].group=dev
spring.cloud.nacos.config.extension-configs[2].refresh=true

网关

将renren-fast加入到注册中心,需要加cloud配置,一定要和原Boot版本对应!!!
http://localhost:88/api/captcha.jpg
http://localhost:8080/renren-fast/captcha.jpg
http://localhost:88/api/product/category/list/tree
http://localhost:10000/product/category/list/tree
通过过滤方法中的路径转换功能

  • 需要注意的是路由的顺序是由上至下,精确的应该放上面,粗略的放下面
  • 新版的路径需要加个?
  • 并且加上Loadbalancer依赖,版本一定要和cloud,boot对应!!!

    org.springframework.cloud
    spring-cloud-starter-loadbalancer
    3.1.1

spring:cloud:gateway:discovery:locator:enabled: true #开启从注册中心动态创建路由的功能,利用微服务名进行路由routes:- id: product_routeuri: lb://gulimall-productpredicates:- Path=/api/product/**filters:- RewritePath=/api/?(?<segment>.*),/$\{segment}- id: admin_routeuri: lb://renren-fastpredicates:- Path=/api/**filters:- RewritePath=/api/?(?<segment>.*),/renren-fast/$\{segment}

跨域

跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是
浏览器对javascript施加的安全限制。
• 同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;

使用nginx部署为同一域

不适合开发阶段

配置当次请求允许跨域

1、添加响应头
Access-Control-Allow-Origin:支持哪些来源的请求跨域
Access-Control-Allow-Methods:支持哪些方法跨域
Access-Control-Allow-Credentials:跨域请求默认不包含cookie,设置为true可以包含
cookie
Access-Control-Expose-Headers:跨域请求暴露的字段
CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:
Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
Access-Control-Max-Age:表明该响应的有效时间为多少秒。在有效时间内,浏览器无须为同一请求再次发起预检请求。请注意,浏览器自身维护了一个最大有效时间,如果该首部字段的值超过了最大有效时间,将不会生效。

@Configuration
public class GuliCorsConfiguration {@Beanpublic CorsWebFilter corsWebFilter(){UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");corsConfiguration.addAllowedOriginPattern("*");corsConfiguration.setAllowCredentials(true);source.registerCorsConfiguration("/**",corsConfiguration);return new CorsWebFilter(source);}
}

@RequestBody:获取请求体,必须发送POST请求
SpringMVC自动将请求体的数据(json),转为对应的对象

文件存储

阿里云的对象存储

普通上传方式

用户经服务器上传,会影响带宽,加大压力

服务端签名后直传

看官网
1、引入oss-starter
2、配置key,endpoint相关信息即可
3、使用OSSClient 进行相关操作

JSR303数据校验

1)、给Bean添加校验注解:javax.validation.constraints,并定义自己的message提示
@NotBlank(message = “品牌名必须提交”)
2)、开启校验功能@Valid
public R save(@Valid @RequestBody BrandEntity brand){
效果:校验错误以后会有默认的响应;
3)、给校验的bean后紧跟一个BindingResult,就可以获取到校验的结果
4)、分组校验(多场景的复杂校验)
1)、 @NotBlank(message = “品牌名必须提交”,groups = {AddGroup.class,UpdateGroup.class})
给校验注解标注什么情况需要进行校验
2)、@Validated({AddGroup.class})
3)、默认没有指定分组的校验注解@NotBlank,在分组校验情况@Validated({AddGroup.class})下不生效,只会在@Validated生效;

5)、自定义校验
1)、编写一个自定义的校验注解
2)、编写一个自定义的校验器 ConstraintValidator
3)、关联自定义的校验器和自定义的校验注解
看源码实现自定义,找格式搬

@Documented
//可以指定多个不同的校验器,适配不同类型的校验
@Constraint(validatedBy = {ListValueConstraintValidator.class}
)
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ListValue {String message() default "{com.vinson.common.validator.group.ListValue.message}";Class<?>[] groups() default {};Class<? extends Payload>[] payload() default {};int[] vals() default {};
}
public class ListValueConstraintValidator implements ConstraintValidator<ListValue,Integer> {private Set<Integer> set=new HashSet<>();//初始化@Overridepublic void initialize(ListValue listValue) {int[] vals = listValue.vals();for (int val : vals) {set.add(val);}}//校验@Overridepublic boolean isValid(Integer integer, ConstraintValidatorContext constraintValidatorContext) {return set.contains(integer);}
}

@NotBlank(message = “品牌名必须提交”) 至少一个字符
@NotEmpty可以为空串
@Min(value = 0)

统一的异常处理

@ControllerAdvice
1)、编写异常处理类,使用@ControllerAdvice。
2)、使用@ExceptionHandler标注方法可以处理的异常。

@Slf4j
@RestControllerAdvice(basePackages = "com.vinson.gulimall.product.controller")
public class GulimallExceptionControllerAdvice {@ExceptionHandler(value = MethodArgumentNotValidException.class)public R handleValidException(MethodArgumentNotValidException e) {log.info(e.getMessage() + e.getClass());BindingResult bindingResult = e.getBindingResult();HashMap<String, String> map = new HashMap<>();bindingResult.getFieldErrors().forEach((item) -> {map.put(item.getField(), item.getDefaultMessage());});return R.error(400, "提交数据不合法").put("data", map);}@ExceptionHandler(value = Throwable.class)public R handleException(Throwable throwable){log.error("错误:",throwable);//需要输出log,不然报错啥也看不到return R.error();}
}

系统错误码

错误码和错误信息定义类

  1. 错误码定义规则为 5 为数字
  2. 前两位表示业务场景,最后三位表示错误码。例如:100001。10:通用 001:系统未知异常
  3. 维护错误码后需要维护错误描述,将他们定义为枚举形式
    错误码列表:
    10: 通用
    001:参数格式校验
    11: 商品
    12: 订单
    13: 购物车
    14: 物流
public enum BizCodeEnum {UNKNOW_EXCEPTION(10000,"系统未知异常"),VAILD_EXCEPTION(10001,"参数格式校验失败");private int code;private String msg;BizCodeEnum(int code,String msg){this.code = code;this.msg = msg;}public int getCode() {return code;}public String getMsg() {return msg;}
}return R.error(BizCodeEnum.UNKNOW_EXCEPTION.getCode(), BizCodeEnum.UNKNOW_EXCEPTION.getMsg());

SPU 与 SKU

SPU:Standard Product Unit(标准化产品单元)
是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。
SKU:Stock Keeping Unit(库存量单位)
即库存进出计量的基本单元,可以是以件,盒,托盘等为单位。SKU 这是对于大型连锁超市DC(配送中心)物流管理的一个必要的方法。现在已经被引申为产品统一编号的简称,每种产品均对应有唯一的 SKU 号。

基本属性【规格参数】与销售属性
每个分类下的商品共享规格参数,与销售属性。只是有些商品不一定要用这个分类下全部的
属性;
 属性是以三级分类组织起来的
 规格参数中有些是可以提供检索的
 规格参数也是基本属性,他们具有自己的分组
 属性的分组也是以三级分类组织起来的
 属性名确定的,但是值是每一个商品不同来决定的

spu举例

sku举例

数据库设计

Object 划分

  • PO(persistant object) 持久对象
  • DO(Domain Object)领域对象
  • TO(Transfer Object) ,数据传输对象
    A传给B,通过Json的形式,两边都是object
  • DTO(Data Transfer Object)数据传输对象
  • VO(value object) 值对象
    View Object:视图对象
    不是数据库的数据
    接受页面传递来的数据,封装对象
    将业务处理完成的对象,封装成页面要用的数据
  • BO(business object) 业务对象
    我们可以把教育经历对应一个 PO ,工作经历对应一个 PO ,社会关系对应一个 PO 。 建立一个对应简历的 BO 对象处理简历
  • POJO(plain ordinary java object) 简单无规则 java 对象
  • DAO(data access object) 数据访问对象

实体类的构造

优惠生效情况[1111(四个状态位,从右到左);0 - 无优惠,成长积分是否赠送;1 - 无优惠,购物积分是否赠送;2 - 有优惠,成长积分是否赠送;3 - 有优惠,购物积分是否赠送【状态位0:不赠送,1:赠送】]
private Integer work;

采购流程

定时任务

待完善:

  • 失败理由
  • 部分失败,应采购10,实采购8

三级分类

@Overridepublic List<CategoryEntity> listWithTree() {//1查出所有分类List<CategoryEntity> entities = baseMapper.selectList(null);//2组装父子结构//2.1 找到所有一级分类List<CategoryEntity> level1Menus = entities.stream().filter((categoryEntity ->categoryEntity.getParentCid() == 0)).map((menu)->{menu.setChildren(getChildrens(menu,entities));return menu;}).sorted((menu1,menu2)->{return (menu1.getSort()==null?0:menu1.getSort())-(menu2.getSort()==null?0:menu2.getSort());}).collect(Collectors.toList());return entities;}//递归查找所有菜单的子菜单private List<CategoryEntity> getChildrens(CategoryEntity root,List<CategoryEntity> all){List<CategoryEntity> children = all.stream().filter(categoryEntity -> categoryEntity.getParentCid() == root.getCatId()).map(categoryEntity -> {categoryEntity.setChildren(getChildrens(categoryEntity, all));return categoryEntity;}).sorted((menu1, menu2) -> {return (menu1.getSort() == null ? 0 : menu1.getSort()) - (menu2.getSort() == null ? 0 : menu2.getSort());}).collect(Collectors.toList());return children;}

谷粒商城项目学-分布式基础相关推荐

  1. 谷粒商城项目1——分布式基础概念、环境搭建

    二.分布式基础概念 1.微服务架构 一个单体应用开发为一套小服务,每个小服务在自己的进程中,并使用轻量级机制通信 拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行 2.集群.分布式 ...

  2. 谷粒商城项目总结(一)-基础篇

    谷粒商城基础篇高级篇,跟着看,也敲了部分代码,但是感觉后续随着业务增加代码部分敲了也记不住,就想着应该重视解决问题的思路,理清思路比代码更重要,写这篇文章,是在看完后在从第一到高级篇,少部分集群篇总结 ...

  3. 谷粒商城微服务分布式基础篇二—— Spring Cloud Alibaba、Nacos注册与发现

    文章目录 Spring Cloud Alibaba--微服务开发 Spring Cloud Alibaba是什么?  主要功能  组件 为什么不使用Spring Cloud 使用 Nacos Disc ...

  4. 尚硅谷谷粒商城项目学习笔记-基础-P1项目搭建

    基础-P1项目搭建 0.虚拟机 1.项目架构 1.1Docker 1.1Docker命令 1.3Docker容器文件挂载与端口映射 1.2微服务-注册中心.配置中心.网关 1.3工具配置 1.3.1 ...

  5. 谷粒商城项目笔记之分布式基础(一)

    谷粒商城项目之分布式基础 目录 谷粒商城项目之分布式基础 前言 1 项目简介 1.1 项目背景 1.1.1 电商模式 1.1.2 谷粒商城 1.2 项目架构图 1.2.1 项目微服务架构图 1.2.2 ...

  6. 谷粒商城项目篇1_分布式基础篇_分布式基础概念、环境搭建、创建项目

    写在前面 为丰富项目经验,特此学习B站开源视频<全网最强电商教程<谷粒商城>对标阿里P6/P7,40-60万年薪>希望通过此学习能巩固所学,将技术栈串接起来. 此项目三个阶段 ...

  7. M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档

    M5(项目)-01-尚硅谷谷粒商城项目分布式基础篇开发文档 分布式基础篇 一.环境搭建 各种开发软件的安装 虚拟机: docker,mysql,redis 主机: Maven, idea(后端),Vs ...

  8. 谷粒商城 - 微服务分布式电商项目

    谷粒商城 1.项目背景 谷粒商城项目是尚硅谷研究院最新推出的完整大型分布式架构电商平台,技术全面.业务深入,全网无出其右.技术涵盖:微服务架构 + 分布式 + 全栈 + 集群 + 部署 + 自动化运维 ...

  9. *谷粒商城项目笔记*

    谷粒商城项目笔记 一 项目介绍(略) 二分布式的基础概念 1,微服务 拒绝大型单体应用,基于业务边界进行服务微化拆分,各个服务独立部署运行 2, 集群是个物理形态,分布式是个工作方式. 例如:京东是个 ...

最新文章

  1. 2019年人工智能的最大趋势和期望
  2. 京东每日特价专栏仿写
  3. C#操作xml之xpath语法
  4. 支付宝支付-支付宝PC端扫码支付
  5. 在ntpdate同步时间的时候出现“the NTP socket is in use, exiting”
  6. 网页版excel服务器,用excel当数据库,做个简单的网页
  7. 中文拼音排序的两种方法
  8. 超级计算机app网易,网易有道超级计算器
  9. 以图搜图 图像匹配_基于内容的图像检索(CBIR) ——以图搜图
  10. LU分解解线性方程组python实现
  11. 制作sim卡 服务器,diao丝绅士日记-自己撸系列 篇一:从此不再做diao丝-自制SIM卡套篇...
  12. 张国荣一生57部电影海报全集
  13. android 屏蔽电源键,home键
  14. 中国移动光猫 GM220-S 改桥接简易教程(安徽移动)
  15. cad.net 依照旧样条曲线数据生成一条新样条曲线的代码段. spline生成
  16. 电子学会2023年3月青少年软件编程python等级考试试卷(一级)真题,含答案解析
  17. Leetcode77 组合
  18. 网站统计-设计思路(访客数,浏览量,平均访问时长,平均同时在线人数,最高同时在线人数)
  19. 推荐几款好用的思维导图软件
  20. E2GameboyAX正式版

热门文章

  1. 实验六 文本串的加密解密
  2. 5000元的电视机推荐 5000元75寸高性价比电视推荐
  3. ValueError:Traceback(most ...)数据集中图片 not exists
  4. Xenon's Attack on the Gangs Codeforces Round #614 (Div. 2)
  5. 服务器安装操作系统失败,安装程序配置服务器失败怎么办
  6. 正向/逆向最大匹配法分词实现
  7. 腾讯的内外社区实践及未来开源布局
  8. 基于MT策略的实战分析
  9. rockchip的yocto编译环境的搭建
  10. 美团:不存在大众点评合并进美团App的可能性