电商项目购物车及订单系统实现

概述

购物车和订单是电商项目的核心,本文将简单介绍一下两者的实现。

一、购物车功能实现

1.功能说明

1、商品加入购物车时,不是必须要求登录。

2、计算购物车中商品的总价。当商品数量发生变化时需要重新计算。

3、用户可以删除购物车中的商品。

4、用户下单后,删除购物车的功能。

2.功能分析

1、在用户不登陆的清空下也可以使用购物车,那么就需要把购物车信息放入cookie中。

2、可以把商品信息,存放到pojo中,然后序列化成json存入cookie中。

3、取商品信息可以从cookie中把json数据取出来,然后转换成java对象即可。

4、此功能只需要操作cookie不需要数据库的支持,所以只需要在taotao-portal中实现即可。

5、购物车分有四种动作

a) 添加商品

b) 修改商品数量

c) 删除购物车中的商品

d) 展示购物车商品列表

缺点:换一台电脑后购物车的商品不能同步。

实现的工程:taotao-protal中实现购物车功能。只需要调用商品信息的服务,除此之外不需要和其他系统交互。

3.添加购物车商品

3.1流程分析

在商品详情页面点击“加入购物车”按钮提交一个请求吧商品id传递给Controller,Controller接收id,Controller调用Service根据商品id查询商品基本信息。把商品写入cookie中,加入cookie之前先从cookie中把购物车的商品取出来判断当前购物车商品列表中是否有此商品,如果有数量加一,如果没有添加一个商品,数量为1。展示给用户购物车列表。

创建购物车商品POJO:

public class CartItem {

	private long id;
	private String title;
	private Integer num;
	private long price;
	private String image;
}

3.2Service层

功能:接收一个商品id,数量(默认为1),根据商品id查询商品信息。调用taotao-rest的服务。把商品添加到购物车,先把购物车商品列表取出来,判断列表中是否有此商品,如果有就增加数量就可以了。如果没有把此商品添加到商品列表。返回添加成功Taotaoresult。

//添加购物车商品
@Override
public TaotaoResult addCartItem(long itemId, int num, HttpServletRequest request, HttpServletResponse response) {
    CartItem cartItem =null;
    //取购物车商品列表
    List<CartItem> list = getCartItemList(request);
    //判断购物车商品列表中是否存在此商品
    for (CartItem cItem : list) {
        //如果存在此商品
        if(cItem.getId()==itemId) {
            //增加商品数量
            cItem.setNum(cItem.getNum()+num);
            cartItem=cItem;
            break;
        }
    }
    //没找到
    if(cartItem==null) {
        cartItem = new CartItem();
        //根据商品id查询商品基本信息。
        String json = HttpClientUtil.doGet(REST_BASE_URL + ITEM_INFO_URL + itemId);
        //把json转换成java对象
        TaotaoResult taotaoResult = TaotaoResult.formatToPojo(json, TbItem.class);
        if(taotaoResult.getStatus()==200) {
            TbItem item = (TbItem) taotaoResult.getData();
            cartItem.setId(item.getId());
            cartItem.setTitle(item.getTitle());
            cartItem.setImage(item.getImage() == null ? "":item.getImage().split(",")[0]);
            cartItem.setNum(num);
            cartItem.setPrice(item.getPrice());
        }
        //添加到购物车列表
        list.add(cartItem);
    }
    //把购物车列表写入cookie
    CookieUtils.setCookie(request, response, "TT_CART", JsonUtils.objectToJson(list),true);
    return TaotaoResult.ok();
}

//从cookie中取商品列表
private List<CartItem> getCartItemList(HttpServletRequest request){
    String cartJson = CookieUtils.getCookieValue(request, "TT_CART", true);
    if(cartJson==null)return new ArrayList<>();
    //把json转换成商品列表
    try {
        List<CartItem> list = JsonUtils.jsonToList(cartJson, CartItem.class);
        return list;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return new ArrayList<>();
}

3.3Controller层

接收商品的id和商品的数量,商品数量如果为空默认为1.调用Service向购物车添加商品。展示添加成功页面。

请求的url:http://localhost:8082/cart/add/144141542125084.html

@Controller
@RequestMapping("/cart")
public class CartController {

	@Autowired
	private CartService cartService;
	
	@RequestMapping("/add/{itemId}")
	public String addCartItem(@PathVariable Long itemId, 
			@RequestParam(defaultValue="1")Integer num, 
			HttpServletRequest request, HttpServletResponse response) {
		TaotaoResult result = cartService.addCartItem(itemId, num, request, response);
		return "redirect:/cart/cart.html";
	}
	
}

4.展示购物车列表

需要展示购物车页面,没有参数,只需要从cookie中把商品列表取出来,展示到页面即可。

4.1Service层

@Override
public List<CartItem> getCartItemList(HttpServletRequest request, HttpServletResponse response) {
    List<CartItem> itemList = getCartItemList(request);
    return itemList;
}

4.2Controller层

@RequestMapping("/cart")
public String showCart(HttpServletRequest request, HttpServletResponse response, Model model) {
    List<CartItem> list = cartService.getCartItemList(request, response);
    model.addAttribute("cartList", list);
    return "cart";
}

5.购物车商品数量修改

电商项目购物车及订单系统实现_第1张图片

5.1Service层

@Override
public TaotaoResult updateCartItem(long itemId, int num,
                                   HttpServletRequest request, HttpServletResponse response) {
    //取购物车商品列表
    List<CartItem> list = getCartItemList(request);
    for (CartItem cItem : list) {
        if(cItem.getId()==itemId) {
            cItem.setNum(num);
            break;
        }
    }
    return TaotaoResult.ok();
}

5.2Controller层

@RequestMapping("/update")
public String updateCart(Long itemId,Integer num,HttpServletRequest request, HttpServletResponse response) {
    TaotaoResult result = cartService.updateCartItem(itemId, num, request, response);
    return "cart";
}

6.删除购物车商品

在购物车页面中点击删除连接,接收要删除的商品id,从cookie中把商品找到删除,重新写入cookie,重新展示购物车页面。

6.1Service层

@Override
public TaotaoResult deleteCartItem(long itemId, HttpServletRequest request, HttpServletResponse response) {
    //从cookie中取购物车商品列表
    List<CartItem> itemList = getCartItemList(request);
    //从列表中找到此商品
    for (CartItem cartItem : itemList) {
        if (cartItem.getId() == itemId) {
            itemList.remove(cartItem);
            break;
        }		 
    }
    //把购物车列表重新写入cookie
    CookieUtils.setCookie(request, response, "TT_CART", JsonUtils.objectToJson(itemList), true);

    return TaotaoResult.ok();
}

6.2Controller层

@RequestMapping("/delete/{itemId}")
public String deleteCartItem(@PathVariable Long itemId, 
                             HttpServletRequest request, HttpServletResponse response) {
    cartService.deleteCartItem(itemId, request, response);
    return "redirect:/cart/cart.html";
}

7.目前购物车存在的问题

1、更换设备购物车商品不能同步

a) 不能把购物车商品保存到数据库

b) 要求用户登录才能同步信息

c) 可以把购物车信息保存到redis中,key就是用户,value就是购物车列表

d) 购物车商品合并的问题。

2、提交订单后购物车商品需要清空。

二、订单系统的实现

1.系统架构

电商项目购物车及订单系统实现_第2张图片

2.订单表结构

订单表:

电商项目购物车及订单系统实现_第3张图片

订单商品表:

电商项目购物车及订单系统实现_第4张图片

物流表:

电商项目购物车及订单系统实现_第5张图片

3.创建工程

创建taotao-order工程,ssm整合参照taotao-rest

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<parent>
		<groupId>com.taotaogroupId>
		<artifactId>taotao-parentartifactId>
		<version>0.0.1-SNAPSHOTversion>
	parent>
	<groupId>com.taotaogroupId>
	<artifactId>taotao-orderartifactId>
	<version>0.0.1-SNAPSHOTversion>
	<packaging>warpackaging>
	<dependencies>
		<dependency>
			<groupId>com.taotaogroupId>
			<artifactId>taotao-manager-mapperartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
		
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-contextartifactId>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-beansartifactId>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-webmvcartifactId>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-jdbcartifactId>
		dependency>
		<dependency>
			<groupId>org.springframeworkgroupId>
			<artifactId>spring-aspectsartifactId>
		dependency>
		<dependency>
			<groupId>javax.servletgroupId>
			<artifactId>servlet-apiartifactId>
			<scope>providedscope>
		dependency>
		<dependency>
			<groupId>javax.servletgroupId>
			<artifactId>jsp-apiartifactId>
			<scope>providedscope>
		dependency>
		
		<dependency>
			<groupId>redis.clientsgroupId>
			<artifactId>jedisartifactId>
		dependency>
	dependencies>
	<build>
		
		<plugins>
			<plugin>
				<groupId>org.apache.tomcat.mavengroupId>
				<artifactId>tomcat7-maven-pluginartifactId>
				<configuration>
					<port>8086port>
					<path>/path>
				configuration>
			plugin>
		plugins>
	build>
project>

4.接口服务说明

4.1创建接口

用户使用portal创建订单、android、ios、微信商城提交订单时使用。

电商项目购物车及订单系统实现_第6张图片

4.2根据订单ID查询订单

请求方法 GET
URL http://order.taotao.com/order/info/{orderId}
参数说明 orderId:订单编号
示例 http://order.taotao.com/order/info/31414485440695
返回值 { “status”: 200, “msg”: “OK”, “data”: { “orderId”:“100544”, “payment”: 5288, “paymentType”:1 “status”:1 “createTime”:“2015-01-01 08:22:14” “postFee”: 0, “userId”: “3”, “buyerMessage”: null, “buyerNick”: “zhang123”, “orderItems”: [ { “itemId”: “9”, “num”: 1, “title”: “苹果(Apple)iPhone 6 (A1586) 16GB 金色 移动联通电信4G手机3”, “price”: 5288, “totalFee”: 5288, “picPath”: “http://image.taotao.com/images/2015/03/06/2015030610045320609720.jpg” } ], “orderShipping”: { “receiverName”: “张三”, “receiverPhone”: “”, “receiverMobile”: “15800000000”, “receiverState”: “上海”, “receiverCity”: “上海”, “receiverDistrict”: “闵行区”, “receiverAddress”: “三鲁公路3279号 明浦广场 3号楼 205室”, “receiverZip”: “200000” } } }

4.3根据用户分页查询订单

电商项目购物车及订单系统实现_第7张图片

4.4修改订单状态

请求方法 POST
URL http://order.taotao.com/order/changeStatus
参数说明 { “orderId”: “100544”,//订单编号 “status”: 2, //订单状态 “paymentTime”: “1414489420444” //付款时间 }
示例 http://sso.taotao.com/user/check/zhangsan;t=1
返回值 { status: 200 //200 成功 msg: “OK” // 返回信息消息 data: null // 返回数据 }

5.创建订单接口

5.1订单号的生成

解决方案一(不能使用):

使用mysql的自增长。

优点:不需要我们自己生成订单号,mysql会自动生成。

缺点:如果订单表数量太大时需要分库分表,此时订单号会重复。如果数据备份后再恢复,订单号会变。

方案二:日期+随机数

采用毫秒+随机数。

缺点:仍然有重复的可能。不建议采用此方案。在没有更好的解决方案之前可以使用。

方案三:使用UUID

优点:不会重复。

缺点:长。可读性查。不建议使用。

方案四:可读性好,不能太长。一般订单都是全数字的。可以使用redis的incr命令生成订单号。

优点:可读性好,不会重复

缺点:需要搭建redis服务器。

使用方案四,在resource.properties配置

#订单号生成key
ORDER_GEN_KEY=ORDER_GEN_KEY
#初始化订单号
ORDER_INIT_ID=10054
#订单明细生成key
ORDER_DETAIL_GEN_KEY=ORDER_DETAIL_GEN_KEY

5.2Service层

@Service
public class OrderServiceImpl implements OrderService {

	@Autowired
	private TbOrderMapper orderMapper;
	@Autowired
	private TbOrderItemMapper orderItemMapper;
	@Autowired
	private TbOrderShippingMapper orderShippingMapper;
	@Autowired
	private JedisClient jedisClient;
	
	@Value("${ORDER_GEN_KEY}")
	private String ORDER_GEN_KEY;
	@Value("${ORDER_INIT_ID}")
	private String ORDER_INIT_ID;
	@Value("${ORDER_DETAIL_GEN_KEY}")
	private String ORDER_DETAIL_GEN_KEY;
	
	
	@Override
	public TaotaoResult createOrder(TbOrder order, List<TbOrderItem> itemList, TbOrderShipping orderShipping) {
		//向订单表中插入记录
		//获得订单号
		String string = jedisClient.get(ORDER_GEN_KEY);
		if (StringUtils.isBlank(string)) {
			jedisClient.set(ORDER_GEN_KEY, ORDER_INIT_ID);
		}
		long orderId = jedisClient.incr(ORDER_GEN_KEY);
		//补全pojo的属性
		order.setOrderId(orderId + "");
		//状态:1、未付款,2、已付款,3、未发货,4、已发货,5、交易成功,6、交易关闭
		order.setStatus(1);
		Date date = new Date();
		order.setCreateTime(date);
		order.setUpdateTime(date);
		//0:未评价 1:已评价
		order.setBuyerRate(0);
		//向订单表插入数据
		orderMapper.insert(order);
		//插入订单明细
		for (TbOrderItem tbOrderItem : itemList) {
			//补全订单明细
			//取订单明细id
			long orderDetailId = jedisClient.incr(ORDER_DETAIL_GEN_KEY);
			tbOrderItem.setId(orderDetailId + "");
tbOrderItem.setOrderId(orderId + ""); 
			//向订单明细插入记录
			orderItemMapper.insert(tbOrderItem);
		}
		//插入物流表
		//补全物流表的属性
		orderShipping.setOrderId(orderId + "");
		orderShipping.setCreated(date);
		orderShipping.setUpdated(date);
		orderShippingMapper.insert(orderShipping);
		
		return TaotaoResult.ok(orderId);
	}

}

5.3Controller层

接收一个json格式的字符串作为参数。需要使用@RequestBody注解。需要使用一个pojo接收参数。

创建一个对应json格式的pojo。

public class Order extends TbOrder {
	private List<TbOrderItem> orderItems;
	private TbOrderShipping orderShipping;
}
@Controller
public class OrderController {

	@Autowired
	private OrderService orderService;
	
	@RequestMapping("/create")
	@ResponseBody
	public TaotaoResult createOrder(@RequestBody Order order) {
		try {
			TaotaoResult result = orderService.createOrder(order, order.getOrderItems(), order.getOrderShipping());
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
		}
	}
}

6.根据订单ID查询订单

6.1Service层

@Override
public TaotaoResult selectOrderByOrderId(String orderId) {
    Order order = new Order();
    TbOrder tbOrder = orderMapper.selectByPrimaryKey(orderId);
    order = (Order) tbOrder;
    TbOrderShipping tbOrderShipping = orderShippingMapper.selectByPrimaryKey(orderId);
    order.setOrderShipping(tbOrderShipping);
    TbOrderItemExample example = new TbOrderItemExample();
    Criteria criteria = example.createCriteria();
    criteria.andOrderIdEqualTo(orderId);
    List<TbOrderItem> list = orderItemMapper.selectByExample(example);
    order.setOrderItems(list);
    return TaotaoResult.ok(order);
}

6.2Controller层

@RequestMapping("/info/{orderId}")
@ResponseBody
public TaotaoResult selectOrderByOrderId(@PathVariable String orderId) {
    TaotaoResult result = orderService.selectOrderByOrderId(orderId);
    return result;
}

三、前端系统实现下单功能

1.下单流程

电商项目购物车及订单系统实现_第8张图片

2.订单确认页面

1、要求用户登录。

2、根据用户id查询用户的收货地址列表。

3、在此页面展示购物车的商品列表。

4、需要计算订单的总金额(包括运费)展示给用户。

2.1要求用户登录

修改springmvc.xml拦截所有以:/order/**形式的url

电商项目购物车及订单系统实现_第9张图片

2.2根据用户id查询用户的收货地址列表

在实际的商城中是必须有此功能,需要taotao-rest发布服务,由taotao-portal根据用户查询用户的收货地址列表。

在此,使用静态数据模拟。

2.3展示购物车的商品列表

需要从cookie中把购物车商品列表取出,传递给order-cart.jsp。

@Controller
@RequestMapping("/order")
public class OrderController {
	
	@Autowired
	private CartService cartService;

	@RequestMapping("/order-cart")
	public String showOrderCart(HttpServletRequest request, HttpServletResponse response, Model model) {
		//取购物车商品列表
		List<CartItem> list = cartService.getCartItemList(request, response);
		//传递给页面
		model.addAttribute("cartList", list);
		
		return "order-cart";
	}
}

3.提交订单

3.1需求分析

点击“提交订单”按钮把用户已经确认的订单信息,提交给后台。提交一个隐藏的表单,其中包含订单基本信息,订单名称以及配送信息。需要使用一个包装的pojo接收表单中的内容。

电商项目购物车及订单系统实现_第10张图片

在resource.properties配置

#订单系统基础url
ORDER_BASE_URL=http://localhost:8086/order
#创建订单服务
ORDER_CREATE_URL=/create

3.2Service层

接收Order对象,调用taotao-order提供的服务,提交订单。需要把pojo转换成json数据。调用taotao-order提供的服务返回taotaoResult,包含订单号。

参数:Order 返回值:String(订单号)

@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(Order order) {
		//调用taotao-order的服务提交订单。
		String json = HttpClientUtil.doPostJson(ORDER_BASE_URL + ORDER_CREATE_URL, JsonUtils.objectToJson(order));
		//把json转换成taotaoResult
		TaotaoResult taotaoResult = TaotaoResult.format(json);
		if(taotaoResult.getStatus()==200) {
			Object orderId = taotaoResult.getData();
			return orderId.toString();
		}
		return "";
	}

}

3.3Controller层

@RequestMapping("/create")
public String createOrder(Order order,Model model) {
    try {
        String orderId = orderService.createOrder(order);
        model.addAttribute("orderId", orderId);
        model.addAttribute("payment", order.getPayment());
        model.addAttribute("date", new DateTime().plusDays(3).toString("yyyy-MM-dd"));
        return "success";
    } catch (Exception e) {
        e.printStackTrace();
        model.addAttribute("message", "订单创建出错,请稍后重试");
        return "error/exception";
    }
}

4.成品

电商项目购物车及订单系统实现_第11张图片

结语

常用词汇:啊这。就这。有一说一。寻思。建议。嗷汁宁呐呐。xx也就图一乐,真xx还得xx。凑弟弟往后稍稍⑧。说话带emoji。不会吧不会吧不会真有人以为用不会真有人以为就真有人这么认为了吧。不是吧不是吧。

你可能感兴趣的:(java,java,数据库,mysql,分布式)