做網(wǎng)上水果網(wǎng)站的調(diào)查百度sem代運營
文章目錄
- 1、確認下單:購物車頁面點擊去結(jié)算
- 1.1、在OrderController類中創(chuàng)建 trade 方法
- 1.2、在CartController類中創(chuàng)建 checkedCartInfos
- 1.3、CartServiceImpl 實現(xiàn) checkedCartInfos的業(yè)務功能
- 1.4、在service-cart-client模塊下定義遠程openFeign接口
- 1.5、在SpzxOrderApplication類上加上@EnableFeignClients
- 1.6、OrderServiceImpl 實現(xiàn) trade的業(yè)務邏輯
- 1.7、此時啟動 SpzxOrderApplication
- 2、 openFeign攔截器使用
- 2.1、使用feign攔截器攔截請求,獲取token,重新傳遞token
- 2.1.1、CartClientInterceptor
- 2.1.2、@EnableCartClientConfig
- 2.1.3、SpzxOrderApplication
1、確認下單:購物車頁面點擊去結(jié)算
- 點擊
去結(jié)算
這個按鈕,會發(fā)起一個請求,這個請求是trade
,然后展示我們要購買的商品
和商品的總金額
1.1、在OrderController類中創(chuàng)建 trade 方法
@RestController
@Tag(name = "訂單管理模塊", description = "訂單管理模塊")
@RequestMapping("/api/order/orderInfo")
public class OrderController {@Resourceprivate OrderService orderService;//查詢購物車中選中的購物項列表 轉(zhuǎn)為 orderItem 列表交給前端展示@Operation(summary = "確認下單:購物車頁面點擊去結(jié)算")@GetMapping("/auth/trade")public Result trade() {TradeVo tradeVo = orderService.trade();return Result.ok(tradeVo);}
}
1.2、在CartController類中創(chuàng)建 checkedCartInfos
@RestController
@RequestMapping("/api/order/cart")
@Tag(name = "購物車模塊")
public class CartController {//只要請求頭中攜帶token,不需要再傳用戶id@Operation(summary = "查詢用戶購物車已選中購物項列表")@GetMapping("/auth/checkedCartInfos")public Result checkedCartInfos(){List<CartInfo> cartInfos = cartService.checkedCartInfos();return Result.ok(cartInfos);}
}
1.3、CartServiceImpl 實現(xiàn) checkedCartInfos的業(yè)務功能
@Service
public class CartServiceImpl implements CartService {@Resourceprivate RedisTemplate redisTemplate;private BoundHashOperations getUserCart() {UserInfo userInfo = SpzxServiceAuthInterceptor.THREAD_LOCAL.get();BoundHashOperations ops = redisTemplate.boundHashOps("spzx:cart:" + userInfo.getId());return ops;}@Overridepublic List<CartInfo> checkedCartInfos() {//泛型1:redis鍵類型,泛型2:hash的key類型, 泛型3:hash的value的類型BoundHashOperations<String,String,CartInfo> userCart = getUserCart();return userCart.values().stream().filter(cartInfo -> cartInfo.getIsChecked()==1).toList();}
}
1.4、在service-cart-client模塊下定義遠程openFeign接口
@FeignClient(value = "service-cart")
public interface CartClient {@GetMapping("/api/order/cart/auth/checkedCartInfos")public Result<List<CartInfo>> checkedCartInfos();@DeleteMapping("/api/order/cart/auth/delCheckedCartInfos")public Result<Void> delCheckedCartInfos();
}
1.5、在SpzxOrderApplication類上加上@EnableFeignClients
@SpringBootApplication
@EnableSpzxServiceAuth
@EnableFeignClients(basePackages = "com.atguigu.spzx")
@EnableCartClientConfig
@MapperScan(basePackages = "com.atguigu.spzx.order.mapper")
@EnableTransactionManagement
public class SpzxOrderApplication {public static void main(String[] args){SpringApplication.run(SpzxOrderApplication.class,args);}
}
1.6、OrderServiceImpl 實現(xiàn) trade的業(yè)務邏輯
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, OrderInfo> implements OrderService {@Resourceprivate CartClient cartClient;@Resourceprivate StringRedisTemplate stringRedisTemplate;@Overridepublic TradeVo trade() {//1、查詢 當前用戶 的購物車中已選中的購物項列表(cart服務管理購物車數(shù)據(jù))Result<List<CartInfo>> cartInfos = cartClient.checkedCartInfos();if (cartInfos.getCode() != 200) {throw new SpzxException(ResultCodeEnum.FAIL,null);}List<CartInfo> cartInfoList = cartInfos.getData();if (CollectionUtils.isEmpty(cartInfoList)) {//沒有已選中的購物項throw new SpzxException(ResultCodeEnum.FAIL,null);}Long token = IdUtil.getSnowflake(1,1).nextId();//將token存到redis:redis的大key問題stringRedisTemplate.opsForValue().set("spzx:order:"+token.toString(), "1", 30, TimeUnit.MINUTES);//2、將購物項列表轉(zhuǎn)為 OrderItem列表List<OrderItem> orderItemList = cartInfoList.stream().map(cartInfo -> {OrderItem orderItem = new OrderItem();orderItem.setOrderId(token);orderItem.setSkuId(cartInfo.getSkuId());orderItem.setSkuName(cartInfo.getSkuName());orderItem.setSkuNum(cartInfo.getSkuNum());orderItem.setSkuPrice(cartInfo.getCartPrice());orderItem.setThumbImg(cartInfo.getImgUrl());return orderItem;}).toList();TradeVo tradeVo = new TradeVo();tradeVo.setOrderItemList(orderItemList);//遍歷每一個訂單項,計算它的小計金額返回//最后對所有小計金額累加 得到總金額tradeVo.setTotalAmount(orderItemList.stream().map(orderItem -> {return orderItem.getSkuPrice().multiply(new java.math.BigDecimal(orderItem.getSkuNum()));}).reduce(BigDecimal::add).get());return tradeVo;}
}
1.7、此時啟動 SpzxOrderApplication
-
點擊 購物車頁面的 去結(jié)算按鈕 發(fā)現(xiàn)報錯NullPointerException
java.lang.NullPointerException: Cannot invoke "com.atguigu.spzx.model.entity.user.UserInfo.getId()"
because the return value of "com.atguigu.spzx.common.util.AuthContextUtil.getUserInfo()" is nullat com.atguigu.spzx.cart.service.impl.CartServiceImpl.getAllCkecked(CartServiceImpl.java:147)
2、 openFeign攔截器使用
2.1、使用feign攔截器攔截請求,獲取token,重新傳遞token
針對service-cart微服務是獲取不到當前登錄用戶的信息。原因:service-order微服務調(diào)用service-cart微服務的時候,是通過openFeign進行調(diào)用,openFeign在調(diào)用的時候會丟失請求頭
2.1.1、CartClientInterceptor
@Component
public class CartClientInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {//1、獲取引入cartClient模塊的 項目 在使用cartClient時 請求報文中的tokenServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = requestAttributes.getRequest();String token = request.getHeader("token");//2、將token設置到feign客戶端的請求報文中requestTemplate.header("token", token);}
}
現(xiàn)在訂單服務無法使用feign攔截器,因為這個組件類放到了com.atguigu.spzx.cart.interceptor下面,訂單服務掃描不到,如果我們想啟用它,可以創(chuàng)建注解,然后把注解加到訂單服務的啟動類上面
2.1.2、@EnableCartClientConfig
@Target({ElementType.TYPE})
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Documented
@Import(value = {CartClientInterceptor.class})
public @interface EnableCartClientConfig {
}
2.1.3、SpzxOrderApplication
@SpringBootApplication
@EnableSpzxServiceAuth
@EnableFeignClients(basePackages = "com.atguigu.spzx")
@EnableCartClientConfig
@MapperScan(basePackages = "com.atguigu.spzx.order.mapper")
@EnableTransactionManagement
public class SpzxOrderApplication {public static void main(String[] args){SpringApplication.run(SpzxOrderApplication.class,args);}
}