加入购物车
购物车-创建数据表
1.使用use命令先选中store数据库。
USE store;
2.在store数据库中创建t_cart用户数据表。
CREATE TABLE t_cart (
cid INT AUTO_INCREMENT COMMENT '购物车数据id',
uid INT NOT NULL COMMENT '用户id',
pid INT NOT NULL COMMENT '商品id',
price BIGINT COMMENT '加入时商品单价',
num INT COMMENT '商品数量',
created_user VARCHAR(20) COMMENT '创建人',
created_time DATETIME COMMENT '创建时间',
modified_user VARCHAR(20) COMMENT '修改人',
modified_time DATETIME COMMENT '修改时间',
PRIMARY KEY (cid)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
购物车-创建实体类
在com.cy.store.entity包下创建购物车的Cart实体类。
package com.cy.store.entity;
import java.io.Serializable;
/** 购物车数据的实体类 */
public class Cart extends BaseEntity implements Serializable {
private Integer cid;
private Integer uid;
private Integer pid;
private Long price;
private Integer num;
// Generate: Getter and Setter、Generate hashCode() and equals()、toString()
}
购物车-添加购物车-持久层
规划需要执行的SQL语句
向购物车表中插入商品数据的SQL语句大致是:
insert into t_cart (除了cid以外的字段列表) values (匹配的值列表);
如果用户曾经将某个商品加入到购物车过,则点击“加入购物车”按钮只会对购物车中相同商品数量做递增操作。
update t_cart set num=? where cid=?
关于判断“到底应该插入数据,还是修改数量”,可以通过“查询某用户是否已经添加某商品到购物车”来完成。如果查询到某结果,就表示该用户已经将该商品加入到购物车了,如果查询结果为null,则表示该用户没有添加过该商品。
select * from t_cart where uid=? and pid=?
接口与抽象方法
在com.cy.store.mapper包下创建CartMapper接口,并添加抽象相关的方法。
package com.cy.store.mapper;
import com.cy.store.entity.Cart;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
/** 处理购物车数据的持久层接口 */
public interface CartMapper {
/**
* 插入购物车数据
* @param cart 购物车数据
* @return 受影响的行数
*/
Integer insert(Cart cart);
/**
* 修改购物车数据中商品的数量
* @param cid 购物车数据的id
* @param num 新的数量
* @param modifiedUser 修改执行人
* @param modifiedTime 修改时间
* @return 受影响的行数
*/
Integer updateNumByCid(
@Param("cid") Integer cid,
@Param("num") Integer num,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime);
/**
* 根据用户id和商品id查询购物车中的数据
* @param uid 用户id
* @param pid 商品id
* @return 匹配的购物车数据,如果该用户的购物车中并没有该商品,则返回null
*/
Cart findByUidAndPid(
@Param("uid") Integer uid,
@Param("pid") Integer pid);
}
配置SQL映射
1.在resources.mapper文件夹下创建CartMapper.xml文件,并在文件中配置以上三个方法的映射。
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.store.mapper.CartMapper">
<resultMap id="CartEntityMap" type="com.cy.store.entity.Cart">
<id column="cid" property="cid"/>
<result column="created_user" property="createdUser"/>
<result column="created_time" property="createdTime"/>
<result column="modified_user" property="modifiedUser"/>
<result column="modified_time" property="modifiedTime"/>
</resultMap>
<!-- 插入购物车数据:Integer insert(Cart cart) -->
<insert id="insert" useGeneratedKeys="true" keyProperty="cid">
INSERT INTO t_cart (uid, pid, price, num, created_user, created_time, modified_user, modified_time)
VALUES (#{uid}, #{pid}, #{price}, #{num}, #{createdUser}, #{createdTime}, #{modifiedUser}, #{modifiedTime})
</insert>
<!-- 修改购物车数据中商品的数量:
Integer updateNumByCid(
@Param("cid") Integer cid,
@Param("num") Integer num,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime) -->
<update id="updateNumByCid">
UPDATE
t_cart
SET
num=#{num},
modified_user=#{modifiedUser},
modified_time=#{modifiedTime}
WHERE
cid=#{cid}
</update>
<!-- 根据用户id和商品id查询购物车中的数据:
Cart findByUidAndPid(
@Param("uid") Integer uid,
@Param("pid") Integer pid) -->
<select id="findByUidAndPid" resultMap="CartEntityMap">
SELECT
*
FROM
t_cart
WHERE
uid=#{uid} AND pid=#{pid}
</select>
</mapper>
2.在com.cy.store.mapper包下创建CartMapperTests测试类,并添加测试方法。
package com.cy.store.mapper;
import com.cy.store.entity.Cart;
import com.cy.store.entity.Product;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CartMapperTests {
@Autowired
private CartMapper cartMapper;
@Test
public void insert() {
Cart cart = new Cart();
cart.setUid(1);
cart.setPid(2);
cart.setNum(3);
cart.setPrice(4L);
Integer rows = cartMapper.insert(cart);
System.out.println("rows=" + rows);
}
@Test
public void updateNumByCid() {
Integer cid = 1;
Integer num = 10;
String modifiedUser = "购物车管理员";
Date modifiedTime = new Date();
Integer rows = cartMapper.updateNumByCid(cid, num, modifiedUser, modifiedTime);
System.out.println("rows=" + rows);
}
@Test
public void findByUidAndPid() {
Integer uid = 1;
Integer pid = 2;
Cart result = cartMapper.findByUidAndPid(uid, pid);
System.out.println(result);
}
}
购物车-添加购物车-业务层
规划异常
在插入数据时,可能抛出InsertException异常;在修改数据时,可能抛出UpdateException异常。如果不限制购物车中的记录的数量,则没有其它异常。
接口与抽象方法
在com.cy.store.service包下创建ICartService接口,并添加抽象方法。
package com.cy.store.service;
/** 处理商品数据的业务层接口 */
public interface ICartService {
/**
* 将商品添加到购物车
* @param uid 当前登录用户的id
* @param pid 商品的id
* @param amount 增加的数量
* @param username 当前登录的用户名
*/
void addToCart(Integer uid, Integer pid, Integer amount, String username);
}
实现抽象方法
1.创建com.cy.store.service.impl.CartServiceImpl类,并实现ICartService接口,并在类的定义前添加@Service注解。在类中声明CartMapper持久层对象和IProductService处理商品数据的业务对象,并都添加@Autowired注修饰。
package com.cy.store.service.impl;
import com.cy.store.entity.Cart;
import com.cy.store.entity.Product;
import com.cy.store.mapper.CartMapper;
import com.cy.store.service.ICartService;
import com.cy.store.service.IProductService;
import com.cy.store.service.ex.InsertException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Date;
/** 处理购物车数据的业务层实现类 */
@Service
public class CartServiceImpl implements ICartService {
@Autowired
private CartMapper cartMapper;
@Autowired
private IProductService productService;
}
2.在CartServiceImpl类中实现业务层ICartService接口中定义的抽象方法。
@Override
public void addToCart(Integer uid, Integer pid, Integer amount, String username) {
// 根据参数pid和uid查询购物车中的数据
// 判断查询结果是否为null
// 是:表示该用户并未将该商品添加到购物车
// -- 创建Cart对象
// -- 封装数据:uid,pid,amount
// -- 调用productService.findById(pid)查询商品数据,得到商品价格
// -- 封装数据:price
// -- 封装数据:4个日志
// -- 调用insert(cart)执行将数据插入到数据表中
// 否:表示该用户的购物车中已有该商品
// -- 从查询结果中获取购物车数据的id
// -- 从查询结果中取出原数量,与参数amount相加,得到新的数量
// -- 执行更新数量
}
3.addToCart(Integer uid, Integer pid, Integer amount, String username)方法的代码具体实现。
@Override
public void addToCart(Integer uid, Integer pid, Integer amount, String username) {
// 根据参数pid和uid查询购物车中的数据
Cart result = cartMapper.findByUidAndPid(uid, pid);
Integer cid = result.getCid();
Date now = new Date();
// 判断查询结果是否为null
if (result == null) {
// 是:表示该用户并未将该商品添加到购物车
// 创建Cart对象
Cart cart = new Cart();
// 封装数据:uid,pid,amount
cart.setUid(uid);
cart.setPid(pid);
cart.setNum(amount);
// 调用productService.findById(pid)查询商品数据,得到商品价格
Product product = productService.findById(pid);
// 封装数据:price
cart.setPrice(product.getPrice());
// 封装数据:4个日志
cart.setCreatedUser(username);
cart.setCreatedTime(now);
cart.setModifiedUser(username);
cart.setModifiedTime(now);
// 调用insert(cart)执行将数据插入到数据表中
Integer rows = cartMapper.insert(cart);
if (rows != 1) {
throw new InsertException("插入商品数据时出现未知错误,请联系系统管理员");
}
} else {
// 否:表示该用户的购物车中已有该商品
// 从查询结果中获取购物车数据的id
Integer cid = result.getCid();
// 从查询结果中取出原数量,与参数amount相加,得到新的数量
Integer num = result.getNum() + amount;
// 执行更新数量
Integer rows = cartMapper.updateNumByCid(cid, num, username, now);
if (rows != 1) {
throw new InsertException("修改商品数量时出现未知错误,请联系系统管理员");
}
}
}
4.在com.cy.store.service包下创建测试类CartServiceTests类,并编写测试方法。
package com.cy.store.service;
import com.cy.store.entity.Product;
import com.cy.store.service.ex.ServiceException;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class CartServiceTests {
@Autowired
private ICartService cartService;
@Test
public void addToCart() {
try {
Integer uid = 2;
Integer pid = 10000007;
Integer amount = 1;
String username = "Tom";
cartService.addToCart(uid, pid, amount, username);
System.out.println("OK.");
} catch (ServiceException e) {
System.out.println(e.getClass().getSimpleName());
System.out.println(e.getMessage());
}
}
}
购物车-添加购物车-控制器
处理异常
说明:无异常。
设计请求
设计用户提交的请求,并设计响应的方式。
请求路径:/carts/add_to_cart
请求参数:Integer pid, Integer amount, HttpSession session
请求类型:POST
响应结果:JsonResult<Void>
处理请求
1.在com.cy.store.controller包下创建CartController类并继承自BaseController类,添加@RequestMapping(“carts”)和@RestController注解;在类中声明ICartService业务对象,并使用@Autowired注解修饰。
package com.cy.store.controller;
import com.cy.store.service.ICartService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("carts")
public class CartController extends BaseController {
@Autowired
private ICartService cartService;
}
2.在CartController类中添加处理请求的addToCart()方法。
@RequestMapping("add_to_cart")
public JsonResult<Void> addToCart(Integer pid, Integer amount, HttpSession session) {
// 从Session中获取uid和username
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
// 调用业务对象执行添加到购物车
cartService.addToCart(uid, pid, amount, username);
// 返回成功
return new JsonResult<Void>(OK);
}
3.完成后启动项目,先登录再访问http://localhost:8080/carts/add_to_cart?pid=10000017&amount=3进行测试。
购物车-添加购物车-前端页面
1.在product.html页面中的body标签内的script标签里为“加入购物车”按钮添加点击事件。
$("#btn-add-to-cart").click(function() {
$.ajax({
url: "/carts/add_to_cart",
type: "POST",
data: {
"pid": id,
"amount": $("#num").val()
},
dataType: "JSON",
success: function(json) {
if (json.state == 200) {
alert("增加成功!");
} else {
alert("增加失败!" + json.message);
}
},
error: function(xhr) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
location.href = "login.html";
}
});
});
$.ajax函数中参数data提交请参数的方式:
// 1.适用于参数较多,且都在同一个表单中 data: $("#form表单id属性值").serialize() // 2.仅适用于上传文件 data: new FormData($("##form表单id属性值")[0]) // 3.参数拼接形式提交 data: "pid=10000005&amount=3" // 4.使用JSON格式提交参数 data: { "pid": 10000005, "amount": 3 }
2.完成后启动项目,先登录再访问http://localhost:8080/web/index.html页面进行测试。