一、需求分析
(1)添加购物车(子功能)
在进行加入购物车功能时,先到数据库查询是否有同一商品存在,如有,则需要更改数量即可,如无,则需要添加到购物车当中。
(2)展示购物车的商品列表(子功能)
用户在登录的情况下,可以看到购物车的商品列表。
(3)购物车页面商品数量的增加和减少(子功能)
在查询到用户的购物车商品后,能通过控件来实现商品的增加和减少。
如:
(4)显示勾选的购物车数据(子功能)
用户在购物车页面可以进行商品的勾选,点击“结算”按钮后,跳转到结算页面,并显示所勾选的购物车数据。
(5)收货地址下拉列表(子功能)
在用户登录的情况下,选择购物车后跳转到结算页面,可以根据收货地址下拉列表选择相应的收货地址。
(6)生成订单(子功能)
用户可以在购物车页面进行商品的结算,并生成订单。
二、开发步骤与范例
持久层
1.添加购物车(子功能)
(1)sql语句
<?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.example.store.mapper.CartMapper">
<resultMap id="Cart" type="com.example.store.domain.Cart">
<result property="createdUser" column="created_user"></result>
<result property="createdTime" column="created_time"></result>
<result property="modifiedUser" column="modified_user"></result>
<result property="modifiedTime" column="modified_time"></result>
</resultMap>
<insert id="insertCart" useGeneratedKeys="true" keyProperty="cid">
insert into t_cart (uid,pid,price ,num,created_user,created_time,modified_user,modified_time)
value (#{uid},#{pid},#{price},#{num},#{createdUser},#{createdTime},#{modifiedUser},#{modifiedTime})
</insert>
<update id="updateCart">
update t_cart set num=#{num} ,modified_user=#{modifiedUser},modified_time=#{modifiedTime} where cid=#{cid}
</update>
<select id="findByPidAndUid" resultMap="Cart">
select * from t_cart where pid=#{pid} and uid=#{uid}
</select>
</mapper>
(2)设计相应的接口和抽象方法
@Mapper
public interface CartMapper {
//添加购物车
Integer insertCart(Cart cart);
//更新购买的数量
Integer updateCart(Integer num , Integer cid , String modifiedUser , Date modifiedTime);
//查询购物车是否存在商品信息
Cart findByPidAndUid(Integer uid ,Integer pid );
}
2.展示用户的购物车商品列表(子功能)
(1)sql语句
<select id="findByuid" resultMap="Cart">
select cid,price,num,pid from t_cart where uid=#{uid}
</select>
(2)设计抽象方法
//查询用户购物车的所有商品信息
List<Cart> findByuid(Integer uid);
3.购物车页面商品数量的增加和减少(子功能)
(1)sql
<select id="findByCid" resultMap="Cart">
select * from t_cart where cid=#{cid}
</select>
<update id="updateCart">
update t_cart set num=#{num} ,modified_user=#{modifiedUser},modified_time=#{modifiedTime} where cid=#{cid}
</update>
(2)设计抽象方法
//通过购物车数据id查询数据
Cart findByCid(Integer cid);
//更新购买的数量
Integer updateCart(Integer num , Integer cid , String modifiedUser , Date modifiedTime);
4.显示勾选的购物车数据(子功能)
(1)sql
<select id="findByListCid" resultMap="Cart">
select cid,price,num,pid from t_cart
where cid in (
<foreach collection="array" separator="," item="cids">
#{cids}
</foreach>
)
order by created_time desc
</select>
(2)设计抽象方法
//根据购物车id查询数据
List<Cart> findByListCid(Integer [] cids);
5.收货地址下拉列表(子功能)
(1)sql
<!-- 通过用户id查询收货地址-->
<select id="selectAddress" resultMap="Address">
select aid,tag ,name ,phone ,address ,province_name ,city_name,area_name ,is_default from t_address where uid=#{uid} order by is_default desc ,created_time DESC
</select>
(2)设计抽象方法
/**
* 根据用户的id查询用户的收货地址信息
* @param uid 用户的id
* @return 返回一个地址实体类对象
*/
List<Address> selectAddress(Integer uid);
6.生成订单(子功能):根据表格数据分析,怎么获取到这些数据。(购物车、地址、订单结合)
(1)sql语句(涉及两个表)
<insert id="insertOrder" parameterType="com.example.store.domain.Order">
<!--通过mybatis框架提供selecKey标签获得自增长产生的ID-->
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="oid">
select LAST_INSERT_ID()
</selectKey>
insert into t_order (uid,recv_name,recv_phone,fanlyAddress,total_price,status,order_time,
pay_time,created_user,created_time,modified_user,modified_time)
values(#{uid},#{recvName},#{recvPhone},#{fanlyAddress},#{totalPrice},#{status},#{orderTime},#{payTime},
#{createdUser},#{createdTime},#{modifiedUser},#{modifiedTime})
</insert>
<insert id="insertOrderItem" useGeneratedKeys="true" keyProperty="id">
insert into t_order_item (oid,pid,title,image,price,num,created_user,
created_time,modified_user,modified_time)
values(#{oid},#{pid},#{title},#{image},#{price},#{num},#{createdUser},
#{createdTime},#{modifiedUser},#{modifiedTime})
</insert>
(2)设计抽象方法
//将数据插入订单表中
Integer insertOrder(Order order);
//将数据插入订单项表中
Integer insertOrderItem(OrderItem orderItem);
业务层
1.添加购物车
(1)规划异常:更新异常和插入异常
package com.example.store.service.exceptions;
//service层异常总类
public class ServiceExceptions extends RuntimeException{
public ServiceExceptions() {
super();
}
public ServiceExceptions(String message) {
super(message);
}
public ServiceExceptions(String message, Throwable cause) {
super(message, cause);
}
public ServiceExceptions(Throwable cause) {
super(cause);
}
protected ServiceExceptions(String message, Throwable cause,
boolean enableSuppression,
boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
package com.example.store.service.exceptions;
//插入异常
public class InsertException extends ServiceExceptions {
public InsertException() {
super();
}
public InsertException(String message) {
super(message);
}
public InsertException(String message, Throwable cause) {
super(message, cause);
}
public InsertException(Throwable cause) {
super(cause);
}
protected InsertException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
package com.example.store.service.exceptions;
/**更新异常*/
public class UpdateException extends ServiceExceptions{
public UpdateException() {
super();
}
public UpdateException(String message) {
super(message);
}
public UpdateException(String message, Throwable cause) {
super(message, cause);
}
public UpdateException(Throwable cause) {
super(cause);
}
protected UpdateException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
(2)设计相应的接口和抽象方法
/**
* 购物车模块业务层开发
*/
public interface ICartService {
//加入购物车
void joinCart(Integer num, Integer pid, Integer uid ,String username);
}
(3)接口的实现类
@Service
public class CartServiceImpl implements ICartService {
@Autowired
private CartMapper cartMapper;
@Autowired
private IProductService productService;
/**
* 添加购物车
* @param num 商品的数量
* @param pid 商品的id
* @param uid 用户id
* @param username 用户名
*/
@Override
public void joinCart(Integer num, Integer pid, Integer uid, String username) {
Cart resultCart = cartMapper.findByPidAndUid(uid, pid);
Cart cart =new Cart();
Product product = productService.findById(pid);
if(resultCart == null){
cart.setUid(uid);
cart.setPid(pid);
cart.setNum(num);
cart.setPrice(product.getPrice());
cart.setCreatedUser(username);
cart.setCreatedTime(new Date());
cart.setModifiedUser(username);
cart.setModifiedTime(new Date());
Integer rows = cartMapper.insertCart(cart);
if(rows != 1){
throw new InsertException("添加购物车失败!");
}
}else{
Integer rows1 = cartMapper.updateCart(num, resultCart.getCid(), username, new Date());
if(rows1 != 1){
throw new UpdateException("修改购物车数量失败!");
}
}
}
}
2.展示用户的购物车商品列表(子功能)
(1)设计抽象方法
//查询用户购物车下的所有商品信息
List<Cart> findCartProductList(Integer uid);
(2)抽象方法的实现
/**
* 根据用户id查询用户购物车里的所有商品信息
* @param uid 用户id
* @return 返回一个带有Product类型变量的Cart对象
*/
@Override
public List<Cart> findCartProductList(Integer uid) {
List<Cart> result = cartMapper.findByuid(uid);
List<Cart> cart=new ArrayList<>();
if(result != null){
for (Cart c: result ) {
Integer pid = c.getPid();
//在ProductService业务模块,根据pid查询商品信息
Product product = productService.findById(pid);
if(product == null ){
throw new DeleteException("商品不存在异常!");
}else{
product.setSellPoint(null);
c.setProduct(product);
cart.add(c);
}
}
}
return cart;
}
3.购物车页面商品数量的增加和减少(子功能)
(1)设计抽象方法
//在购物车页面增加商品的数量
Integer UpdateCartAddNum( Integer cid , String modifiedUser );
//在购物车页面减少商品的数量
Integer UpdateCartDownlowNum(Integer cid, String modifiedUser);
(2)抽象方法的实现
/**
* 在购物车页面增加商品的数量
* @param cid 购物车数据id
* @param modifiedUser 用户名
* @return 返回一个最新的商品数量值,用户前端页面的展示
*/
@Override
public Integer UpdateCartAddNum(Integer cid, String modifiedUser) {
Cart resultCart = cartMapper.findByCid(cid);
if(resultCart == null){
throw new CartNotFonddException("该商品已不存在!");
}
Integer newNum =resultCart.getNum() + 1;
Integer rows = cartMapper.updateCart(newNum, cid, modifiedUser, new Date());
if(rows == null) {
throw new UpdateException("更新时出现异常!");
}
return newNum;
}
/**
* 在购物车页面减少商品的数量
* @param cid 购物车数据id
* @param modifiedUser 用户名
* @return 返回一个最新的商品数量值,用户前端页面的展示
*/
@Override
public Integer UpdateCartDownlowNum(Integer cid, String modifiedUser) {
Cart resultCart = cartMapper.findByCid(cid);
if(resultCart == null){
throw new CartNotFonddException("该商品已不存在!");
}
Integer newNum =resultCart.getNum() - 1;
Integer rows = cartMapper.updateCart(newNum, cid, modifiedUser, new Date());
if(rows == null) {
throw new UpdateException("更新时出现异常!");
}
return newNum;
}
}
4.显示勾选的购物车数据(子功能)
(1)设计抽象方法
//显示勾选购物车的数据
List<Cart> findByListCid(Integer [] cids);
(2)抽象方法的实现
/**
*显示勾选的购物车数据
* @param cids 传入所勾选的商品id
* @return 返回一个Cart类型的集合
*/
@Override
public List<Cart> findByListCid(Integer[] cids) {
List<Cart> resultCartList = cartMapper.findByListCid(cids);
if(resultCartList != null){
for (Cart c: resultCartList) {
Integer pid =c.getPid();
Product product = productService.findById(pid);
product.setSellPoint(null);
c.setProduct(product);
}
}
return resultCartList;
}
5.收货地址下拉列表(子功能)
(1)设计抽象方法
//根据用户的id查询用户的收货地址
List<Address> selectAddress(Integer uid);
(2)抽象方法的实现
/**
* 根据用户的id查询用户的收货地址
* @param uid 用户id
* @return 返回Addressl类型的集合
*/
@Override
public List<Address> selectAddress(Integer uid) {
List<Address> list = addressMapper.selectAddress(uid);
for (Address i : list ) {
String finalAddress =null;
finalAddress =i.getProvinceName()+i.getCityName()+i.getAreaName();
i.setFanlyAddress(finalAddress);
}
return list;
}
6.生成订单(子功能)
(1)设计抽象方法
/**
* 创建订单
* @param aid 地址的id
* @param uid 用户的id
* @param username 用户名
* @param cids 购物车id
* @return 返回一个Order类型的对象
*/
Order createOrder(Integer aid , Integer uid , String username , Integer [] cids);
(2)抽象方法的实现类
@Service
public class OrderServiceImpl implements IOrderService {
@Autowired
private IAddressService addressService;
@Autowired
private ICartService cartService;
@Autowired
private OrderMapper orderMapper;
@Autowired
private IProductService productService;
/**
* 创建订单
* @param aid 地址的id
* @param uid 用户的id
* @param username 用户名
* @param cids 购物车id
* @return 返回一个Order类型的对象
*/
@Override
public Order createOrder(Integer aid, Integer uid, String username, Integer[] cids) {
//1.创建order对象和OrderItem对象
Order order = new Order();
OrderItem orderItem =new OrderItem();
Long totalPrice =0L;
//2.根据aid查询收货地址的信息,用于补全数据
Address resultAddress = addressService.findByAid(aid);
if(resultAddress == null){
throw new AddressNotFondException("该收货地址已不存在!");
}
//补全order
order.setUid(uid);
order.setRecvName(resultAddress.getName());
order.setRecvPhone(resultAddress.getPhone());
order.setFanlyAddress(resultAddress.getFanlyAddress());
//3.根据购物车勾选的商品id来查询商品的信息
List<Cart> resultCart =cartService.findByListCid(cids);
if(resultCart.size() != 0){
for (Cart c: resultCart) {
//根据商品的id查询商品的相关信息
Integer pid = c.getPid();
Product product = productService.findById(pid);
//补全orderItem
orderItem.setPid(pid);
orderItem.setTitle(product.getTitle());
orderItem.setImage(product.getImage());
orderItem.setPrice(product.getPrice());
orderItem.setNum(c.getNum());
//计算商品的总价格
totalPrice +=c.getNum() * c.getPrice();
}
}
//补全order
order.setTotalPrice(totalPrice);
order.setOrderTime(new Date());
order.setCreatedUser(username);
order.setCreatedTime(new Date());
order.setModifiedUser(username);
order.setModifiedTime(new Date());
order.setStatus(0);
//补全orderItem信息
orderItem.setCreatedUser(username);
orderItem.setModifiedUser(username);
orderItem.setCreatedTime(new Date());
orderItem.setModifiedTime(new Date());
//插入数据
Integer rows = orderMapper.insertOrder(order);
if(rows != 1){
throw new InsertException("数据插入失败!");
}
orderItem.setOid(order.getOid());
Integer rows1 = orderMapper.insertOrderItem(orderItem);
if(rows1 != 1){
throw new InsertException("数据插入失败!");
}
return order;
}
控制层
1.添加购物车
(1)异常处理:无
(2)设计请求
data: pid,num,session(之前的用户名和id已经保存在session域中)
url:"/cart/joinCart"
type:post
datatype:json
(3)编写控制层方法
/**
* 添加购物车
* @param num 商品的数量
* @param pid 商品的id
* @param session 保存用户名和用户id的session
* @return 返回一个只包含状态信息的Result对象
*/
@RequestMapping("/joinCart")
public Result<Void> joinCart(Integer num , Integer pid , HttpSession session){
cartService.joinCart(num,pid,getUidFromSession(session),getUsernameFromSession(session));
return new Result<>(OK);
}
2.展示用户的购物车商品列表(子功能)
(1)异常处理:和第一个功能写法差不多(略)
(2)设计请求
data: session(之前的用户名和id已经保存在session域中)
url:"/cart/findCartProductList"
type:post
datatype:json
(3)编写控制层方法
/**
* 展示用户购物车的所有商品信息
* @param session 之前已将session保存在session域当中
* @return 返回一个Cart类型的集合
*/
@RequestMapping("/findCartProductList")
public Result<List<Cart>> findCartProductList(HttpSession session){
List<Cart> data = cartService.findCartProductList(getUidFromSession(session));
return new Result<List<Cart>>(OK,data);
}
3.购物车页面商品数量的增加和减少(子功能)
注:加减相似,故只写增加的开发范例。
1.异常处理:更新异常(略)
2.设计请求
data: cid.session(用户获取存在session域中的用户id,用户名)
url:"/cart/AddNumToCart"
type:post
datatype:json
3.编写控制层方法
/**
* 在购物车页面增加商品数量
* @param cid
* @param session
* @return
*/
@RequestMapping("/AddNumToCart")
public Result<Integer> AddNumToCart(Integer cid,HttpSession session){
Integer data = cartService.UpdateCartAddNum(cid, getUsernameFromSession(session));
return new Result<>(OK,data);
}
4.显示勾选的购物车数据(子功能)
(1)异常处理:无
(2)请求设计
data: Integer [] cids
url:"/cart/findByListCid"
type:get
datatype:json
(3)编写控制层方法
/**
* 显示勾选购物车的数据
* @param cids 勾选的商品id
* @return 返回一个Cart类型的集合
*/
@RequestMapping("/findByListCid")
public Result<List<Cart>> findByListCid(Integer [] cids){
List<Cart> data = cartService.findByListCid(cids);
return new Result<>(OK,data);
}
5.收货地址下拉列表(子功能)
(1)异常处理:暂无
(2)设计请求
data:session
url:"/address"
type:post
datatype:json
(3)编写控制层方法
@RequestMapping({"","/"})
public Result<List<Address>> selectAddress(HttpSession session){
Integer uid = getUidFromSession(session);
List<Address> data = addressService.selectAddress(uid);
return new Result<>(OK,data);
}
6.生成订单(子功能)
(1)异常处理:暂无
(2)设计请求
data:session
url:"/address"
type:get
datatype:json
(3)编写控制层方法
@Autowired
private IOrderService orderService;
@RequestMapping("/createOrder")
public Result<Order> createOrder(Integer aid , Integer [] cids , HttpSession session){
Order data = orderService.createOrder(aid, getUidFromSession(session), getUsernameFromSession(session), cids);
return new Result<>(OK,data);
}
前端页面
1.添加购物车
$("#btn-add-to-cart").click(function (){
$.ajax({
url:"/cart/joinCart",
data:{
"pid":id,
"num":$("#num").val()
},
datatype:"json",
type:"post",
async:false,
success: function(json){
if(json.state == 200){
alert("添加购物车成功!");
console.log("----------------");
}else{
alert("添加购物车失败!");
}
},
error: function (xhr){
alert("添加购物车时产生未知的异常!"+xhr.message);
}
});
});
</script>
2.展示用户的购物车商品列表(子功能)
$(document).ready(function(){
$("#cart-list").empty();
$.ajax({
url:"/cart/findCartProductList",
datatype:"json",
type:"get",
success:function(json){
debugger
if(json.state == 200){
let list =json.data;
console.log(list.length);
for(let i =0 ;i <list.length ;i++){
let tr ='<tr>\n' +
'<td>\n' +
'<input name="cids" id="#{cid}" type="checkbox" class="ckitem" />\n' +
'</td>\n' +
'<td><img src="..#{image}collect.png" class="img-responsive" /></td>\n' +
'<td>#{title}</td>\n' +
'<td>¥<span id="goodsPrice#{cid}">#{price}</span></td>\n' +
'<td>\n' +
'<input id="price" type="button" value="-" class="num-btn" onclick="reduceNum(#{cid})" />\n' +
'<input id="goodsCount#{cid}" type="text" size="2" readonly="readonly" class="num-text" value="#{num}">\n' +
'<input id="price" class="num-btn" type="button" value="+" onclick="addNum(#{cid})" />\n' +
'</td>\n' +
'<td><span id="goodsCast#{cid}">#{totalPrice}</span></td>\n' +
'<td>\n' +
'<input type="button" onclick="delCartItem(this)" class="cart-del btn btn-default btn-xs" value="删除" />\n' +
'</td>\n' +
'</tr>';
tr =tr.replace(/#{cid}/g,list[i].cid);
tr =tr.replace("#{image}",list[i].product.image);
tr =tr.replace("#{title}",list[i].product.title);
tr =tr.replace("#{price}",list[i].price);
tr =tr.replace("#{num}",list[i].num);
tr =tr.replace("#{totalPrice}",list[i].num * list[i].price);
console.log(tr)
$("#cart-list").append(tr);
}
}
}
});
});
3.购物车页面商品数量的增加和减少(子功能)
function addNum(cid){
console.log(cid);
$.ajax({
url:"/cart/AddNumToCart",
data:{"cid":cid},
datatype:"json",
type:"post",
success: function(json){
debugger
if(json.state == 200){
$("#goodsCount"+cid).val(json.data);
let price =$("#goodsPrice"+cid).html();
let totalPrice =price * json.data;
$("#goodsCast"+cid).html(totalPrice);
}else{
alert("商品添加失败!");
}
},
error :function (xhr){
alert("商品添加数量时产生未知的异常!"+xhr.message);
}
});
}
4.显示勾选的购物车数据(子功能)
<script type="text/javascript">
$(document).ready(function (){
$("#cart-list").empty()
$.ajax({
url:"/cart/findByListCid",
data:location.search.substr(1),//从导航栏截取的数据?代表0索引,之后的从1开始,如http://localhost:8080/cart/findByListCid ? cids=1&cids=7
datatype:"json",
type:"get",
success:function (json){
debugger
if(json.state == 200){
let list =json.data;
let totalNum = 0;
let totalPrice =0 ;
for (let i =0 ;i <list.length ; i++ ) {
let tr ='<tr>\n' +
'<td><img src="..#{image}collect.png" class="img-responsive" /></td>\n' +
'<td>#{title}</td>\n' +
'<td>¥<span>#{price}</span></td>\n' +
'<td>#{num}</td>\n' +
'<td><span>#{totalPrice}</span></td>\n' +
'</tr>';
tr =tr.replace("#{image}",list[i].product.image);
tr =tr.replace("#{title}",list[i].product.title);
tr =tr.replace("#{price}",list[i].price);
tr =tr.replace("#{num}",list[i].num);
tr =tr.replace("#{totalPrice}",list[i].price * list[i].num);
$("#cart-list").append(tr);
totalNum += list[i].num;
totalPrice += list[i].num * list[i].price;
}
$("#all-count").html(totalNum);
$("#all-price").html(totalPrice);
}else{
alert("商品展示失败!");
}
}
});
});
5.收货地址下拉列表(子功能)
function showAddressList(){
$("#address-list").empty();
$.ajax({
url:"/address",
datatype:"json",
type:"post",
success:function(json){
debugger
if(json.state == 200){
let list =json.data;
for(let i =0 ;i < list.length ;i++){
let op ='<option value="#{aid}">#{name} #{home} #{fanlyAddress} #{phone}</option>';
op =op.replace("#{aid}",list[i].aid);
op = op.replace("#{name}",list[i].name);
op =op.replace("#{home}",list[i].home);
op =op.replace("#{fanlyAddress}",list[i].fanlyAddress);
op =op.replace("#{phone}",list[i].phone);
$("#address-list").append(op);
}
}else{
alert("暂无数据!");
}
}
});
}
6.生成订单(子功能)
$("#btn-create-order").click(function(){
let aid =$("#address-list").val();//地址下拉列表框的id
let cids =location.search.substr(1);//cids=7&cids=1
$.ajax({
url:"/order/createOrder",
data:"aid="+aid+"&"+cids,
datatype:"json",
type:"get",
success :function (json){
if(json.state == 200){
location.href ="payment.html";
alert("订单创建成功!");
}
},
error :function (xhr){
alert("订单创建过程出现未知的异常!"+xhr.message);
}
});
});