✅P276_商城业务-订单服务-订单确认页完成
大约 2 分钟
下单执行流程
订单服务的执行流程如下图所示
创建防重令牌
编写防重令牌前缀常量
cfmall-order/src/main/java/com/gyz/cfmall/order/constant/OrderConstant.java
public class OrderConstant {
public static final String USER_ORDER_TOKEN_PREFIX = "order:token:";
}
存储防重令牌:4.1 redis存储、4.2 返回页面
com.gyz.cfmall.order.service.impl.OrderServiceImpl#confirmOrder
@Override
public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
//构建OrderConfirmVo
OrderConfirmVo confirmVo = new OrderConfirmVo();
//获取当前用户登录的信息
MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get();
//获取当前线程请求头信息(解决Feign异步调用丢失请求头问题)
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
//开启第一个异步任务
CompletableFuture<Void> addressFuture = CompletableFuture.runAsync(() -> {
//每一个线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);
//1、远程查询所有的收获地址列表
List<MemberAddressVo> address = memberFeignService.getAddress(memberResponseVo.getId());
confirmVo.setMemberAddressVos(address);
}, threadPoolExecutor);
//开启第二个异步任务
CompletableFuture<Void> cartInfoFuture = CompletableFuture.runAsync(() -> {
//每一个线程都来共享之前的请求数据
RequestContextHolder.setRequestAttributes(requestAttributes);
//2、远程查询购物车所有选中的购物项
List<OrderItemVo> currentCartItems = cartFeignService.getCurrentCartItems();
confirmVo.setItems(currentCartItems);
//feign在远程调用之前要构造请求,调用很多的拦截器
}, threadPoolExecutor).thenRunAsync(() -> {
List<OrderItemVo> items = confirmVo.getItems();
List<Long> skuIds = items.stream().map(item -> {
return item.getSkuId();
}).collect(Collectors.toList());
R r = wmsFeignService.getSkuHasStock(skuIds);
List<SkuStockVo> data = r.getData(new TypeReference<List<SkuStockVo>>() {
});
Map<Long, Boolean> collect = data.stream().collect(Collectors.toMap(SkuStockVo::getSkuId, SkuStockVo::getHasStock));
confirmVo.setStocks(collect);
}, threadPoolExecutor);
//3、查询用户积分
Integer integration = memberResponseVo.getIntegration();
confirmVo.setIntegration(integration);
CompletableFuture.allOf(addressFuture, cartInfoFuture).get();
//4、生成防重令牌
String token = UUID.randomUUID().toString().replace("-", "");
//4.1 redis存储
redisTemplate.opsForValue().set(OrderConstant.USER_ORDER_TOKEN_PREFIX + memberResponseVo.getId().toString(), token, 30, TimeUnit.MINUTES);
//4.2 返回页面
confirmVo.setOrderToken(token);
return confirmVo;
}
订单提交数据
京东的结算页中的商品信息是实时获取的,结算的时候会去购物车中再去获取一遍,因此,提交页面的数据Vo没必要提交商品信息
封装订单提交VO
cfmall-order/src/main/java/com/gyz/cfmall/order/vo/OrderSubmitVo.java
package com.gyz.cfmall.order.vo;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class OrderSubmitVo {
/**
* 收获地址的id
*/
private Long addrId;
/**
* 支付方式
*/
private Integer payType;
/**
* 防重令牌
**/
private String orderToken;
/**
* 应付价格
*/
private BigDecimal payPrice;
/**
* 订单备注
*/
private String remarks;
}
前端页面
cfmall-order/src/main/resources/templates/confirm.html
提交表单编写
<form action="http://order.cfmall.com/submitOrder" method="post">
<input id="addrInput" type="hidden" name="addrId" />
<input id="payPriceInput" type="hidden" name="payPrice">
<input name="orderToken" th:value="${confirmOrderData.orderToken}" type="hidden"/>
<button class="tijiao" type="submit">提交订单</button>
</form>
输入框绑定数据
function getFare(addrId) {
$("#addrInput").val(addrId);
$.get("http://cfmall.com/api/ware/wareinfo/fare?addrId=" + addrId, function (resp) {
console.log(resp);
$("#fareEle").text(resp.data.fare);
var total = [[${confirmOrderData.getTotal()}]];
//设置运费
var payPrice = total * 1 + resp.data.fare * 1;
$("#payPriceEle").text(payPrice);
$("#payPriceInput").val(payPrice);
//设置收获地址人信息
$("#recieveAddr").text(resp.data.address.province + " " + resp.data.address.city + " " + " " + resp.data.address.region + resp.data.address.detailAddress);
$("#reciever").text(resp.data.address.name);
})
};
订单提交接口
cfmall-order/src/main/java/com/gyz/cfmall/order/web/OrderWebController.java
@PostMapping("/submitOrder")
public String submitOrder(OrderSubmitVo orderSubmitVo) {
return null;
}