购物车和订单的实现
购物车的逻辑写在taotao-portal中
分析:
1、添加购物车不需要用户登录。购物车的数据应该放到cookie中。
2、当向购物车添加同一款商品时,购物车中商品的数量增加。
3、购物车中可以删除商品
4、购物车中可以修改商品数量。商品的总价需要重新计算。
5、点击“结算”按钮要求用户登录。
购物车添加商品service.
逻辑:
1、接收商品id
2、从cookie中购物车商品列表
3、从商品列表中查询列表是否存在此商品
4、如果存在商品的数量加上参数中的商品数量
5、如果不存在,调用rest服务,根据商品id获得商品数据。
6、把商品数据添加到列表中
7、把购物车商品列表写入cookie
8、返回TaotaoResult
@Service
public class CartServiceImpl implements CartService {
@Autowired
private ItemService itemService;
@Value("${COOKIE_EXPIRE}")
private Integer COOKIE_EXPIRE;
@Override
public TaotaoResult addCart(Long itemId, Integer num, HttpServletRequest request,
HttpServletResponse response) {
//1.接收商品id
//从cookie中获取购物车商品列表
List<CartItem> itemList = getCartItemList(request);
//3.从商品列表中查询列表是否存在此商品
//flag用来判断是否找到对应的产品
boolean haveFlg = false;
for(CartItem cartItem : itemList) {
//如果商品存在数量相加
//4.如果存在商品的数量加上参数中的商品数量
if(cartItem.getId().longValue() == itemId) {
cartItem.setNum(cartItem.getNum() + num);
haveFlg = true;
break;
}
}
//5.如果不存在,调用rest服务,根据商品id获得商品数据
if(!haveFlg) {
TbItem item = itemService.getItemById(itemId);
//转换成CartItem
CartItem cartItem = new CartItem();
cartItem.setId(itemId);
cartItem.setNum(num);
cartItem.setPrice(item.getPrice());
cartItem.setTitle(item.getTitle());
//购物车上只会展示一张图片
if(StringUtils.isNoneBlank(item.getImage())) {
String image = item.getImage();
String[] strings = image.split(",");
cartItem.setImage(strings[0]);
}
//添加到购物车商品列表
//6.把商品数据添加到列表中
itemList.add(cartItem);
}
//7.把购物车商品列表写入cookie
CookieUtils.setCookie(request, response, "TT_CART", JsonUtils.objectToJson(itemList), COOKIE_EXPIRE, true);
//返回taotaoResult
return TaotaoResult.ok();
}
/**
* 取购物车商品列表
*/
private List<CartItem> getCartItemList(HttpServletRequest request){
try {
//从cookie中取商品列表
String json = CookieUtils.getCookieValue(request, "TT_CART", true);
//把json转换成java对象
List<CartItem> list = JsonUtils.jsonToList(json, CartItem.class);
return list == null?new ArrayList<CartItem>() : list;
} catch (Exception e) {
return new ArrayList<CartItem>();
}
}
}
购物车中商品数量的加减按钮,删除商品按钮都是要联系到cookie和redis的操作
删除的controller中重定向,点击删除按钮应该重新跳回购物车url
@RequestMapping("/cart/delete/{itemId}")
public String deleteCartItem(@PathVariable Long itemId,
HttpServletResponse response, HttpServletRequest request) {
TaotaoResult result = cartService.deleteCartItem(itemId, request, response);
return "redirect:/cart/cart.html";
}
更换设备后购物车信息不能同步
解决方案:当用户登录后,需要把cookie的购物车信息同步到redis
订单实现
搭建taotao-order
1、接收json数据,需要使用@RequestBody注解。对应提交的json数据格式创建一个pojo接收。
需要使用的表:
tb_order 订单表(一)
tb_order_item 订单明细表(多)
tb_order_shipping 物流表(一)
可以使用订单相关的三个表对应的pojo封装一个pojo接收提交的json数据。注意继承。
public class OrderInfo extends TbOrder{
private List<TbOrderItem> orderItems;//明细表
private TbOrderShipping orderShipping;
public List<TbOrderItem> getOrderItems() {
return orderItems;
}
public void setOrderItems(List<TbOrderItem> orderItems) {
this.orderItems = orderItems;
}
public TbOrderShipping getOrderShipping() {
return orderShipping;
}
public void setOrderShipping(TbOrderShipping orderShipping) {
this.orderShipping = orderShipping;
}
}
2、接收json数据后,把数据插入到响应的表中。
3、使用redis的incr命令(redis是单线程,不会重复)
接收json报文,插入三张表数据,返回订单号的服务Service
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private TbOrderMapper orderMapper;
@Autowired
private TbOrderItemMapper orderItemMapper;
@Autowired
private TbOrderShippingMapper orderShippingMapper;
@Autowired
private JedisClient jedisClient;
@Value("${REDIS_ORDER_GEN_KEY}")
private String REDIS_ORDER_GEN_KEY;
@Value("${ORDER_ID_BEGIN}")
private String ORDER_ID_BEGIN;
@Value("${REDIS_ORDER_DETAIL_GEN_KEY}")
private String REDIS_ORDER_DETAIL_GEN_KEY;
@Override
public TaotaoResult createOrder(OrderInfo orderInfo) {
//一、插入订单表
//1.接收数据OrderInfo
//2.生成订单号
//取订单号
String id = jedisClient.get(REDIS_ORDER_GEN_KEY);
if(StringUtils.isBlank(id)) {
//如果订单号生成key不存在设置初始值
jedisClient.set(REDIS_ORDER_GEN_KEY, ORDER_ID_BEGIN);
}
Long orderId = jedisClient.incr(REDIS_ORDER_GEN_KEY);
//3.补全字段
orderInfo.setOrderId(orderId.toString());
//状态:1.未付款2.已付款3.未发货4.已发货5.交易成功6.交易关闭
orderInfo.setStatus(1);
Date date = new Date();
orderInfo.setCreateTime(date);
orderInfo.setUpdateTime(date);
//4.插入订单表
orderMapper.insert(orderInfo);
//二、插入订单明细
//2.补全字段
List<TbOrderItem> orderItems = orderInfo.getOrderItems();
for(TbOrderItem orderItem : orderItems) {
//1.生成订单明细id,使用redis的incr命令生成
Long detailId = jedisClient.incr(REDIS_ORDER_DETAIL_GEN_KEY);
orderItem.setId(detailId.toString());
//订单号
orderItem.setOrderId(orderId.toString());
//3.插入数据
orderItemMapper.insert(orderItem);
}
//三、插入物流表
TbOrderShipping orderShipping = orderInfo.getOrderShipping();
//1.补全字段
orderShipping.setOrderId(orderId.toString());
orderShipping.setCreated(date);
orderShipping.setUpdated(date);
//2.插入数据
orderShippingMapper.insert(orderShipping);
//返回TaotaoResult包装订单号
return TaotaoResult.ok(orderId);
}
}
对应的controller,注意@RequestBody
@Controller
public class OrderController {
@Autowired
private OrderService orderService;
@RequestMapping(value="/order/create", method=RequestMethod.POST)
@ResponseBody
public TaotaoResult createOrder(@RequestBody OrderInfo orderInfo) {
try {
TaotaoResult result = orderService.createOrder(orderInfo);
return result;
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
}
}
taotao-portal的处理
点击提交订单按钮要确认登录,并且token中有需要的用户信息
拦截器的request和最后的request是同一个,所以可以把用户信息放在request中

在订单确认页面点击“提交订单按钮”进行提交订单的处理。把表单的内容提交给taotao-portal的后台,后台调用taotao-order发布的服务生成订单。展示订单提交成功页面,并且展示订单号。
taotao-portal中调用taotao-order的service
@Service
public class OrderServiceImpl implements OrderService {
@Value("${ORDER_BASE_URL}")
private String ORDER_BASE_URL;
@Value("${ORDER_CREATE_URL}")
private String ORDER_CREATE_URL;
@Override
public String createOrder(OrderInfo orderInfo) {
// 把OrderInfo转换成json
String json = JsonUtils.objectToJson(orderInfo);
//提交订单数据
String jsonResult = HttpClientUtils.doPostJson(ORDER_BASE_URL+ORDER_CREATE_URL, json);
//转换成java对象
TaotaoResult taotaoResult = TaotaoResult.format(jsonResult);
//取订单号
String orderId = taotaoResult.getData().toString();
return orderId;
}
}
Controller接收提交的订单信息,使用OrderInfo接收。调用Service创建订单,跳转到成功页面,并且把订单号传递给页面。
Controller
@RequestMapping(value="/create",method=RequestMethod.POST)
public String createOrder(OrderInfo orderInfo, Model model,HttpServletRequest request) {
//取用户信息
TbUser user = (TbUser) request.getAttribute("user");
//补全orderInfo的属性
orderInfo.setUserId(user.getId());
orderInfo.setBuyerNick(user.getUsername());
//调用服务
String orderId = orderService.createOrder(orderInfo);
//把订单号传递给页面
model.addAttribute("orderId",orderId);
model.addAttribute("payment",orderInfo.getPayment());
DateTime dateTime = new DateTime();
dateTime = dateTime.plusDays(3);
model.addAttribute("date",dateTime.toString("yyyy-MM-dd"));
//返回逻辑视图
return "success";
}