Project(17)——购物车 - 增加商品数量
70、购物车 - 增加商品数量 - 持久层
如果需要修改购物车中商品的数量,需要执行的 SQL 语句应该是:
UPDATE
t_cart
SET
num=?, modified_user=?, modified_time=?
WHERE
cid=?
以上功能已经完成,无需再次开发。
此次操作,需要将原有的数据读取出来,然后加 1 ,则需要查询出原有数量:
SELECT
num
FROM
t_cart
WHERE
cid=?
由于以上查询中,使用的 cid 是由客户端提交的参数,则应该将其视为不可靠参数!所以,在后续的更新之前,还需要检查数据是否存在,并检查数据归属是否正确,则在查询时,还应该查询出数据的 uid,后续结合 session 中的 uid 进行对比,以保证每个用户只能修改自己的数据,所以,以上查询需要补充查询 uid 字段:
SELECT
uid, num
FROM
t_cart
WHERE
cid=?
以上查询尚未开发,需要补充!
在持久层接口中添加抽象方法:
/**
* 根据购物车的 cid 查询商品信息
* @param cid 购物车中的 cid
* @return 商品信息
*/
Cart findByCid(Integer cid);
配置以上方法的映射:
<!-- 根据购物车的 cid 查询商品信息 -->
<!-- Cart findByCid(Integer cid) -->
<select id="findByCid" resultType="cn.tedu.store.entity.Cart">
SELECT
uid, num
FROM
t_cart
WHERE
cid=#{cid}
</select>
然后,执行单元测试:
/**
* 测试根据购物车的 cid 查询商品信息
*/
@Test
public void testFindByCid() {
Integer cid = 1;
Cart cart = cartMapper.findByCid(cid);
System.err.println(cart);
}
71、购物车 - 增加商品数量 - 业务层
此次增加数量之前,应该对即将要操作的数据进行检查,例如数据是否存在,数据归属是否正常,则可能抛出CartNotFoundException
、AccessDeniedException
,后续执行更新时还可能抛出UpdateException
异常。
则需要创建cn.tedu.store.service.ex.CartNotFoundException
异常类。
在业务层接口中添加抽象方法:
/**
* 将购物车中商品的数量 + 1
* @param cid 购物车商品 cid
* @param uid 用户 uid
* @param username 用户名
* @return 增加后的商品数量
* @throws CartNotFoundException 购物车商品数据不存在异常
* @throws AccessDeniedException 访问被拒绝异常
* @throws UpdateException 更新失败
*/
Integer add(Integer cid, Integer uid, String username)
throws CartNotFoundException, AccessDeniedException, UpdateException;
以上Integer
返回值表示增加后的商品数量,该数据将相应给客户端,客户端可用于显示。
在业务层实现类中,首先私有化实现持久层中新增的方法:
然后,实现接口中的抽象方法:
/**
* 将购物车中商品的数量 + 1
*/
@Override
public Integer add(Integer cid, Integer uid, String username)
throws CartNotFoundException, AccessDeniedException, UpdateException {
// 根据 cid 查询购物车的商品的信息
// 判断查询结果是否为 null
// 是 -- 抛出购物车商品数据不存在异常
Cart result = findByCid(cid);
if(result == null) {
throw new CartNotFoundException("增加商品数量失败!商品数据不存在!");
}
// 根据查询结果的 uid 和参数 uid 比较是否一致
// 否 -- 抛出访问被拒绝异常
if(result.getUid() != uid) {
throw new AccessDeniedException("增加商品数量失败!不允许访问他人的数据!");
}
// 从查询结果中取出 num,增加 1,得到新数量
// 执行更新商品数量
Integer num = result.getNum() + 1;
Date now = new Date();
Integer rows = cartMapper.updateNum(cid, num, username, now);
if(rows != 1) {
throw new UpdateException("增加商品数量失败!出现未知错误,请联系系统管理员!");
}
return num;
}
/**
* 根据购物车的 cid 查询商品信息
* @param cid 购物车中的 cid
* @return 商品信息
*/
private Cart findByCid(Integer cid) {
return cartMapper.findByCid(cid);
}
编写并执行单元测试:
/**
* 将购物车中商品的数量 + 1
*/
@Test
public void testAdd() {
try {
Integer cid = 2;
Integer uid = 7;
String username = "Gin";
Integer num = service.add(cid, uid, username);
System.err.println("增加后商品数量为:" + num);
}catch(ServiceException e) {
System.err.println(e.getClass().getName());
System.out.println(e.getMessage());
}
}
72、购物车 - 增加商品数量 - 控制器层
首先,需要在BaseController
中添加对CartNotFoundException
的处理。
然后,在CartController
中添加处理请求的方法:
/**
* 将购物车商品数量增加 1
* @param cid
* @param session
* @return
*/
@RequestMapping("{cid}/add")
public JsonResult<Integer> add(
@PathVariable("cid") Integer cid,
HttpSession session){
// 从 session 中获取 uid,username
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
// 执行将购物车商品数量增加 1
Integer num = service.add(cid, uid, username);
// 返回响应数据结果
return new JsonResult<Integer>(SUCCESS, num);
}
完成后,先登录,再在地址栏上输入http://localhost:8080/carts/1/add
进行测试。
73、购物车 - 增加商品数量 - 前端页面
<script type="text/javascript">
$(document).ready(function(){
showCartList();
});
function showCartList(){
$.ajax({
"url" : "/carts/",
"type" : "GET",
"dataType" : "json",
"success" : function(json){
var list = json.data;
console.log("count = " + list.length);
$("#cart-list").empty();
for(var i = 0; i < list.length; i++){
console.log(list[i].title);
html = '<tr>'
+' <td><input type="checkbox" class="ckitem" /></td>'
+'<td><img'
+' src="..#{image}collect.png"'
+' class="img-responsive" /></td>'
+'<td>#{title}</td>'
+'<td>¥<span id="price-#{cid}">#{price}</span></td>'
+'<td><input type="button" value="-" class="num-btn"'
+' οnclick="reduceNum(1)" /> <input id="inp-num-#{cid}" type="text"'
+' size="2" readonly="readonly" class="num-text" value="#{num}">'
+' <input class="num-btn" type="button" value="+"'
+' οnclick="addNum(#{cid})" /></td>'
+'<td>¥<span id="total-price-#{cid}">#{totalPrice}</span></td>'
+'<td><input type="button" οnclick="delCartItem(this)"'
+' class="cart-del btn btn-default btn-xs" value="删除" /></td>'
+'</tr>';
html = html.replace(/#{cid}/g, list[i].cid);
html = html.replace(/#{image}/g, list[i].image);
html = html.replace(/#{title}/g, list[i].title);
html = html.replace(/#{price}/g, list[i].price);
html = html.replace(/#{num}/g, list[i].num);
html = html.replace(/#{totalPrice}/g, list[i].price * list[i].num);
$("#cart-list").append(html);
}
}
});
}
function addNum(cid){
$.ajax({
"url" : "/carts/" + cid +"/add",
"type" : "POST",
"dataType" : "json",
"success" : function(json){
if(json.state == 2000){
var price = parseInt($("#price-" + cid).html());
$("#inp-num-" + cid).val(json.data);
$("#total-price-" + cid).html(json.data * price);
}else{
alert(json.message);
showCartList();
}
},
"error" : function(){
alert("您的登录信息已过期,请重新登录!");
}
});
}
</script>
74、购物车 - 减少商品数量 - 持久层
执行减少商品数量的功能,需要查询出已有的数量,然后减一。
此开发已经在增加商品数量
功能中完成,无需重复开发。
75、购物车 - 减少商品数量 - 业务层
在业务层接口中添加抽象方法:
/**
* 将购物车中商品的数量 - 1
* @param cid 购物车商品 cid
* @param uid 用户 uid
* @param username 用户名
* @return 增加后的商品数量
* @throws CartNotFoundException 购物车商品数据不存在异常
* @throws AccessDeniedException 访问被拒绝异常
* @throws UpdateException 更新失败
*/
Integer reduce(Integer cid, Integer uid, String username)
throws CartNotFoundException, AccessDeniedException, UpdateException;
在业务层实现类中实现该抽象方法:
/**
* 将购物车中商品的数量 - 1
*/
@Override
public Integer reduce(Integer cid, Integer uid, String username)
throws CartNotFoundException, AccessDeniedException, UpdateException {
// 根据 cid 查询购物车的商品的信息
// 判断查询结果是否为 null
// 是 -- 抛出购物车商品数据不存在异常
Cart result = findByCid(cid);
if(result == null) {
throw new CartNotFoundException("减少商品数量失败!商品数据不存在!");
}
// 根据查询结果的 uid 和参数 uid 比较是否一致
// 否 -- 抛出访问被拒绝异常
if(result.getUid() != uid) {
throw new AccessDeniedException("减少商品数量失败!不允许访问他人的数据!");
}
// 从查询结果中取出 num,减少 1,得到新数量
// 执行更新商品数量
Integer num = result.getNum() - 1;
Date now = new Date();
Integer rows = cartMapper.updateNum(cid, num, username, now);
if(rows != 1) {
throw new UpdateException("减少商品数量失败!出现未知错误,请联系系统管理员!");
}
return num;
}
编写并执行单元测试:
/**
* 将购物车中商品的数量 - 1
*/
@Test
public void testReduce() {
try {
Integer cid = 1;
Integer uid = 7;
String username = "Gin";
Integer num = service.reduce(cid, uid, username);
System.err.println("减少后商品数量为:" + num);
}catch(ServiceException e) {
System.err.println(e.getClass().getName());
System.out.println(e.getMessage());
}
}
76、购物车 - 减少商品数量 - 控制器层
处理请求的方法:
/**
* 将购物车商品数量 - 1
* @param cid
* @param session
* @return
*/
@RequestMapping("{cid}/reduce")
public JsonResult<Integer> reduce(
@PathVariable("cid") Integer cid,
HttpSession session){
// 从 session 中获取 uid,username
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
// 执行将购物车商品数量减少 1
Integer num = service.reduce(cid, uid, username);
// 返回响应数据结果
return new JsonResult<Integer>(SUCCESS, num);
}
77、购物车 - 减少商品数量 - 前端页面
function reduceNum(cid){
$.ajax({
"url" : "/carts/" + cid +"/reduce",
"type" : "POST",
"dataType" : "json",
"success" : function(json){
if(json.state == 2000){
var price = parseInt($("#price-" + cid).html());
$("#inp-num-" + cid).val(json.data);
$("#total-price-" + cid).html(json.data * price);
}else{
alert(json.message);
showCartList();
}
},
"error" : function(){
alert("您的登录信息已过期,请重新登录!");
}
});
}