谷粒商城基础分布式总结

  • 1.新增商品
    • 1.调试member服务
    • 2.查询分类下的所有品牌
    • 2.获取分类下面带属性的属性分组。
    • 3、保存设定好的spu和sku信息
  • 2.商品管理
    • 1.spu展示查询(spuinfo/list)
    • 2.商品展示
  • 3.仓库管理
    • 1.初始化ware获取仓库列表
    • 2.查询库存&创建采购需求
    • 3.合并采购需求
    • 4.领取采购单
    • 5.完成采购
    • 6.展示规格,修改规格
  • 4.基础分布式总结
    • 1.分布式:
    • 2.基础开发:
    • 3.环境:
    • 4.开发规范

1.新增商品

1.调试member服务

出现问题:

①路由规则配置问题/api/member/错,改成/api(原因在找)

②在最后一步没有显示会员的优惠信息。这一栏如果没有显示原因就是你设置了多个默认会员。导致错误。可以看看数据库或者是看看会员等级这个部分。

- id: gulimall_member_routeuri: lb://gulimall-memberpredicates:- Path=/api/member/**filters:- RewritePath=/api/(?<segment>.*),/$\{segment}

2.查询分类下的所有品牌

思路

①CategoryBrandCon中写brands/list接口,接收catId,并且封装返回的BrandVo对象

②CateBrandSer根据分类id查询分类品牌的关联关系,然后通过关系对象获取所有的品牌id。

③根据品牌id再次获取品牌对象,封装到list返回

CateBrandSer

@Overridepublic List<BrandEntity> getBrandsByCatId(Long catId) {//1.根据分类id查询关联的List<CategoryBrandRelationEntity> relationEntities = categoryBrandRelationDao.selectList(new QueryWrapper<CategoryBrandRelationEntity>().eq("catelog_id", catId));//2.根据品牌id查询品牌。(查询的是分类下面关联的品牌。)List<BrandEntity> brandEntities = relationEntities.stream().map(item -> {Long brandId = item.getBrandId();BrandEntity byId = brandService.getById(brandId);return byId;}).collect(Collectors.toList());return brandEntities;}

CateBrandCon

 @GetMapping("brands/list")public R getBrandsRelation(@RequestParam(value = "catId",required = true)Long catId ){//service获取对应的brandentityList<BrandEntity> list=categoryBrandRelationService.getBrandsByCatId(catId);List<BrandVo> vos= list.stream().map(item -> {BrandVo brandVo = new BrandVo();brandVo.setBrandId(item.getBrandId());brandVo.setBrandName(item.getName());return brandVo;}).collect(Collectors.toList());return R.ok().put("data",vos);}

2.获取分类下面带属性的属性分组。

思路

①需要一个vo对象来存储处理group对象的属性还要有属性集合

②先根据分类id获取所有分组

③根据分组id通过之前写过的getRelationAttr方法获取分组下所有的属性,存入对应的vo对象

AttrService

/*** 查询分类下所有属性* @param catelogId* @return*/@Overridepublic List<AttrGroupWithAttrsVo> getGroupWithAttrsByCatId(Long catelogId) {//1.查询所有分组List<AttrGroupEntity> group= attrGroupDao.selectList(new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId));//2.获取查询分组下所有的属性List<AttrGroupWithAttrsVo> attrGroupWithAttrsVos = group.stream().map(item -> {//3.把group放入vo对象AttrGroupWithAttrsVo attrGroupWithAttrsVo = new AttrGroupWithAttrsVo();BeanUtils.copyProperties(item, attrGroupWithAttrsVo);Long attrGroupId = item.getAttrGroupId();//4.根据groupid查询关联关系List<AttrEntity> attrs = attrService.getRelationAttr(attrGroupId);attrGroupWithAttrsVo.setAttrs(attrs);return attrGroupWithAttrsVo;}).collect(Collectors.toList());return attrGroupWithAttrsVos;}

3、保存设定好的spu和sku信息

思路

①JSON转换成java类

②理清楚所有要保存的属性。

③第一步保存Spu的所有信息

④接着就是保存sku的信息。如果发现需要转换对象那么就可以通过stream来达到转换的效果。

拓展与踩坑

①保存spu的bound的时候需要远程调用,服务之间的远程参数可以放到common的TO对象中。而且TO对象在传输的时候会变成requestBody也就是json字符串的请求体,也就是只需要消费者对象和提供者对象的json字符串相容就能够传输。(相容指的是他们的属性名是否相同,结构是否相似。)

②第一个是关于getCode的问题,获取的本来就是一个Integer无法转换成String。那么直接强转Object为Integer就可以

③第二个即使desc的问题,其实问题就是字段sku_id不应该是自增而是我们设置进去的。不然程序设置的时候会发现sku_id已经有默认值而无法自增。

④解决会员价<=0和折扣<=0的情况,还有就是sku_imgurl为空的情况。

⑤set session transaction isolation level read uncommitted;通过这个设置会话为读未提交,能够有虚拟数据加入。但是中途如果自己断开连接,这些数据会保存下来。

⑥compound能够把微服务一起开启,并且可以设置-Xml100m在VM-option中限制他们运行的内存

SpuInfoServiceImpl

 @Transactional@Overridepublic void saveSpuSaveVo(SpuSaveVo vo) {//1.保存Spu的基本信息spu_infoSpuInfoEntity spuInfoEntity=new SpuInfoEntity();BeanUtils.copyProperties(vo,spuInfoEntity);spuInfoEntity.setCreateTime(new Date());spuInfoEntity.setUpdateTime(new Date());this.saveSpuInfo(spuInfoEntity);//2.保存spu的图片集spu_imgList<String> images = vo.getImages();spuImagesService.saveImages(spuInfoEntity.getId(),images);//3.保存spu的介绍图片集spu_desList<String> decript = vo.getDecript();SpuInfoDescEntity spuInfoDescEntity = new SpuInfoDescEntity();spuInfoDescEntity.setSpuId(spuInfoEntity.getId());spuInfoDescEntity.setDecript(String.join(",",decript));spuInfoDescService.saveSpuDesc(spuInfoDescEntity);//4.保存spu的规格参数spu_product_attr_valueList<BaseAttrs> baseAttrs = vo.getBaseAttrs();//转换成productattrvalueList<ProductAttrValueEntity> attrValueEntities = baseAttrs.stream().map(attr -> {ProductAttrValueEntity productAttrValueEntity = new ProductAttrValueEntity();productAttrValueEntity.setAttrId(attr.getAttrId());productAttrValueEntity.setQuickShow(attr.getShowDesc());//根据attrId获取属性->nameAttrEntity attrEntity = attrService.getById(attr.getAttrId());productAttrValueEntity.setAttrName(attrEntity.getAttrName());productAttrValueEntity.setAttrValue(attr.getAttrValues());return productAttrValueEntity;}).collect(Collectors.toList());attrValueService.saveProductAttrValueList(attrValueEntities);//5.保存spu的积分信息spu_boundsBounds bounds = vo.getBounds();R r1 = couponFeignService.saveBound(bounds);if(r1.getCode()!=0){log.error("保存spu积分信息失败");}//6.保存skuList<Skus> skusList = vo.getSkus();//判空操作if(skusList!=null&&skusList.size()>0){//遍历skufor(Skus skuvo:skusList){//遍历图片,找到defalutURLString defaultImg="";List<Images> skuImages = skuvo.getImages();for(Images skuImage:skuImages){if(skuImage.getDefaultImg()==1){defaultImg=skuImage.getImgUrl();}}//vo->po转换SkuInfoEntity skuInfoEntity = new SkuInfoEntity();BeanUtils.copyProperties(skuvo,skuInfoEntity);skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());skuInfoEntity.setSaleCount(0L);skuInfoEntity.setSpuId(spuInfoEntity.getId());skuInfoEntity.setSkuDefaultImg(defaultImg);//6.1、sku基本信息skuInfoService.saveSkuInfo(skuInfoEntity);//处理图片集List<SkuImagesEntity> skuImagesEntityList = skuImages.stream().map(img -> {//存入SkuImage下SkuImagesEntity skuImagesEntity = new SkuImagesEntity();BeanUtils.copyProperties(img, skuImagesEntity);skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());return skuImagesEntity;}).collect(Collectors.toList());//6.2、sku图片集skuImagesService.saveBatch(skuImagesEntityList);//6.3、sku销售属性List<Attr> attrList = skuvo.getAttr();List<SkuSaleAttrValueEntity> skuSaleAttrValueEntityList = attrList.stream().map(attr -> {SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());return skuSaleAttrValueEntity;}).collect(Collectors.toList());skuSaleAttrValueService.saveBatch(skuSaleAttrValueEntityList);//6.4、sku优惠属性,满减、会员价、打折信息SkuReductionTo skuReductionTo = new SkuReductionTo();skuReductionTo.setSkuId(skuInfoEntity.getSkuId());BeanUtils.copyProperties(skuvo,skuReductionTo);R r = couponFeignService.saveSkuReduction(skuReductionTo);if(r.getCode()!=0){log.error("保存sku优惠信息失败");}}}}

SpuBoundsCon

/*** 保存*/@RequestMapping("/save")//@RequiresPermissions("coupon:spubounds:save")public R save(@RequestBody SpuBoundsEntity spuBounds){spuBoundsService.save(spuBounds);return R.ok();}

CouponFeignService


@FeignClient("gulimall-coupon")
public interface CouponFeignService {@RequestMapping("coupon/spubounds/save")R saveBound(Bounds bounds);@PostMapping("coupon/skufullreduction/saveInfo")R saveSkuReduction(SkuReductionTo skuReductionTo);
}

2.商品管理

1.spu展示查询(spuinfo/list)

思路

①重写service方法qeuryForPageByCondition

②对属性值进行判空,然后增加条件查询。

拓展

①如果发现最后显示的时间格式不好那么可以在application.yml中配置date-formate.(json)

SpuInfoSer

@Overridepublic PageUtils queryPageByCondition(Map<String, Object> params) {QueryWrapper<SpuInfoEntity> wrapper = new QueryWrapper<>();//1.判断keyString  key = (String) params.get("key");if(!StringUtils.isEmpty(key)){wrapper.and(w->{w.eq("id",key).or().like("spu_name",key);});}//2.statusString  status = (String) params.get("status");if(!StringUtils.isEmpty(status)){wrapper.eq("publish_status",status);}//3.catelog_idString  catelogId = (String) params.get("catelogId");if(!StringUtils.isEmpty(catelogId )){wrapper.eq("catalog_id",catelogId);}//4.brandIdString  brandId = (String) params.get("brandId");if(!StringUtils.isEmpty(brandId)){wrapper.eq("brand_id",brandId);}IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params),wrapper);return new PageUtils(page);}

2.商品展示

思路

①还是在对应的skuinfo/list中增加条件查询

拓展与问题

①在这个地方会发现catelog_id和brand_id如果等于0的时候就会查询不到,那么就要做一个判断处理,如果是0那么就不增加查询条件。

②max需要放入decimal检测是否是数字,然后还需要看是不是>0如果是才加入条件。

③条件查询的连接可以用到and(w->{})继续连接查询。或者是eq。

SkuInoSer

 @Overridepublic PageUtils queryPageByCondition(Map<String, Object> params) {QueryWrapper<SkuInfoEntity> wrapper = new QueryWrapper<>();/*** key:* catelogId: 0* brandId: 0* min: 0* max: 0*/String key = (String) params.get("key");if(!StringUtils.isEmpty(key)){wrapper.and(w->{w.eq("sku_id",key).or().like("sku_name",key);});}String brandId = (String) params.get("brandId");if(!StringUtils.isEmpty(brandId)&&!"0".equalsIgnoreCase(brandId)){wrapper.eq("brand_id",brandId);}String catelogId = (String) params.get("catelogId");if(!StringUtils.isEmpty(catelogId)&&!"0".equalsIgnoreCase(catelogId)){wrapper.eq("catalog_id",catelogId);}String min = (String) params.get("min");if(!StringUtils.isEmpty(min)){wrapper.ge("price",min);}String max = (String) params.get("max");if(!StringUtils.isEmpty(max)){//判断是否为0try {BigDecimal maxBigDecimal = new BigDecimal(max);if(maxBigDecimal.compareTo(new BigDecimal("0"))==1){wrapper.le("price",max);}}catch (Exception e){e.printStackTrace();}}IPage<SkuInfoEntity> page = this.page(new Query<SkuInfoEntity>().getPage(params),wrapper);return new PageUtils(page);}

3.仓库管理

1.初始化ware获取仓库列表

思路

①写好gateway

②服务注册,name,开启事务。

2.查询库存&创建采购需求

思路和上面的一致都是判空然后添加条件。

3.合并采购需求

需求描述:把采购需求合并到一个采购单中。分解出来其实就是把采购单id与对应的采购需求绑定在一起,所以只需要更新采购需求的绑定采购单id,如果没有采购单就创建采购单.

思路

①搜索合并采购单,并且查询那些未领取和新建的,处理status条件即可

②创建constant类来记录这些采购状态。

③主要是编写merge接口

PurchaseSer

/*** 合并菜单* @param mergeVo*/@Overridepublic void merge(MergeVo mergeVo) {//1.如果没有订单那么就创建一个Long purchaseId = mergeVo.getPurchaseId();if(purchaseId==null){PurchaseEntity purchaseEntity=new PurchaseEntity();purchaseEntity.setStatus(WareConstant.PurchaseStatusEnum.CREATE.getCode());purchaseEntity.setCreateTime(new Date());purchaseEntity.setUpdateTime(new Date());this.save(purchaseEntity);}//2.更新需求信息List<Long> items = mergeVo.getItems();List<PurchaseDetailEntity> detailEntities = items.stream().map(i -> {PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();//绑定到的订单号purchaseDetailEntity.setPurchaseId(purchaseId);purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailEnum.ASSIGNED.getCode());//根据自己的id来更新purchaseDetailEntity.setId(i);return purchaseDetailEntity;}).collect(Collectors.toList());//更新detailService.updateBatchById(detailEntities);}

4.领取采购单

思路

①相当于就是修改采购单和采购需求的状态。

②先确定采购单的状态

③修改采购单状态->通过id获取采购单->过滤状态不对的采购单->修改状态

④修改采购需求状态->根据采购单id获取对应需求->修改状态

 @Overridepublic void receivedPurchase(List<Long> ids) {//1.确认采购单的状态是0或者是1List<PurchaseEntity> purchaseEntities = ids.stream().map(id -> {//查询信息PurchaseEntity purchaseEntity = this.getById(id);return purchaseEntity;}).filter(entity -> {//过滤if (entity.getStatus() == WareConstant.PurchaseStatusEnum.ASSIGNED.getCode() ||entity.getStatus() == WareConstant.PurchaseStatusEnum.CREATE.getCode()) {return true;}return false;}).map(entity -> {//改变状态entity.setStatus(WareConstant.PurchaseStatusEnum.RECEIVE.getCode());return entity;}).collect(Collectors.toList());//2.修改采购单状态this.updateBatchById(purchaseEntities);//3.修改采购需求状态purchaseEntities.forEach(item->{Long purchaseId = item.getId();//查询采购单的需求List<PurchaseDetailEntity> detailEntities=detailService.getDetailByPurchaseId(purchaseId);//遍历需求,修改状态List<PurchaseDetailEntity> updateDetailList = detailEntities.stream().map(entity -> {PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();purchaseDetailEntity.setId(entity.getId());purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailEnum.BUYING.getCode());return purchaseDetailEntity;}).collect(Collectors.toList());//更新detailService.updateBatchById(updateDetailList);});

5.完成采购

需求分析

完成采购谁需要改变?很明显采购单需要状态改变,第二个就是采购项状态需要改变。那么完成了采购是不是相应的库存也应该有所增加?也就是说库存也需要进行改变。那么思路就是purchaseSer完成状态改变->wareSkuSer完成库存改变。库存其实就是商品-仓库-商品数量之间的一个对应关系。

思路

①需要两个vo对象,一个是采购单的,一个是采购项的。采购单中有id和多个采购项,采购项里就是采购项的id和采购状态还有造成这个状态的采购原因。其实就是购买出现了什么状况

②然后就是PurchaseCon写好done接口,->交给ser先完成采购项的状态更新,并且留一个flag判断是否采购成功,因为一个采购项出现问题,那么采购单的采购也是有问题的。

③更新采购单状态。

④接着就是改变库存。

拓展与踩坑

①flag只需要一个失败的采购项就是一直是false,不需要在成功的时候改成true

②注意json对象与vo对象的兼容

WareSkuSer

 @Overridepublic void addStock(PurchaseDetailEntity entity) {//不存在这个库存位置List<WareSkuEntity> list = this.list(new QueryWrapper<WareSkuEntity>().eq("sku_id", entity.getSkuId()).eq("ware_id", entity.getWareId()));if(list!=null&&list.size()>0){//如果存在的话baseMapper.addStock(entity.getSkuId(),entity.getWareId(),entity.getSkuNum());}else{//如果不存在这个库存,那么就创建一条记录。//仓库——商品(数量)WareSkuEntity wareSkuEntity = new WareSkuEntity();wareSkuEntity.setSkuId(entity.getSkuId());wareSkuEntity.setStock(entity.getSkuNum());wareSkuEntity.setWareId(entity.getWareId());wareSkuEntity.setStockLocked(0);//远程调用添加商品名字try {R info = productFeignService.info(entity.getSkuId());if(info.getCode()==0){Map<String,Object> skuInfo = (Map<String, Object>) info.get("skuInfo");wareSkuEntity.setSkuName((String) skuInfo.get("skuName"));}} catch (Exception e) {e.printStackTrace();}baseMapper.insert(wareSkuEntity);}}

PurchaseSer

@Transactional@Overridepublic void done(PurChaseDoneVo purChaseDoneVo) {boolean flag=true;//1.修改采购项的状态List<PurChaseItemVo> itemVos = purChaseDoneVo.getItems();//创建一个detailList方便修改List<PurchaseDetailEntity> purchaseDetailEntities=new ArrayList<>();for(PurChaseItemVo itemVo:itemVos){//新创建detail对象PurchaseDetailEntity purchaseDetailEntity = new PurchaseDetailEntity();//获取状态并且判断Integer itemStatus = itemVo.getStatus();if(itemStatus== WareConstant.PurchaseDetailEnum.HASERROR.getCode()){//失败//主要修改状态purchaseDetailEntity.setStatus(itemStatus);flag=false;}else{//1.1修改库存信息purchaseDetailEntity.setStatus(WareConstant.PurchaseDetailEnum.FINISHED.getCode());//1.2获取项信息,并修改库存。PurchaseDetailEntity byIdDetailEntity = detailService.getById(itemVo.getItemId());//1.3修改库存wareSkuService.addStock(byIdDetailEntity);}purchaseDetailEntity.setId(itemVo.getItemId());purchaseDetailEntities.add(purchaseDetailEntity);}detailService.updateBatchById(purchaseDetailEntities);//2.修改采购单的状态Long purchaseId = purChaseDoneVo.getId();//获取订单对象PurchaseEntity updatePurchase = new PurchaseEntity();updatePurchase.setId(purchaseId);System.out.println(flag);updatePurchase.setStatus(flag?WareConstant.PurchaseStatusEnum.FINISHED.getCode():WareConstant.PurchaseStatusEnum.HASERROR.getCode());updatePurchase.setUpdateTime(new Date());this.updateById(updatePurchase);}

6.展示规格,修改规格

思路

①直接展示spu_id相关的规格参数,条件查询

②修改规格,接收参数,删除spuId相关的规格参数之后再重新插入。

拓展与踩坑

①如果发现点击规格出现404,先去gulimall-admin的数据库中插入信息INSERT INTO sys_menu (menu_id, parent_id, name, url, perms, type, icon, order_num) VALUES (76, 37, ‘规格维护’, ‘product/attrupdate’, null,2, ‘log’, 0);,接着还是会出现404,那么就去到src/router/index.js下的mainRoutes的children:[]里面加入路径{ path: ‘/product-attrupdate’, component: _import(‘modules/product/attrupdate’), name: ‘attr-update’, meta: { title: ‘规格维护’, isTab: true } }

ProductAttrValueSer

  /*** 查询产品规格参数* @param spuId* @return*/@Overridepublic List<ProductAttrValueEntity> listForSpu(Long spuId) {List<ProductAttrValueEntity> productAttrValueEntityList = this.baseMapper.selectList(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id", spuId));return productAttrValueEntityList;}/*** 更新规格参数* @param spuId* @param updateProductAttrList*/@Overridepublic void updateProductAttrList(Long spuId, List<ProductAttrValueEntity> updateProductAttrList) {//1.删除所有关于spuId的规格参数this.baseMapper.delete(new QueryWrapper<ProductAttrValueEntity>().eq("spu_id",spuId));//2.给修改的集合加上spuId然后插入修改List<ProductAttrValueEntity> productAttrValueEntities = updateProductAttrList.stream().map(item -> {item.setSpuId(spuId);return item;}).collect(Collectors.toList());this.saveBatch(productAttrValueEntities);}

4.基础分布式总结

1.分布式:

①注册中心:服务注册

②配置中心:配置文件注册

③Feign:完成远程调用和负载均衡

④远程调用

⑤微服务

2.基础开发:

①Springboot2

②mybatis-plus

③springcloud

④vue

⑤阿里云对象存储

3.环境:

①linux

②redis、mysql

③逆向工程和人人开源

④vagrant虚拟机

4.开发规范

①vo(前端数据)与to(服务之间传输的对象)还有po(数据库表保存对象)的区别

②JSR303数据校验

③全局跨域、异常映射、统一返回

④枚举状态、业务枚举

⑤lombok

总结:对于自己来说相比起尚筹网和谷粒学院这个项目逻辑更复杂,一开始我并不适应,后来跟着一步步练习,然后找到对象之间的关系。如果大家也很觉得难,那么可以尝试先把思路写在纸上,然后画出类和表之间的逻辑关系,相互调用的逻辑关系,以及分析需求的求解方案,这样能够梳理清楚业务逻辑,然后加以总结。接下来就进入到谷粒商城的第二个阶段了。

谷粒商城(新增商品、商品管理、仓库管理)思路详解相关推荐

  1. 企业项目权限管理设计思路详解

    任何系统都离不开权限的管理,有一个好的权限管理模块,不仅使我们的系统操作自如,管理方便,也为系统添加亮点. l        不同职责的人员,对于系统操作的权限应该是不同的.优秀的业务系统,这是最基本 ...

  2. ElasticSearch最全详细使用教程:入门、索引管理、映射详解、索引别名、分词器、文档管理、路由、搜索详解...

    墨墨导读:之前我们分享了ElasticSearch最全详细使用教程:入门.索引管理.映射详解,本文详细介绍ElasticSearch的索引别名.分词器.文档管理.路由.搜索详解. 一.索引别名 1. ...

  3. 【直播】陈安东,但扬:CNN模型搭建、训练以及LSTM模型思路详解

    CNN模型搭建.训练以及LSTM模型思路详解 目前 Datawhale第24期组队学习 正在如火如荼的进行中.为了大家更好的学习"零基础入门语音识别(食物声音识别)"的课程设计者 ...

  4. Java编程配置思路详解

    Java编程配置思路详解 SpringBoot虽然提供了很多优秀的starter帮助我们快速开发,可实际生产环境的特殊性,我们依然需要对默认整合配置做自定义操作,提高程序的可控性,虽然你配的不一定比官 ...

  5. ElasticSearch最全详细使用教程:入门、索引管理、映射详解

    墨墨导读:本文介绍了ElasticSearch的必备知识:从入门.索引管理到映射详解. 一.快速入门 1. 查看集群的健康状况http://localhost:9200/_cat http://loc ...

  6. 【云原生之k8s】k8s管理工具kubectl详解

    [云原生之k8s]k8s管理工具kubectl详解 前言 一.陈述式管理 (1)陈述式资源管理方法 (2)k8s相关信息查看 ①查看版本信息 ②查看节点信息 ③查看资源对象简写 ④查看集群信息 ⑤配置 ...

  7. Pinterest 3.0 for iOS设计过程——升级iOS7设计思路详解

    Pinterest 3.0 for iOS设计过程--升级iOS7设计思路详解 时间2013-12-11 11:39:31  苹果开发中文站 原文  http://www.cocoachina.com ...

  8. elasticsearch最全详细使用教程:入门、索引管理、映射详解、索引别名、分词器、文档管理、路由、搜索详解

    一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 ...

  9. JAVA抖音潜艇挑战_Android 实现抖音小游戏潜艇大挑战的思路详解

    <潜水艇大挑战>是抖音上的一款小游戏,以面部识别来驱动潜艇通过障碍物,最近特别火爆,相信很多人都玩过. 一时兴起自己用Android自定义View也撸了一个,发现只要有好的创意,不用高深的 ...

最新文章

  1. android+apk+反编译和再签名打包,Android:apk反编译步骤,打包、签名和逆向工程经验总结...
  2. vue.js框架原理浅析
  3. 2020-2021年度第二届全国大学生算法设计与编程挑战赛 (春季赛)- 天才的操作(线段树+主席树+树上倍增)
  4. 基于Sbo SDK的Add-on插件开发实例
  5. vs设计窗口不见了_碳纤维的巅峰:VS沛纳海616V3
  6. vscode无法打开源文件iostream_C++的iostream标准库介绍(1)
  7. bae php微信配置,使用BAE3.0搭建微信开发环境
  8. 在Linux下安装LaTeX+CJK+中文字体的方法 [转]
  9. Eclipse中使用GIT将文件还原至上一版本
  10. Java中的数据结构之常见的五种数据结构
  11. iMC iNode客户端上岗证
  12. unity物理引擎详解
  13. 怎样设置阿里云Web应用攻击防护?
  14. 一堂难忘的计算机课作文,一节电脑课作文600字
  15. Stack Ball 堆栈球小游戏unity3d开发教程
  16. excel一列数字前面批量加个逗号
  17. Robert Sedgewick左倾红黑树论文翻译
  18. 为什么一场比赛进3球叫帽子戏法?
  19. 你从未见过的“地狱级”烂项目
  20. react 生命周期

热门文章

  1. 浅谈卓智达公网集群通信系统在大型赛事中的应用
  2. [Datasheet] PHY LAN8720网络芯片解读
  3. 华为Ascend众智计划项目--3DMPPE_ROOTNET--Pytorch模型迁移至NPU(二)
  4. 整数规划(线性)matlab实现
  5. 使用MegaCli监控Linux硬盘
  6. BZOJ2073: [POI2004]PRZ
  7. 创客教育对学生的意义
  8. 每天和琦琦学点新知识_爬虫篇002_Python正则表达式
  9. PCIe热插拔机制(详细)总结-PCIe专题知识(五)
  10. Verilog基础入门