商城项目业务总结
一、条件查询
/*** 条件查询列表** @param params* @return*/@Overridepublic PageUtils queryPageByCondition(Map<String, Object> params) {QueryWrapper<SpuInfoEntity> entityQueryWrapper = new QueryWrapper<>();String status = (String) params.get("status");String key = (String) params.get("key");String brandId = (String) params.get("brandId");String catelogId = (String) params.get("catelogId");if (StringUtils.isNotEmpty(status)) {entityQueryWrapper.eq("publish_status", status);}if (StringUtils.isNotEmpty(key)) {//这样写的话要写在所有条件最后
// entityQueryWrapper.eq("id",key)
// .or().like("spu_name",key)
// .or().like("spu_description",key);//否则就是这样写entityQueryWrapper.and(w -> {w.or().like("spu_name", key).or().like("spu_description", key);});}if (StringUtils.isNotEmpty(brandId) && !"0".equalsIgnoreCase(brandId)) {entityQueryWrapper.eq("brand_id", brandId);}if (StringUtils.isNotEmpty(catelogId) && !"0".equalsIgnoreCase(catelogId)) {entityQueryWrapper.eq("catalog_id", catelogId);}IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params),entityQueryWrapper);List<SpuInfoEntity> infoEntities = page.getRecords();List<SpuInfoResponsVo> vos = infoEntities.stream().map(spu -> {SpuInfoResponsVo spuInfoVo = new SpuInfoResponsVo();BeanUtils.copyProperties(spu, spuInfoVo);Long brandId1 = spu.getBrandId();BrandEntity brandEntity = brandService.getById(brandId1);spuInfoVo.setBrandName(brandEntity.getName());Long catalogId = spu.getCatalogId();CategoryEntity categoryEntity = categoryService.getById(catalogId);spuInfoVo.setCatalogName(categoryEntity.getName());return spuInfoVo;}).collect(Collectors.toList());PageUtils pageUtils = new PageUtils(page);pageUtils.setList(vos);return pageUtils;}二、递归树形结构分类查询
/*** 实现获得数据分类树形结构** @param params* @return*/@Overridepublic List<CategoryEntity> getTree(Map<String, Object> params) {//1.查询得到所有数据List<CategoryEntity> categoryEntities = categoryDao.selectList(null);//2.将所有数据过滤出所有ParentCid() == 0的大类查询出来List<CategoryEntity> list = categoryEntities.stream().filter(categoryEntity -> categoryEntity.getParentCid() == 0).map(categoryEntity -> {//根据大类找到小类ParentCid() ≠0 递归方法categoryEntity.setChildCategoryList(getCategoryChildrens(categoryEntity, categoryEntities));return categoryEntity;}).sorted((entity1, entity2) -> {return (entity1.getSort() == null ? 0 : entity1.getSort()) - (entity2.getSort() == null ? 0 : entity2.getSort());}).collect(Collectors.toList());return list;}
/*** 查找该大类下的所有的小类 递归查找* 递归找到大类中的小类** @param categoryEntity* @param categoryEntities* @return*/private List<CategoryEntity> getCategoryChildrens(CategoryEntity categoryEntity, List<CategoryEntity> categoryEntities) {List<CategoryEntity> entityList = categoryEntities.stream().filter(entity -> {//根据这个大类找小类 它的父亲ID与传过来的大类ID相等则都为该大类下的小类//注意Long类型的数据比较 如果不在-128-127之间的数据 它辉new Long(l)对象 所以比较不能用==
// return entity.getParentCid() == categoryEntity.getCatId();return entity.getParentCid().equals(categoryEntity.getCatId());}).map(entity -> {//递归找到小类下的小小类 设置到小类的属性中去并返回该实体 递归方法entity.setChildCategoryList(getCategoryChildrens(entity, categoryEntities));return entity;}).sorted((entity1, entity2) -> {return (entity1.getSort() == null ? 0 : entity1.getSort()) - (entity2.getSort() == null ? 0 : entity2.getSort());}).collect(Collectors.toList());return entityList;}三、多次查询数据库
可以通过ids查询出所有的在通过stream流转化为Map集合
但是注意的是有重复key的情况要排除
四、远程调用问题
1.远程调用的方法问题 POST GET 要一致
2.远程调用后 feign接口中的返回接收对象类型可以不一致但是里面的字段名称要一致
3.远程调用被其他服务所用的时候一般返回对象为JSON对象
//通常用fastJSON工具来进行json与对象的转化
//这里写一个Map<String,SkuInfoDTO> 的转化
//sku信息if (skuinfos.getCode()==0){//远程调用成功--一般远程调用都把对象以json形式放入String skuInfoMapJSON = skuinfos.get("skuInfoMap").toString();//转化Map对象Map<String, SkuInfoDTO> skuInfoMap = JSON.parseObject(skuInfoMapJSON, new TypeReference<Map<String,SkuInfoDTO>>() {});seckillSkuRedisDTO.setSkuInfo(skuInfoMap.get(seckillSkuRedisDTO.getSkuId().toString()));}
//否则 会报;linkedHashMap转化错误4. 远程调用的Cookie问题
package com.yueluo.mall.order.config;import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;/*** @author xjx* @email 15340655443@163.com* @date 2024/2/14 19:21*/
@Configuration
public class MallFeignConfig {/*** 解决因为访问购物车服务时,没有携带token,导致无法获取到用户信息--而转到了登录页面所以导致类型转换异常* 因为spring在feign远程调用时创建了一个RequestTemplate,但是没有携带cookie* Could not extract response: no suitable HttpMessageConverter found for response* type [java.util.List<com.yueluo.mall.order.vo.OrderItemVo>] and content type [text/html;charset=UTF-8]* 解决方案 在feign调用时,携带cookie** 如果在异步使用线程池进行远程调用的时候 使用的还是本地线程 因此我们需要同步添加 具体看OrderServiceImpl 中toConfirm方法* RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();* //同步设置请求头* RequestContextHolder.setRequestAttributes(requestAttributes);* @return*/@Beanpublic RequestInterceptor requestInterceptor(){return new RequestInterceptor() {@Overridepublic void apply(RequestTemplate requestTemplate) {ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();//可能为null--如果是读取MQ来的请求就会为null那么 他就不需要携带cookieif (requestAttributes == null){return;}if (requestAttributes.getRequest().getHeader("Cookie") != null){String cookie = requestAttributes.getRequest().getHeader("Cookie");requestTemplate.header("Cookie",cookie);}}};}
}
/*** 查询订单确认信息--异步编排** @return*/@Overridepublic OrderConfirmVo toConfirm() {MemberDTO memberInfo = getMemberInfo();Long memberId = memberInfo.getId();OrderConfirmVo orderConfirmVo = new OrderConfirmVo();//获取RequestContextHolder.getRequestAttributes() RequestContextHolder.getRequestAttributes()RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {//同步设置请求头RequestContextHolder.setRequestAttributes(requestAttributes);//1.会员地址信息List<MemberAddressVo> address = memberFeignService.getAddress(memberId);orderConfirmVo.setAddress(address);}, threadPoolExecutor);CompletableFuture<Void> cartItemsFuture = CompletableFuture.runAsync(() -> {//同步设置请求头RequestContextHolder.setRequestAttributes(requestAttributes);//2.购物车选中的商品信息List<OrderItemVo> cartItems = cartFeignService.getCartItems(memberId);orderConfirmVo.setItems(cartItems);}, threadPoolExecutor);//3.积分信息//4.优惠券信息//5.发票信息//6.其他信息//7.计算价格--计算订单的总金额 订单支付的总金额//8.返回确认信息CompletableFuture.allOf(addressFuture, cartItemsFuture).join();System.out.println("当前用户" + memberInfo + "订单确认信息为" + orderConfirmVo.toString());//9.防重令牌String token = UUID.randomUUID().toString().replace("-", "");orderConfirmVo.setOrderToken(token);//10.缓存防重令牌redisTemplate.opsForValue().set(OrderConstant.ORDER_TOKEN_PREFIX + memberId, token);return orderConfirmVo;}