所有代码发布在 [https://github.com/hades0525/leyou]
Day09
2019年1月29日
20:22
- 文件上传时出错:
spring boot的应用服务在启动的时候,会生成在操作系统的/tmp目录下生成一个Tomcat.*的文件目录,用于"java.io.tmpdir"文件流操作TomcatEmbeddedServletContainerFactory
程序对文件的操作时:会生成临时文件,暂存在临时文件中。但是由于长时间不操作,上传文件找不到目录,会报错。所以在配置文件中加一个参数,自定义目录。
server: tomcat: basedir: C:/Users/TEMP/AppData/Local/tomcat |
2.通用mapper
在工具类里写一个BaseMapper接口,所有mapper直接继承BaseMapper
@RegisterMapper public interface BaseMapper<T> extends Mapper<T>, IdListMapper<T,Long>, InsertListMapper<T> { } |
3.jdk8的lambda和stream使用
商品管理
- 商品的新增
- 前端页面
用了弹窗+4个stepper-content(分步的标签):新增的信息较多,分成4步来完成
|
- 基本信息:需要获取商品分类和分类下的品牌
- 获取商品分类已经在之前写了,还需要写一个根据分类获取品牌的方法
- 商品描述:运用了富文本编辑器,自定义了组件的上传图片的功能
- 规格参数:需要根据商品分类cid,获取规格参数
- sku属性:是spu下的每个商品的不同特征
- 页面提交:提交的数据整体是jason格式,包含spu表所有数据
|
- 后台实现
- pojo
- spu
- pojo
@Table(name="tb_spu") @Data publicclassSpu{ @Id @KeySql(useGeneratedKeys=true) privateLongid; privateLongbrandId; privateLongcid1;//1级类目 privateLongcid2;//2级类目 privateLongcid3;//3级类目 privateStringtitle;//标题 privateStringsubTitle;//子标题 privateBooleansaleable;//是否上架
@JsonIgnore//页面忽略的字段 privateBooleanvalid;//是否有效,逻辑删除用
privateDatecreateTime;//创建时间
@JsonIgnore//页面忽略字段 privateDatelastUpdateTime;//最后修改时间
@Transient//spu表里没有的字段,但页面查询要用 privateStringcname; @Transient//spu表里没有的字段,但页面查询要用 privateStringbname; @Transient//spu表里没有的字段,但页面新增,修改要用 privateList<Sku>skus; @Transient//spu表里没有的字段,但页面新增,修改要用 privateSpuDetailspuDetail; } |
- spuDetail
@Table(name="tb_spu_detail") @Data publicclassSpuDetail{ @Id privateLongspuId;//对应的SPU的id privateStringdescription;//商品描述 privateStringspecialSpec;//商品特殊规格的名称及可选值模板 privateStringgenericSpec;//商品的全局规格属性 privateStringpackingList;//包装清单 privateStringafterService;//售后服务
} |
- sku
@Table(name="tb_sku") @Data publicclassSku{ @Id @KeySql(useGeneratedKeys=true) privateLongid; privateLongspuId; privateStringtitle; privateStringimages; privateLongprice; privateStringownSpec;//商品特殊规格的键值对 privateStringindexes;//商品特殊规格的下标 privateBooleanenable;//是否有效,逻辑删除用 privateDatecreateTime;//创建时间 privateDatelastUpdateTime;//最后修改时间
@Transient//sku表里没有的字段,但页面商品新增和修改时要用 privateIntegerstock;//库存量 } |
- stock
@Table(name="tb_stock") @Data publicclassStock{ @Id privateLongskuId;//对应sku的id privateIntegerseckillStock;//秒杀可用库存 privateIntegerseckillTotal;//已秒杀数量 privateIntegerstock;//正常库存 } |
- 点击弹窗的后台
- 根据分类获取品牌
/** *根据cid查询品牌 *@paramcid *@return */ @GetMapping("/cid/{cid}") publicResponseEntity<List<Brand>>queryBrandByCid(@PathVariable("cid")Longcid){ returnResponseEntity.ok(brandService.queryBrandByCid(cid)); } |
/** *根据cid查询品牌 *@paramcid *@return */ publicList<Brand>queryBrandByCid(Longcid){ List<Brand>brands=brandMapper.queryByCategoryId(cid); if(CollectionUtils.isEmpty(brands)){ thrownewLyException(ExceptionEnum.BRAND_NOT_FOUND); } returnbrands; } |
@Select("SELECT b.* FROM tb_category_brand cb INNER JOIN tb_brand b ON cb.brand_id = b.id WHERE cb.category_id = #{cid}") List<Brand> queryByCategoryId(@Param("cid") Long cid); |
- 商品新增
- controller
/** *商品的新增 *@paramspu是一个Jason对象要用@RequestBody *@return */ @PostMapping("goods") publicResponseEntity<Void>saveGoods(@RequestBodySpuspu){ goodsService.saveGoods(spu); returnResponseEntity.status(HttpStatus.CREATED).build(); } |
- service,要对SPU新增以外,还要对SpuDetail、Sku、Stock进行保存
/** *新增商品 *@paramspu */ @Transactional publicvoidsaveGoods(Spuspu){ //新增spu spu.setId(null); spu.setCreateTime(newDate()); spu.setLastUpdateTime(spu.getCreateTime()); spu.setSaleable(true); spu.setValid(false); intcount=spuMapper.insert(spu); if(count!=1){ thrownewLyException(ExceptionEnum.GOODS_SAVE_ERROE); }
//新增spu_detail SpuDetaildetail=spu.getSpuDetail(); detail.setSpuId(spu.getId()); spuDetailMapper.insert(detail); //新增sku和stock saveSkuAndStock(spu);
}
/** *新增sku和stock *@paramspu */ privatevoidsaveSkuAndStock(Spuspu){ intcount;//定义库存集合 List<Stock>stockList=newArrayList<>(); //新增sku List<Sku>skus=spu.getSkus(); for(Skusku:skus){ sku.setCreateTime(newDate()); sku.setLastUpdateTime(sku.getCreateTime()); sku.setSpuId(spu.getId()); count=skuMapper.insert(sku); if(count!=1){ thrownewLyException(ExceptionEnum.GOODS_SAVE_ERROE); } //新增stock Stockstock=newStock(); stock.setSkuId(sku.getId()); stock.setStock(sku.getStock()); stockList.add(stock); }
//批量新增stock count=stockMapper.insertList(stockList); if(count!=1){ thrownewLyException(ExceptionEnum.GOODS_SAVE_ERROE); } } |
- 商品更新
- 商品更新时,会发起两个请求,查询商品详情detail和sku信息
-
- controller
/** *根据spu的id查询详情detail *@paramspuId *@return */ @GetMapping("/spu/detail/{id}") publicResponseEntity<SpuDetail>queryDetailById(@PathVariable("id")LongspuId){ returnResponseEntity.ok(goodsService.queryDetailById(spuId)); }
/** *根据spu查询下面所有sku *@paramspuId *@return */ @GetMapping("/sku/list") publicResponseEntity<List<Sku>>querySkuBySpuId(@RequestParam("id")LongspuId){ returnResponseEntity.ok(goodsService.querySkuBySpuId(spuId)); } |
- service
/** *根据spu的id查询详情detail *@paramspuId *@return */ publicSpuDetailqueryDetailById(LongspuId){ SpuDetaildetail=spuDetailMapper.selectByPrimaryKey(spuId); if(detail==null){ thrownewLyException(ExceptionEnum.GOODS_DETAIL_NOT_FOUND); } returndetail; }
/** *根据spuid查询下面所有的sku和stock *@paramspuId *@return */ publicList<Sku>querySkuBySpuId(LongspuId){ Skusku=newSku(); sku.setSpuId(spuId); List<Sku>skuList=skuMapper.select(sku); if(CollectionUtils.isEmpty(skuList)){ thrownewLyException(ExceptionEnum.GOODS_SKU_NOT_FOUND); }
//查询库存 //根据skulist取得到所有id集合 List<Long> ids = skuList.stream().map(Sku::getId).collect(Collectors.toList()); //根据id集合查询到所有stock集合 List<Stock> stockList = stockMapper.selectByIdList(ids); if(CollectionUtils.isEmpty(stockList)){ throw new LyException(ExceptionEnum.GOODS_STOCK_NOT_FOUND); } //把stock变成一个map,key是skuid,value是库存量 Map<Long,Integer> stockMap = stockList.stream() .collect(Collectors.toMap(Stock::getSkuId,Stock::getStock)); //把stockmap的库存量赋值给skulist的库存量 skuList.forEach(s->s.setStock(stockMap.get(s.getId()))); return skuList; } |
- 更新的提交
- controller
/** *商品的修改 *@paramspu是一个Jason对象要用@RequestBody *@return */ @PutMapping("goods") publicResponseEntity<Void>updateGoods(@RequestBodySpuspu){ goodsService.updateGoods(spu); returnResponseEntity.status(HttpStatus.NO_CONTENT).build(); } |
- service
/** *修改商品 *@param spu */ @Transactional publicvoidupdateGoods(Spuspu){ if(spu.getId()==null){ thrownewLyException(ExceptionEnum.GOODS_ID_CANNOT_BE_NULL); }
Skusku=newSku(); sku.setSpuId(spu.getId()); //查询sku List<Sku>skuList=skuMapper.select(sku); if(!CollectionUtils.isEmpty(skuList)){ //删除sku skuMapper.delete(sku); //删除stock List<Long>ids=skuList.stream().map(Sku::getId).collect(Collectors.toList()); stockMapper.deleteByIdList(ids); } //修改spu spu.setValid(null); spu.setSaleable(null); spu.setLastUpdateTime(newDate()); spu.setCreateTime(null);
intcount=spuMapper.updateByPrimaryKeySelective(spu); if(count!=1){ thrownewLyException(ExceptionEnum.UPDATE_GOODS_ERROR); } //修改detail count=spuDetailMapper.updateByPrimaryKeySelective(spu.getSpuDetail()); if(count!=1){ thrownewLyException(ExceptionEnum.UPDATE_GOODS_ERROR); } //新增sku和stock saveSkuAndStock(spu); } |
- 前台门户系统 leyou-portal
- 不再采用后台的单页应用,而是直接编写原生的静态HTML。nuxt + vue + webpack 服务端渲染
- 使用带有热加载功能的小型开发服务器live-server。用它来展示你的HTML / JavaScript / CSS,但不能用于部署最终的网站。
- 安装:npm install -g live-server
- 运行:live-server --port=9002
- 在nginx中配置域名
server { listen 80; server_name www.leyou.com;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / { proxy_pass http://192.168.163.128:9002; proxy_connect_timeout 600; proxy_read_timeout 600; } } |