購物車服務
一、環境搭建
- springboot初始化
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-w8Etki5f-1634740503555)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020215413222.png)]](https://img.uj5u.com/2021/10/22/276462220734592.png)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mx7XHAam-1634740503558)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020215509730.png)]](https://img.uj5u.com/2021/10/22/276462220734593.png)
- 新增本地域名
cart.achangmall.com
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-squlof7q-1634740503559)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020220220652.png)]](https://img.uj5u.com/2021/10/22/276462220734594.png)
- 修改對應pom配置,與此次服務間版本對應
- 引入公共依賴
- 修改springboot版本
- 修改springcloud版本
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-T0lijbWA-1634740503562)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020220324525.png)]](https://img.uj5u.com/2021/10/22/276462220734595.png)
- 將提供的靜態資源匯入nginx服務,做到
動靜分離
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-zSZSoZS2-1634740503564)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020221013248.png)]](https://img.uj5u.com/2021/10/22/276462220734596.png)
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Et4sjIlg-1634740503565)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020221039429.png)]](https://img.uj5u.com/2021/10/22/276462220734597.png)
- 修改頁面對應的資源地址,修改只選nginx的靜態地址,如:
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-eQVVKGGa-1634740503567)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020221252757.png)]](https://img.uj5u.com/2021/10/22/276462220734591.png)
- 主啟動類com.achang.achangmall.cart.AchangmallCartApplication
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableFeignClients
@EnableDiscoveryClient
public class AchangmallCartApplication {
public static void main(String[] args) {
SpringApplication.run(AchangmallCartApplication.class, args);
}
}
- 組態檔achangmall-cart/src/main/resources/application.yaml
spring:
cloud:
loadbalancer:
ribbon:
enabled: false
nacos:
discovery:
server-addr: localhost:8848
thymeleaf:
cache: false
redis:
host: 192.168.109.101
port: 6379
application:
name: achangmall-cart
server:
port: 30000
- 網關配置路由映射achangmall-gateway/src/main/resources/application.yml
- id: cart_route
uri: lb://achangmall-cart
predicates:
- Host=cart.achangmall.com
- 啟動服務測驗,訪問:
http://cart.achangmall.com/
![[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-6NV0o2aD-1634740503568)(C:/Users/PePe/AppData/Roaming/Typora/typora-user-images/image-20211020222801089.png)]](https://img.uj5u.com/2021/10/22/276462220734598.png)
二、業務

- com.achang.achangmall.cart.vo.CartVo
/**
* 購物車1級
*/
public class CartVo {
/**
* 購物車子項資訊
*/
List<CartItemVo> items;
/**
* 商品數量
*/
private Integer countNum;
/**
* 商品型別數量
*/
private Integer countType;
/**
* 商品總價
*/
private BigDecimal totalAmount;
/**
* 減免價格
*/
private BigDecimal reduce = new BigDecimal("0.00");;
public List<CartItemVo> getItems() {
return items;
}
public void setItems(List<CartItemVo> items) {
this.items = items;
}
public Integer getCountNum() {
int count = 0;
if (items != null && items.size() > 0) {
for (CartItemVo item : items) {
count += item.getCount();
}
}
return count;
}
public Integer getCountType() {
int count = 0;
if (items != null && items.size() > 0) {
for (CartItemVo item : items) {
count += 1;
}
}
return count;
}
public BigDecimal getTotalAmount() {
BigDecimal amount = new BigDecimal("0");
// 計算購物項總價
if (!CollectionUtils.isEmpty(items)) {
for (CartItemVo cartItem : items) {
if (cartItem.getCheck()) {
amount = amount.add(cartItem.getTotalPrice());
}
}
}
// 計算優惠后的價格
return amount.subtract(getReduce());
}
public BigDecimal getReduce() {
return reduce;
}
public void setReduce(BigDecimal reduce) {
this.reduce = reduce;
}
}
- com.achang.achangmall.cart.vo.CartItemVo
/**
* 購物車2級--購物項
*/
public class CartItemVo {
private Long skuId;
private Boolean check = true;
private String title;
private String image;
/**
* 商品套餐屬性
*/
private List<String> skuAttrValues;
private BigDecimal price;
private Integer count;
private BigDecimal totalPrice;
public Long getSkuId() {
return skuId;
}
public void setSkuId(Long skuId) {
this.skuId = skuId;
}
public Boolean getCheck() {
return check;
}
public void setCheck(Boolean check) {
this.check = check;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public List<String> getSkuAttrValues() {
return skuAttrValues;
}
public void setSkuAttrValues(List<String> skuAttrValues) {
this.skuAttrValues = skuAttrValues;
}
public BigDecimal getPrice() {
return price;
}
public void setPrice(BigDecimal price) {
this.price = price;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
/**
* 計算當前購物項總價
* @return
*/
public BigDecimal getTotalPrice() {
return this.price.multiply(new BigDecimal("" + this.count));
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
}
- com.achang.achangmall.cart.vo.SkuInfoVo
@Data
public class SkuInfoVo {
private Long skuId;
/**
* spuId
*/
private Long spuId;
/**
* sku名稱
*/
private String skuName;
/**
* sku介紹描述
*/
private String skuDesc;
/**
* 所屬分類id
*/
private Long catalogId;
/**
* 品牌id
*/
private Long brandId;
/**
* 默認圖片
*/
private String skuDefaultImg;
/**
* 標題
*/
private String skuTitle;
/**
* 副標題
*/
private String skuSubtitle;
/**
* 價格
*/
private BigDecimal price;
/**
* 銷量
*/
private Long saleCount;
}
- 引入依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 整合springsession -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
- com.achang.achangmall.cart.config.AchangmallSessionConfig
@Configuration
@EnableRedisHttpSession
public class AchangmallSessionConfig {
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
//放大作用域
cookieSerializer.setDomainName("achangmall.com");
cookieSerializer.setCookieName("ACHANGSESSION");
return cookieSerializer;
}
@Bean
public RedisSerializer<Object> springSessionDefaultRedisSerializer() {
//使用json存盤redis,而不是默認的序列化存盤
return new GenericJackson2JsonRedisSerializer();
}
}
- com.achang.achangmall.cart.config.MyThreadConfig
@EnableConfigurationProperties(ThreadPoolConfigProperties.class)
@Configuration
public class MyThreadConfig {
@Bean
public ThreadPoolExecutor executor(ThreadPoolConfigProperties pool) {
return new ThreadPoolExecutor(
pool.getCoreSize(),
pool.getMaxSize(),
pool.getKeepAliveTime(),
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(100000),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
}
}
- com.achang.achangmall.cart.config.ThreadPoolConfigProperties
@ConfigurationProperties(prefix = "achangmall.thread")
@Data
public class ThreadPoolConfigProperties {
private Integer coreSize;
private Integer maxSize;
private Integer keepAliveTime;
}
- com.achang.achangmall.cart.exception.RuntimeExceptionHandler
@ControllerAdvice
public class RuntimeExceptionHandler {
/**
* 全域統一例外處理
*/
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public R handler(RuntimeException exception) {
return R.error(exception.getMessage());
}
@ExceptionHandler(CartExceptionHandler.class)
public R userHandler(CartExceptionHandler exception) {
return R.error("購物車無此商品");
}
}
- com.achang.achangmall.cart.exception.CartExceptionHandler
public class CartExceptionHandler extends RuntimeException {}
- com.achang.achangmall.cart.feign.ProductFeignService
@FeignClient("achangmall-product")
public interface ProductFeignService {
/**
* 根據skuId查詢sku資訊
*/
@RequestMapping("/product/skuinfo/info/{skuId}")
R getInfo(@PathVariable("skuId") Long skuId);
/**
* 根據skuId查詢pms_sku_sale_attr_value表中的資訊
*/
@GetMapping(value = "/product/skusaleattrvalue/stringList/{skuId}")
List<String> getSkuSaleAttrValues(@PathVariable("skuId") Long skuId);
/**
* 根據skuId查詢當前商品的最新價格
*/
@GetMapping(value = "/product/skuinfo/{skuId}/price")
BigDecimal getPrice(@PathVariable("skuId") Long skuId);
}
- com.achang.achangmall.cart.intercept.CartIntercept
@Data
public class UserInfoTo {
private Long userId;
private String userKey;//一定存在
/**
* 是否臨時用戶
*/
private Boolean tempUser = false;
}
- 攔截器com.achang.achangmall.cart.intercept.CartIntercept
@Component
public class CartIntercept implements HandlerInterceptor {
public static ThreadLocal<UserInfoTo> toThreadLocal = new ThreadLocal<>();
//在目標方法執行之前
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
UserInfoTo userInfoTo = new UserInfoTo();
HttpSession session = request.getSession();
MemberResponseVo memberResponseVo = (MemberResponseVo) session.getAttribute(LOGIN_USER);
if (memberResponseVo != null) {
//用戶登錄了
userInfoTo.setUserId(memberResponseVo.getId());
}
Cookie[] cookies = request.getCookies();
if (cookies != null && cookies.length > 0) {
for (Cookie cookie : cookies) {
//user-key
String name = cookie.getName();
if (name.equals(TEMP_USER_COOKIE_NAME)) {
userInfoTo.setUserKey(cookie.getValue());
//標記為已是臨時用戶
userInfoTo.setTempUser(true);
}
}
}
//如果沒有臨時用戶一定分配一個臨時用戶
if (StringUtils.isEmpty(userInfoTo.getUserKey())) {
String uuid = UUID.randomUUID().toString();
userInfoTo.setUserKey(uuid);
}
//目標方法執行之前
toThreadLocal.set(userInfoTo);
return true;
}
//業務執行之后,分配臨時用戶來瀏覽器保存
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
//獲取當前用戶的值
UserInfoTo userInfoTo = toThreadLocal.get();
//如果沒有臨時用戶一定保存一個臨時用戶
if (!userInfoTo.getTempUser()) {
//創建一個cookie
Cookie cookie = new Cookie(TEMP_USER_COOKIE_NAME, userInfoTo.getUserKey());
//擴大作用域
cookie.setDomain("achangmall.com");
//設定過期時間
cookie.setMaxAge(TEMP_USER_COOKIE_TIMEOUT);
response.addCookie(cookie);
}
toThreadLocal.remove();
}
}
- com.achang.achangmall.cart.to.UserInfoTo
@Data
public class UserInfoTo {
private Long userId;
private String userKey;//一定存在
/**
* 是否臨時用戶
*/
private Boolean tempUser = false;
}
- com.achang.common.constant.CartConstant
public class CartConstant {
public final static String TEMP_USER_COOKIE_NAME = "user-key";
public final static int TEMP_USER_COOKIE_TIMEOUT = 60*60*24*30;
public final static String CART_PREFIX = "achangmall:cart:";
}
- com.achang.achangmall.cart.intercept.AchangmallWebConfig配置攔截器,讓其生效
@Configuration
public class AchangmallWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CartIntercept())//注冊攔截器
.addPathPatterns("/**");
}
}
- achangmall-product/src/main/resources/mapper/product/SkuSaleAttrValueDao.xml
<select id="getSkuSaleAttrValuesAsStringList" resultType="java.lang.String">
SELECT
CONCAT( attr_name, ":", attr_value )
FROM
pms_sku_sale_attr_value
WHERE
sku_id = #{skuId}
</select>
- com.achang.achangmall.product.service.impl.SkuSaleAttrValueServiceImpl
@Override
public List<String> getSkuSaleAttrValuesAsStringList(Long skuId) {
SkuSaleAttrValueDao baseMapper = this.baseMapper;
List<String> stringList = baseMapper.getSkuSaleAttrValuesAsStringList(skuId);
return stringList;
}
- com.achang.achangmall.product.app.SkuSaleAttrValueController
@GetMapping(value = "/stringList/{skuId}")
public List<String> getSkuSaleAttrValues(@PathVariable("skuId") Long skuId) {
List<String> stringList = skuSaleAttrValueService.getSkuSaleAttrValuesAsStringList(skuId);
return stringList;
}
- com.achang.achangmall.cart.controller.CartController
@Controller
public class CartController {
@Resource
private CartService cartService;
/**
* 獲取當前用戶的購物車商品項
* @return
*/
@GetMapping(value = "/currentUserCartItems")
@ResponseBody
public List<CartItemVo> getCurrentCartItems() {
List<CartItemVo> cartItemVoList = cartService.getUserCartItems();
return cartItemVoList;
}
/**
* 去購物車頁面的請求
* 瀏覽器有一個cookie:user-key 標識用戶的身份,一個月過期
* 如果第一次使用jd的購物車功能,都會給一個臨時的用戶身份:
* 瀏覽器以后保存,每次訪問都會帶上這個cookie;
*
* 登錄:session有
* 沒登錄:按照cookie里面帶來user-key來做
* 第一次,如果沒有臨時用戶,自動創建一個臨時用戶
*
*/
@GetMapping(value = "/cart.html")
public String cartListPage(Model model) throws ExecutionException, InterruptedException {
//快速得到用戶資訊:id,user-key
// UserInfoTo userInfoTo = CartInterceptor.toThreadLocal.get();
CartVo cartVo = cartService.getCart();
model.addAttribute("cart",cartVo);
return "cartList";
}
/**
* 添加商品到購物車
* attributes.addFlashAttribute():將資料放在session中,可以在頁面中取出,但是只能取一次
* attributes.addAttribute():將資料放在url后面
*/
@GetMapping(value = "/addCartItem")
public String addCartItem(@RequestParam("skuId") Long skuId,
@RequestParam("num") Integer num,
RedirectAttributes attributes) throws ExecutionException, InterruptedException {
cartService.addToCart(skuId,num);
attributes.addAttribute("skuId",skuId);
return "redirect:http://cart.achangmall.com/addToCartSuccessPage.html";
}
/**
* 跳轉到添加購物車成功頁面
*/
@GetMapping(value = "/addToCartSuccessPage.html")
public String addToCartSuccessPage(@RequestParam("skuId") Long skuId,Model model) {
//重定向到成功頁面,再次查詢購物車資料即可
CartItemVo cartItemVo = cartService.getCartItem(skuId);
model.addAttribute("cartItem",cartItemVo);
return "success";
}
/**
* 商品是否選中
*/
@GetMapping(value = "/checkItem")
public String checkItem(@RequestParam(value = "skuId") Long skuId,
@RequestParam(value = "checked") Integer checked) {
cartService.checkItem(skuId,checked);
return "redirect:http://cart.achangmall.com/cart.html";
}
/**
* 改變商品數量
*/
@GetMapping(value = "/countItem")
public String countItem(@RequestParam(value = "skuId") Long skuId,
@RequestParam(value = "num") Integer num) {
cartService.changeItemCount(skuId,num);
return "redirect:http://cart.achangmall.com/cart.html";
}
/**
* 洗掉商品資訊
*/
@GetMapping(value = "/deleteItem")
public String deleteItem(@RequestParam("skuId") Integer skuId) {
cartService.deleteIdCartInfo(skuId);
return "redirect:http://cart.achangmall.com/cart.html";
}
}
- com.achang.achangmall.cart.service.impl.CartServiceImpl
@Slf4j
@Service("cartService")
public class CartServiceImpl implements CartService {
@Autowired
private StringRedisTemplate redisTemplate;
@Autowired
private ProductFeignService productFeignService;
@Autowired
private ThreadPoolExecutor executor;
@Override
public CartItemVo addToCart(Long skuId, Integer num) throws ExecutionException, InterruptedException {
//拿到要操作的購物車資訊
BoundHashOperations<String, Object, Object> cartOps = getCartOps();
//判斷Redis是否有該商品的資訊
String productRedisValue = (String) cartOps.get(skuId.toString());
//如果沒有就添加資料
if (StringUtils.isEmpty(productRedisValue)) {
//2、添加新的商品到購物車(redis)
CartItemVo cartItemVo = new CartItemVo();
//開啟第一個異步任務
CompletableFuture<Void> getSkuInfoFuture = CompletableFuture.runAsync(() -> {
//1、遠程查詢當前要添加商品的資訊
R productSkuInfo = productFeignService.getInfo(skuId);
SkuInfoVo skuInfo = productSkuInfo.getData("skuInfo", new TypeReference<SkuInfoVo>() {});
//資料賦值操作
cartItemVo.setSkuId(skuInfo.getSkuId());
cartItemVo.setTitle(skuInfo.getSkuTitle());
cartItemVo.setImage(skuInfo.getSkuDefaultImg());
cartItemVo.setPrice(skuInfo.getPrice());
cartItemVo.setCount(num);
}, executor);
//開啟第二個異步任務
CompletableFuture<Void> getSkuAttrValuesFuture = CompletableFuture.runAsync(() -> {
//2、遠程查詢skuAttrValues組合資訊
List<String> skuSaleAttrValues = productFeignService.getSkuSaleAttrValues(skuId);
cartItemVo.setSkuAttrValues(skuSaleAttrValues);
}, executor);
//等待所有的異步任務全部完成
CompletableFuture.allOf(getSkuInfoFuture, getSkuAttrValuesFuture).get();
String cartItemJson = JSON.toJSONString(cartItemVo);
cartOps.put(skuId.toString(), cartItemJson);
return cartItemVo;
} else {
//購物車有此商品,修改數量即可
CartItemVo cartItemVo = JSON.parseObject(productRedisValue, CartItemVo.class);
cartItemVo.setCount(cartItemVo.getCount() + num);
//修改redis的資料
String cartItemJson = JSON.toJSONString(cartItemVo);
cartOps.put(skuId.toString(),cartItemJson);
return cartItemVo;
}
}
@Override
public CartItemVo getCartItem(Long skuId) {
//拿到要操作的購物車資訊
BoundHashOperations<String, Object, Object> cartOps = getCartOps();
String redisValue = (String) cartOps.get(skuId.toString());
CartItemVo cartItemVo = JSON.parseObject(redisValue, CartItemVo.class);
return cartItemVo;
}
/**
* 獲取用戶登錄或者未登錄購物車里所有的資料
*/
@Override
public CartVo getCart() throws ExecutionException, InterruptedException {
CartVo cartVo = new CartVo();
UserInfoTo userInfoTo = CartIntercept.toThreadLocal.get();
if (userInfoTo.getUserId() != null) {
//1、登錄
String cartKey = CART_PREFIX + userInfoTo.getUserId();
//臨時購物車的鍵
String temptCartKey = CART_PREFIX + userInfoTo.getUserKey();
//2、如果臨時購物車的資料還未進行合并
List<CartItemVo> tempCartItems = getCartItems(temptCartKey);
if (tempCartItems != null) {
//臨時購物車有資料需要進行合并操作
for (CartItemVo item : tempCartItems) {
addToCart(item.getSkuId(),item.getCount());
}
//清除臨時購物車的資料
clearCartInfo(temptCartKey);
}
//3、獲取登錄后的購物車資料【包含合并過來的臨時購物車的資料和登錄后購物車的資料】
List<CartItemVo> cartItems = getCartItems(cartKey);
cartVo.setItems(cartItems);
} else {
//沒登錄
String cartKey = CART_PREFIX + userInfoTo.getUserKey();
//獲取臨時購物車里面的所有購物項
List<CartItemVo> cartItems = getCartItems(cartKey);
cartVo.setItems(cartItems);
}
return cartVo;
}
/**
* 獲取到我們要操作的購物車
*/
private BoundHashOperations<String, Object, Object> getCartOps() {
//先得到當前用戶資訊
UserInfoTo userInfoTo = CartIntercept.toThreadLocal.get();
String cartKey = "";
if (userInfoTo.getUserId() != null) {
//gulimall:cart:1
cartKey = CART_PREFIX + userInfoTo.getUserId();
} else {
cartKey = CART_PREFIX + userInfoTo.getUserKey();
}
//系結指定的key操作Redis
BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(cartKey);
return operations;
}
/**
* 獲取購物車里面的資料
*/
private List<CartItemVo> getCartItems(String cartKey) {
//獲取購物車里面的所有商品
BoundHashOperations<String, Object, Object> operations = redisTemplate.boundHashOps(cartKey);
List<Object> values = operations.values();
if (values != null && values.size() > 0) {
List<CartItemVo> cartItemVoStream = values.stream().map((obj) -> {
String str = (String) obj;
CartItemVo cartItem = JSON.parseObject(str, CartItemVo.class);
return cartItem;
}).collect(Collectors.toList());
return cartItemVoStream;
}
return null;
}
@Override
public void clearCartInfo(String cartKey) {
redisTemplate.delete(cartKey);
}
@Override
public void checkItem(Long skuId, Integer check) {
//查詢購物車里面的商品
CartItemVo cartItem = getCartItem(skuId);
//修改商品狀態
cartItem.setCheck(check == 1?true:false);
//序列化存入redis中
String redisValue = JSON.toJSONString(cartItem);
BoundHashOperations<String, Object, Object> cartOps = getCartOps();
cartOps.put(skuId.toString(),redisValue);
}
/**
* 修改購物項數量
*/
@Override
public void changeItemCount(Long skuId, Integer num) {
//查詢購物車里面的商品
CartItemVo cartItem = getCartItem(skuId);
cartItem.setCount(num);
BoundHashOperations<String, Object, Object> cartOps = getCartOps();
//序列化存入redis中
String redisValue = JSON.toJSONString(cartItem);
cartOps.put(skuId.toString(),redisValue);
}
/**
* 洗掉購物項
*/
@Override
public void deleteIdCartInfo(Integer skuId) {
BoundHashOperations<String, Object, Object> cartOps = getCartOps();
cartOps.delete(skuId.toString());
}
@Override
public List<CartItemVo> getUserCartItems() {
List<CartItemVo> cartItemVoList = new ArrayList<>();
//獲取當前用戶登錄的資訊
UserInfoTo userInfoTo = CartIntercept.toThreadLocal.get();
//如果用戶未登錄直接回傳null
if (userInfoTo.getUserId() == null) {
return null;
} else {
//獲取購物車項
String cartKey = CART_PREFIX + userInfoTo.getUserId();
//獲取所有的
List<CartItemVo> cartItems = getCartItems(cartKey);
if (cartItems == null) {
throw new CartExceptionHandler();
}
//篩選出選中的
cartItemVoList = cartItems.stream()
.filter(items -> items.getCheck())
.map(item -> {
//更新為最新的價格(查詢資料庫)
BigDecimal price = productFeignService.getPrice(item.getSkuId());
item.setPrice(price);
return item;
})
.collect(Collectors.toList());
}
return cartItemVoList;
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/330272.html
標籤:其他
