计算机毕业设计|基于SpringBoot+MyBatis框架的电脑商城的设计与实现(商品和购物车)

计算机毕业设计|基于SpringBoot+MyBatis框架的电脑商城的设计与实现(商品和购物车)

商品热销排行

1 商品-创建数据表

1.使用use命令先选中store数据库。

USE store;

2.在store数据库中创建t_product数据表。

CREATE TABLE t_product (
  id int(20) NOT NULL COMMENT '商品id',
  category_id int(20) DEFAULT NULL COMMENT '分类id',
  item_type varchar(100) DEFAULT NULL COMMENT '商品系列',
  title varchar(100) DEFAULT NULL COMMENT '商品标题',
  sell_point varchar(150) DEFAULT NULL COMMENT '商品卖点',
  price bigint(20) DEFAULT NULL COMMENT '商品单价',
  num int(10) DEFAULT NULL COMMENT '库存数量',
  image varchar(500) DEFAULT NULL COMMENT '图片路径',
  status int(1) DEFAULT '1' COMMENT '商品状态  1:上架   2:下架   3:删除',
  priority int(10) DEFAULT NULL COMMENT '显示优先级',
  created_time datetime DEFAULT NULL COMMENT '创建时间',
  modified_time datetime DEFAULT NULL COMMENT '最后修改时间',
  created_user varchar(50) DEFAULT NULL COMMENT '创建人',
  modified_user varchar(50) DEFAULT NULL COMMENT '最后修改人',
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2 商品-创建实体类

创建com.cy.store.entity.Product类,并继承自BaseEntity类。在类中声明与数据表中对应的属性。

package com.cy.store.entity;

/** 商品数据的实体类 */
public class Product extends BaseEntity implements Serializable {
    private Integer id;
    private Integer categoryId;
    private String itemType;
    private String title;
    private String sellPoint;
    private Long price;
    private Integer num;
    private String image;
    private Integer status;
    private Integer priority;

    // Generate: Getter and Setter、Generate hashCode() and equals()、toString()
}

3 商品-热销排行-持久层

3.1 规划需要执行的SQL语句

查询热销商品列表的SQL语句大致是。

SELECT * FROM t_product WHERE status=1 ORDER BY priority DESC LIMIT 0,4
3.2 接口与抽象方法

在com.cy.store.mapper包下创建ProductMapper接口并在接口中添加查询热销商品findHotList()的方法。

package com.cy.store.mapper;
import com.cy.store.entity.Product;
import java.util.List;

/** 处理商品数据的持久层接口 */
public interface ProductMapper {
    /**
     * 查询热销商品的前四名
     * @return 热销商品前四名的集合
     */
    List<Product> findHotList();
}
3.3 配置SQL映射

1.在main\resources\mapper文件夹下创建ProductMapper.xml文件,并在文件中配置findHotList()方法的映射。

<?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.ProductMapper">
    <resultMap id="ProductEntityMap" type="com.cy.store.entity.Product">
        <id column="id" property="id"/>
        <result column="category_id" property="categoryId"/>
        <result column="item_type" property="itemType"/>
        <result column="sell_point" property="sellPoint"/>
        <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>

    <!-- 查询热销商品的前四名:List<Product> findHostList() -->
    <select id="findHotList" resultMap="ProductEntityMap">
        SELECT
            *
        FROM
            t_product
        WHERE
            status=1
        ORDER BY
            priority DESC
            LIMIT 0,4
    </select>
</mapper>

2.在com.cy.store.mapper包下创建ProductMapperTests测试类,并添加测试方法。

package com.cy.store.mapper;
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.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductMapperTests {
    @Autowired
    private ProductMapper productMapper;

    @Test
    public void findHotList() {
        List<Product> list = productMapper.findHotList();
        System.out.println("count=" + list.size());
        for (Product item : list) {
            System.out.println(item);
        }
    }
}

4 商品-热销排行-业务层

4.1 规划异常

说明:无异常。

4.2 接口与抽象方法

创建com.cy.store.service.IProductService接口,并在接口中添加findHotList()方法。

package com.cy.store.service;
import com.cy.store.entity.Product;
import java.util.List;

/** 处理商品数据的业务层接口 */
public interface IProductService {
    /**
     * 查询热销商品的前四名
     * @return 热销商品前四名的集合
     */
    List<Product> findHotList();
}
4.3 实现抽象方法

1.创建com.cy.store.service.impl.ProductServiceImpl类,并添加@Service注解;在类中声明持久层对象以及实现接口中的方法。

package com.cy.store.service.impl;
import com.cy.store.entity.Product;
import com.cy.store.mapper.ProductMapper;
import com.cy.store.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

/** 处理商品数据的业务层实现类 */
@Service
public class ProductServiceImpl implements IProductService {
    @Autowired
    private ProductMapper productMapper;

    @Override
    public List<Product> findHotList() {
        List<Product> list = productMapper.findHotList();
        for (Product product : list) {
            product.setPriority(null);
            product.setCreatedUser(null);
            product.setCreatedTime(null);
            product.setModifiedUser(null);
            product.setModifiedTime(null);
        }
        return list;
    }
}

2.在com.cy.store.service包下创建测试类ProductServiceTests,并编写测试方法。

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 ProductServiceTests {
    @Autowired
    private IProductService productService;

    @Test
    public void findHotList() {
        try {
            List<Product> list = productService.findHotList();
            System.out.println("count=" + list.size());
            for (Product item : list) {
                System.out.println(item);
            }
        } catch (ServiceException e) {
            System.out.println(e.getClass().getSimpleName());
            System.out.println(e.getMessage());
        }
    }
}

5 商品-热销排行-控制器

5.1 处理异常

说明:无异常。

5.2 设计请求

1.设计用户提交的请求,并设计响应的方式。

请求路径:/products/hot_list
请求参数:无
请求类型:GET
响应结果:JsonResult<List<Product>>
是否拦截:否,需要将index.html和products/**添加到白名单

2.在LoginInterceptorConfigurer类中将index.html页面和products/**请求添加到白名单。

patterns.add("/web/index.html");
patterns.add("/products/**");
5.3 处理请求

1.创建com.cy.controller.ProductController类继承自BaseController类,类添加@RestController和@RequestMapping(“products”)注解,并在类中添加业务层对象。

package com.cy.store.controller;
import com.cy.store.entity.Product;
import com.cy.store.service.IProductService;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;

@RestController
@RequestMapping("products")
public class ProductController extends BaseController {
    @Autowired
    private IProductService productService;
}

2.在类中添加处理请求的getHotList()方法。

@RequestMapping("hot_list")
public JsonResult<List<Product>> getHotList() {
    List<Product> data = productService.findHotList();
    return new JsonResult<List<Product>>(OK, data);
}

3.完成后启动项目,直接访问http://localhost:8080/products/hot_list进行测试。

在这里插入图片描述

6 商品-热销排行-前端页面

1.在index.html页面给“热销排行”列表的div标签设置id属性值。

<div id="hot-list" class="panel-body panel-item">
	<!-- ... -->
</div>

2.在index.html页面中body标签内部的最后,添加展示热销排行商品的代码。

<script type="text/javascript">
$(document).ready(function() {
    showHotList();
});

function showHotList() {
    $("#hot-list").empty();
    $.ajax({
        url: "/products/hot_list",
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            let list = json.data;
            console.log("count=" + list.length);
            for (let i = 0; i < list.length; i++) {
                console.log(list[i].title);
                let html = '<div class="col-md-12">'
                  + '<div class="col-md-7 text-row-2"><a href="product.html?id=#{id}">#{title}</a></div>'
                  + '<div class="col-md-2">¥#{price}</div>'
                  + '<div class="col-md-3"><img src="..#{image}collect.png" class="img-responsive" /></div>'
                + '</div>';

                html = html.replace(/#{id}/g, list[i].id);
                html = html.replace(/#{title}/g, list[i].title);
                html = html.replace(/#{price}/g, list[i].price);
                html = html.replace(/#{image}/g, list[i].image);

                $("#hot-list").append(html);
            }
        }
    });
}
</script>

3.完成后启动项目,直接访问http://localhost:8080/web/index.html进行测试。

显示商品详情

1 商品-显示商品详情-持久层

1.1 规划需要执行的SQL语句

根据商品id显示商品详情的SQL语句大致是。

SELECT * FROM t_product WHERE id=?
1.2 接口与抽象方法

在ProductMapper接口中添加抽象方法。

/**
 * 根据商品id查询商品详情
 * @param id 商品id
 * @return 匹配的商品详情,如果没有匹配的数据则返回null
 */
Product findById(Integer id);
1.3 配置SQL映射

1.在ProductMapper.xml文件中配置findById(Integer id)方法的映射。

<!-- 根据商品id查询商品详情:Product findById(Integer id) -->
<select id="findById" resultMap="ProductEntityMap">
    SELECT
    	*
    FROM
    	t_product
    WHERE
    	id=#{id}
</select>

2.在ProductMapperTests测试类中添加测试方法。

@Test
public void findById() {
    Integer id = 10000017;
    Product result = productMapper.findById(id);
    System.out.println(result);
}

2 商品-显示商品详情-业务层

2.1 规划异常

如果商品数据不存在,应该抛出ProductNotFoundException,需要创建com.cy.store.service.ex.ProductNotFoundException异常。

package com.cy.store.service.ex;

/** 商品数据不存在的异常 */
public class ProductNotFoundException extends ServiceException {
    // Override Methods...
}
2.2 接口与抽象方法

在业务层IProductService接口中添加findById(Integer id)抽象方法。

/**
 * 根据商品id查询商品详情
 * @param id 商品id
 * @return 匹配的商品详情,如果没有匹配的数据则返回null
 */
Product findById(Integer id);
2.3 实现抽象方法

1.在ProductServiceImpl类中,实现接口中的findById(Integer id)抽象方法。

@Override
public Product findById(Integer id) {
    // 根据参数id调用私有方法执行查询,获取商品数据
    Product product = productMapper.findById(id);
    // 判断查询结果是否为null
    if (product == null) {
        // 是:抛出ProductNotFoundException
        throw new ProductNotFoundException("尝试访问的商品数据不存在");
    }
    // 将查询结果中的部分属性设置为null
    product.setPriority(null);
    product.setCreatedUser(null);
    product.setCreatedTime(null);
    product.setModifiedUser(null);
    product.setModifiedTime(null);
    // 返回查询结果
    return product;
}

2.在ProductServiceTests测试类中编写测试方法。

@Test
public void findById() {
    try {
        Integer id = 100000179;
        Product result = productService.findById(id);
        System.out.println(result);
    } catch (ServiceException e) {
        System.out.println(e.getClass().getSimpleName());
        System.out.println(e.getMessage());
    }
}

3 商品-显示商品详情-控制器

3.1 处理异常

在BaseController类中的handleException()方法中添加处理ProductNotFoundException的异常。

// ...
else if (e instanceof ProductNotFoundException) {
	result.setState(4006);
}
// ...
3.2 设计请求

设计用户提交的请求,并设计响应的方式。

请求路径:/products/{id}/details
请求参数:@PathVariable("id") Integer id
请求类型:GET
响应结果:JsonResult<Product>
3.3 处理请求

1.在ProductController类中添加处理请求的getById()方法。

@GetMapping("{id}/details")
public JsonResult<Product> getById(@PathVariable("id") Integer id) {
    // 调用业务对象执行获取数据
    Product data = productService.findById(id);
    // 返回成功和数据
    return new JsonResult<Product>(OK, data);
}

2.完成后启动项目,直接访问http://localhost:8080/products/10000017/details进行测试。

在这里插入图片描述

4 商品-显示商品详情-前端页面

1.检查在product.html页面body标签内部的最后是否引入jquery-getUrlParam.js文件,如果引入无需重复引入。

<script type="text/javascript" src="../js/jquery-getUrlParam.js"></script>

2.在product.html页面中body标签内部的最后添加获取当前商品详情的代码。

<script type="text/javascript">
let id = $.getUrlParam("id");
console.log("id=" + id);
$(document).ready(function() {
    $.ajax({
        url: "/products/" + id + "/details",
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            if (json.state == 200) {
                console.log("title=" + json.data.title);
                $("#product-title").html(json.data.title);
                $("#product-sell-point").html(json.data.sellPoint);
                $("#product-price").html(json.data.price);

                for (let i = 1; i <= 5; i++) {
                    $("#product-image-" + i + "-big").attr("src", ".." + json.data.image + i + "_big.png");
                    $("#product-image-" + i).attr("src", ".." + json.data.image + i + ".jpg");
                }
            } else if (json.state == 4006) { // 商品数据不存在的异常
                location.href = "index.html";
            } else {
                alert("获取商品信息失败!" + json.message);
            }
        }
    });
});
</script>

3.完成后启动项目,先访问http://localhost:8080/web/index.html页面,然后点击“热销排行”中的某个子项,将跳转到product.html商品详情页,观察页面是否加载的是当前的商品信息。

<script type="text/javascript">
let id = $.getUrlParam("id");
console.log("id=" + id);
$(document).ready(function() {
$.ajax({
url: "/products/" + id + "/details",
type: "GET",
dataType: "JSON",
success: function(json) {
if (json.state == 200) {
console.log("title=" + json.data.title);
$("#product-title").html(json.data.title);
$("#product-sell-point").html(json.data.sellPoint);
$("#product-price").html(json.data.price);
for (let i = 1; i <= 5; i++) {
$("#product-image-" + i + "-big").attr("src", ".." +
json.data.image + i + "_big.png");
$("#product-image-" + i).attr("src", ".." + json.data.image
+ i + ".jpg");
}
} else if (json.state == 4006) { // 商品数据不存在的异常
location.href = "index.html";
} else {
alert("获取商品信息失败!" + json.message);
}
}
});
});
</script>

3.完成后启动项目,先访问http://localhost:8080/web/index.html页面,然后点击“热销排行”中的某个子项,将跳转到product.html商品详情页,观察页面是否加载的是当前的商品信息。
在这里插入图片描述

加入购物车

1 购物车-创建数据表

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;

2 购物车-创建实体类

在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()
}

3 购物车-添加购物车-持久层

3.1 规划需要执行的SQL语句

向购物车表中插入商品数据的SQL语句大致是:

insert into t_cart (除了cid以外的字段列表) values (匹配的值列表);

如果用户曾经将某个商品加入到购物车过,则点击“加入购物车”按钮只会对购物车中相同商品数量做递增操作。

update t_cart set num=? where cid=?

关于判断“到底应该插入数据,还是修改数量”,可以通过“查询某用户是否已经添加某商品到购物车”来完成。如果查询到某结果,就表示该用户已经将该商品加入到购物车了,如果查询结果为null,则表示该用户没有添加过该商品。

select * from t_cart where uid=? and pid=?
3.2 接口与抽象方法

在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);
}
3.3 配置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);
    }
}

4 购物车-添加购物车-业务层

4.1 规划异常

在插入数据时,可能抛出InsertException异常;在修改数据时,可能抛出UpdateException异常。如果不限制购物车中的记录的数量,则没有其它异常。

4.2 接口与抽象方法

在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);
}
4.3 实现抽象方法

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());
        }
    }
}

5 购物车-添加购物车-控制器

5.1 处理异常

说明:无异常。

5.2 设计请求

设计用户提交的请求,并设计响应的方式。

请求路径:/carts/add_to_cart
请求参数:Integer pid, Integer amount, HttpSession session
请求类型:POST
响应结果:JsonResult<Void>
5.3 处理请求

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进行测试。

6 购物车-添加购物车-前端页面

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页面进行测试。

在这里插入图片描述

显示购物车列表

1 购物车-显示列表-持久层

1.1 规划需要执行的SQL语句

显示某用户的购物车列表数据的SQL语句大致是。

SELECT
	cid,
	uid,
	pid,
	t_cart.price,
	t_cart.num,
	t_product.title,
	t_product.price AS realPrice,
	t_product.image
FROM
	t_cart
	LEFT JOIN t_product ON t_cart.pid = t_product.id 
WHERE
	uid = #{uid}
ORDER BY
	t_cart.created_time DESC
1.2 接口与抽象方法

1.由于涉及多表关联查询,必然没有哪个实体类可以封装此次的查询结果,因此需要创建VO类。创建com.cy.store.vo.CartVO类。

package com.cy.store.vo;
import java.io.Serializable;

/** 购物车数据的Value Object类 */
public class CartVO implements Serializable {
    private Integer cid;
    private Integer uid;
    private Integer pid;
    private Long price;
    private Integer num;
    private String title;
    private Long realPrice;
    private String image;
    
    // Generate: Getter and Setter、Generate hashCode() and equals()、toString()
}

2.在CartMapper接口中添加抽象方法。

/**
 * 查询某用户的购物车数据
 * @param uid 用户id
 * @return 该用户的购物车数据的列表
 */
List<CartVO> findVOByUid(Integer uid);
1.3 配置SQL映射

1.在CartMapper.xml文件中添加findVOByUid()方法的映射。

<!-- 查询某用户的购物车数据:List<CartVO> findVOByUid(Integer uid) -->
<select id="findVOByUid" resultType="com.cy.store.vo.CartVO">
    SELECT
        cid,
        uid,
        pid,
        t_cart.price,
        t_cart.num,
        t_product.title,
        t_product.price AS realPrice,
        t_product.image
    FROM
        t_cart
        LEFT JOIN t_product ON t_cart.pid = t_product.id 
    WHERE
        uid = #{uid}
    ORDER BY
        t_cart.created_time DESC
</select>

2.在CartMapperTests测试类中添加findVOByUid()方法的测试。

@Test
public void findVOByUid() {
    List<CartVO> list = cartMapper.findVOByUid(31);
    System.out.println(list);
}

2 购物车-显示列表-业务层

2.1 规划异常

说明:无异常。

2.2 接口与抽象方法

在ICartService接口中添加findVOByUid()抽象方法。

/**
 * 查询某用户的购物车数据
 * @param uid 用户id
 * @return 该用户的购物车数据的列表
 */
List<CartVO> getVOByUid(Integer uid);
2.3 实现抽象方法

1.在CartServiceImpl类中重写业务接口中的抽象方法。

@Override
public List<CartVO> getVOByUid(Integer uid) {
    return cartMapper.findVOByUid(uid);
}

2.在CartServiceTests测试类中添加getVOByUid()测试方法。

@Test
public void getVOByUid() {
    List<CartVO> list = cartService.getVOByUid(31);
    System.out.println("count=" + list.size());
    for (CartVO item : list) {
        System.out.println(item);
    }
}

3 购物车-显示列表-控制器

3.1 处理异常

说明:无异常。

3.2 设计请求

设计用户提交的请求,并设计响应的方式。

请求路径:/carts/
请求参数:HttpSession session
请求类型:GET
响应结果:JsonResult<List<CartVO>>
3.3 处理请求

1.在CartController类中编写处理请求的代码。

@GetMapping({"", "/"})
public JsonResult<List<CartVO>> getVOByUid(HttpSession session) {
    // 从Session中获取uid
    Integer uid = getUidFromSession(session);
    // 调用业务对象执行查询数据
    List<CartVO> data = cartService.getVOByUid(uid);
    // 返回成功与数据
    return new JsonResult<List<CartVO>>(OK, data);
}

2.完成后启动项目,先登录再访问http://localhost:8080/carts请求进行测试。

4 购物车-显示列表-前端页面

1.将cart.html页面的head头标签内引入的cart.js文件注释掉。

<!-- <script src="../js/cart.js" type="text/javascript" charset="utf-8"></script> -->

2.给form标签添加action="orderConfirm.html"属性、tbody标签添加id="cart-list"属性、结算按钮的类型改为type="button"值。如果以上属性值已经添加过无需重复添加。

3.在cart.html页面body标签内的script标签中编写展示购物车列表的代码。

$(document).ready(function() {
    showCartList();
});

function showCartList() {
    $("#cart-list").empty();
    $.ajax({
        url: "/carts",
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            let list = json.data;
            for (let i = 0; i < list.length; i++) {
                let tr = '<tr>'
                + '<td>'
                + 	'<input name="cids" value="#{cid}" type="checkbox" class="ckitem" />'
                + '</td>'
                + '<td><img src="..#{image}collect.png" class="img-responsive" /></td>'
                + '<td>#{title}#{msg}</td>'
                + '<td>¥<span id="price-#{cid}">#{realPrice}</span></td>'
                + '<td>'
                + 	'<input type="button" value="-" class="num-btn" οnclick="reduceNum(1)" />'
                + 	'<input id="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>';
                tr = tr.replace(/#{cid}/g, list[i].cid);
                tr = tr.replace(/#{title}/g, list[i].title);
                tr = tr.replace(/#{image}/g, list[i].image);
                tr = tr.replace(/#{realPrice}/g, list[i].realPrice);
                tr = tr.replace(/#{num}/g, list[i].num);
                tr = tr.replace(/#{totalPrice}/g, list[i].realPrice * list[i].num);

                if (list[i].realPrice < list[i].price) {
                    tr = tr.replace(/#{msg}/g, "比加入时降价" + (list[i].price - list[i].realPrice) + "元");
                } else {
                    tr = tr.replace(/#{msg}/g, "");
                }
                $("#cart-list").append(tr);
            }
        }
    });
}

4.完成后启动项目,先登录再访问http://localhost:8080/web/cart.html页面进行测试。

在这里插入图片描述

增加商品数量

1 购物车-增加商品数量-持久层

1.1 规划需要执行的SQL语句

1.首先进行查询需要操作的购物车数据信息。

SELECT * FROM t_cart WHERE cid=?

2.然后计算出新的商品数量值,如果满足更新条件则执行更新操作。此SQL语句无需重复开发。

UPDATE t_cart SET num=?, modified_user=?, modified_time=? WHERE cid=?
1.2 接口与抽象方法

在CartMapper接口中添加抽象方法。

/**
 * 根据购物车数据id查询购物车数据详情
 * @param cid 购物车数据id
 * @return 匹配的购物车数据详情,如果没有匹配的数据则返回null
 */
Cart findByCid(Integer cid);
1.3 配置SQL映射

1.在CartMapper文件中添加findByCid(Integer cid)方法的映射。

<!-- 根据购物车数据id查询购物车数据详情:Cart findByCid(Integer cid) -->
<select id="findByCid" resultMap="CartEntityMap">
    SELECT
   		*
    FROM
    	t_cart
    WHERE
    	cid = #{cid}
</select>

2.在CartMapperTests测试类中添加findByCid()测试方法。

@Test
public void findByCid() {
	Integer cid = 6;
	Cart result = cartMapper.findByCid(cid);
	System.out.println(result);
}

2 购物车-增加商品数量-业务层

2.1 规划异常

1.如果尝试访问的购物车数据不存在,则抛出CartNotFoundException异常。创建com.cy.store.service.ex.CartNotFoundException类。

/** 购物车数据不存在的异常 */
public class CartNotFoundException extends ServiceException {
	// Override Methods...
}

2.如果尝试访问的数据并不是当前登录用户的数据,则抛出AccessDeniedException异常。此异常类无需再次创建。

3.最终执行更新操作时,可能会抛出UpdateException异常。此异常类无需再次创建。

2.2 接口与抽象方法

在业务层ICartService接口中添加addNum()抽象方法。

/**
 * 将购物车中某商品的数量加1
 * @param cid 购物车数量的id
 * @param uid 当前登录的用户的id
 * @param username 当前登录的用户名
 * @return 增加成功后新的数量
 */
Integer addNum(Integer cid, Integer uid, String username);
2.3 实现抽象方法

1.在CartServiceImpl类中,实现接口中的抽象方法并规划业务逻辑。

public Integer addNum(Integer cid, Integer uid, String username) {
	// 调用findByCid(cid)根据参数cid查询购物车数据
	// 判断查询结果是否为null
	// 是:抛出CartNotFoundException

	// 判断查询结果中的uid与参数uid是否不一致
	// 是:抛出AccessDeniedException

	// 可选:检查商品的数量是否大于多少(适用于增加数量)或小于多少(适用于减少数量)
	// 根据查询结果中的原数量增加1得到新的数量num

	// 创建当前时间对象,作为modifiedTime
	// 调用updateNumByCid(cid, num, modifiedUser, modifiedTime)执行修改数量
}

2.实现addNum()方法中的业务逻辑代码。

@Override
public Integer addNum(Integer cid, Integer uid, String username) {
    // 调用findByCid(cid)根据参数cid查询购物车数据
    Cart result = cartMapper.findByCid(cid);
    // 判断查询结果是否为null
    if (result == null) {
        // 是:抛出CartNotFoundException
        throw new CartNotFoundException("尝试访问的购物车数据不存在");
    }

    // 判断查询结果中的uid与参数uid是否不一致
    if (!result.getUid().equals(uid)) {
        // 是:抛出AccessDeniedException
        throw new AccessDeniedException("非法访问");
    }

    // 可选:检查商品的数量是否大于多少(适用于增加数量)或小于多少(适用于减少数量)
    // 根据查询结果中的原数量增加1得到新的数量num
    Integer num = result.getNum() + 1;

    // 创建当前时间对象,作为modifiedTime
    Date now = new Date();
    // 调用updateNumByCid(cid, num, modifiedUser, modifiedTime)执行修改数量
    Integer rows = cartMapper.updateNumByCid(cid, num, username, now);
    if (rows != 1) {
        throw new InsertException("修改商品数量时出现未知错误,请联系系统管理员");
    }

    // 返回新的数量
    return num;
}

3.在CartServiceTests测试类中添加addNum()测试方法。

@Test
public void addNum() {
    try {
        Integer cid = 6;
        Integer uid = 31;
        String username = "管理员";
        Integer num = cartService.addNum(cid, uid, username);
        System.out.println("OK. New num=" + num);
    } catch (ServiceException e) {
        System.out.println(e.getClass().getSimpleName());
        System.out.println(e.getMessage());
    }
}

3 购物车-增加商品数量-控制器

3.1 处理异常

在BaseController类中添加CartNotFoundException异常类的统一管理。

// ...
else if (e instanceof CartNotFoundException) {
    result.setState(4007);
}
// ...
3.2 设计请求

设计用户提交的请求,并设计响应的方式。

请求路径:/carts/{cid}/num/add
请求参数:@PathVariable("cid") Integer cid, HttpSession session
请求类型:POST
响应结果:JsonResult<Integer>
3.3 处理请求

1.在CartController类中添加处理请求的addNum()方法。

@RequestMapping("{cid}/num/add")
public JsonResult<Integer> addNum(@PathVariable("cid") Integer cid, HttpSession session) {
    // 从Session中获取uid和username
    Integer uid = getUidFromSession(session);
    String username = getUsernameFromSession(session);
    // 调用业务对象执行增加数量
    Integer data = cartService.addNum(cid, uid, username);
    // 返回成功
    return new JsonResult<Integer>(OK, data);
}

2.完成后启动项目,先登录再访问http://localhost:8080/carts/6/num/add页面进行测试。

在这里插入图片描述

4 购物车-增加商品数量-前端页面

1.首先确定在showCartList()函数中动态拼接的增加购物车按钮是绑定了addNum()事件,如果已经添加无需重复添加。

<input class="num-btn" type="button" value="+" onclick="addNum(#{cid})" />

2.在script标签中定义addNum()函数并编写增加购物车数量的逻辑代码。

function addNum(cid) {
    $.ajax({
        url: "/carts/" + cid + "/num/add",
        type: "POST",
        dataType: "JSON",
        success: function(json) {
            if (json.state == 200) {
                // showCartList();
                $("#num-" + cid).val(json.data);
                let price = $("#price-" + cid).html();
                let totalPrice = price * json.data;
                $("#total-price-" + cid).html(totalPrice);
            } else {
                alert("增加商品数量失败!" + json.message);
            }
        },
        error: function(xhr) {
            alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
            location.href = "login.html";
        }
    });
}

3.完成后启动项目,先登录再访问http://localhost:8080/web/cart.html页面点击“+”按钮进行测试。

显示勾选的购物车数据

1 显示确认订单页-显示勾选的购物车数据-持久层

1.1 规划需要执行的SQL语句

在“确认订单页”显示的商品信息,应来自前序页面(购物车列表)中勾选的数据,所以显示的信息其实是购物车中的数据。到底需要显示哪些取决于用户的勾选操作,当用户勾选了若干条购物车数据后,这些数据的id应传递到当前“确认订单页”中,该页面根据这些id获取需要显示的数据列表。

所以在持久层需要完成“根据若干个不确定的id值,查询购物车数据表,显示购物车中的数据信息”。则需要执行的SQL语句大致是。

SELECT
	cid,
	uid,
	pid,
	t_cart.price,
	t_cart.num,
	t_product.title,
	t_product.price AS realPrice,
	t_product.image
FROM
	t_cart
	LEFT JOIN t_product ON t_cart.pid = t_product.id 
WHERE
	cid IN (?, ?, ?)
ORDER BY
	t_cart.created_time DESC	
1.2 接口与抽象方法

在CartMapper接口中添加findVOByCids(Integer[] cids)方法。

/**
 * 根据若干个购物车数据id查询详情的列表
 * @param cids 若干个购物车数据id
 * @return 匹配的购物车数据详情的列表
 */
List<CartVO> findVOByCids(Integer[] cids);
1.3 配置SQL映射

1.在CartMapper.xml文件中添加SQL语句的映射配置。

<!-- 根据若干个购物车数据id查询详情的列表:List<CartVO> findVOByCids(Integer[] cids) -->
<select id="findVOByCids" resultType="com.cy.store.vo.CartVO">
    SELECT
        cid,
        uid,
        pid,
        t_cart.price,
        t_cart.num,
        t_product.title,
        t_product.price AS realPrice,
        t_product.image
    FROM
        t_cart
            LEFT JOIN t_product ON t_cart.pid = t_product.id
    WHERE
        cid IN (
            <foreach collection="array" item="cid" separator=",">
                #{cid}
            </foreach>
        )
    ORDER BY
        t_cart.created_time DESC
</select>

2.在CartMapperTests测试类中添加findVOByCids()测试方法。

@Test
public void findVOByCids() {
    Integer[] cids = {1, 2, 6, 7, 8, 9, 10};
    List<CartVO> list = cartMapper.findVOByCids(cids);
    System.out.println("count=" + list.size());
    for (CartVO item : list) {
        System.out.println(item);
    }
}

2 显示确认订单页-显示勾选的购物车数据-业务层

2.1 规划异常

说明:无异常。

2.2 接口与抽象方法

在ICartService接口中添加getVOByCids()抽象方法。

/**
 * 根据若干个购物车数据id查询详情的列表
 * @param uid 当前登录的用户的id
 * @param cids 若干个购物车数据id
 * @return 匹配的购物车数据详情的列表
 */
List<CartVO> getVOByCids(Integer uid, Integer[] cids);
2.3 实现抽象方法

1.在CartServiceImpl类中重写业务接口中的抽象方法。

@Override
public List<CartVO> getVOByCids(Integer uid, Integer[] cids) {
    List<CartVO> list = cartMapper.findVOByCids(cids);
    /**
    for (CartVO cart : list) {
		if (!cart.getUid().equals(uid)) {
			list.remove(cart);
		}
	}
	*/
    Iterator<CartVO> it = list.iterator();
    while (it.hasNext()) {
        CartVO cart = it.next();
        if (!cart.getUid().equals(uid)) {
            it.remove();
        }
    }
    return list;
}

2.在CartServiceTests测试类中添加getVOByCids()测试方法。

@Test
public void getVOByCids() {
    Integer[] cids = {1, 2, 6, 7, 8, 9, 10};
    Integer uid = 31;
    List<CartVO> list = cartService.getVOByCids(uid, cids);
    System.out.println("count=" + list.size());
    for (CartVO item : list) {
        System.out.println(item);
    }
}

3 显示确认订单页-显示勾选的购物车数据-控制器

3.1 处理异常

说明:无异常。

3.2 设计请求

设计用户提交的请求,并设计响应的方式。

请求路径:/carts/list
请求参数:Integer[] cids, HttpSession session
请求类型:GET
响应结果:JsonResult<List<CartVO>>
3.3 处理请求

1.在CartController类中添加处理请求的getVOByCids()方法。

@GetMapping("list")
public JsonResult<List<CartVO>> getVOByCids(Integer[] cids, HttpSession session) {
    // 从Session中获取uid
    Integer uid = getUidFromSession(session);
    // 调用业务对象执行查询数据
    List<CartVO> data = cartService.getVOByCids(uid, cids);
    // 返回成功与数据
    return new JsonResult<>(OK, data);
}

2.完成后启动项目,先登录再访问http://localhost:8080/carts/list?cids=7&cids=8&cids=13&cids=14&cids=17地址进行测试。

4 显示确认订单页-前端页面

4.1 显示勾选的购物车数据-前端页面

1.在orderConfirm.html页面的head标签里注释掉引入外部的orderConfirm.js文件。

<!-- <script src="../js/orderConfirm.js" type="text/javascript" charset="utf-8"></script> -->

2.在orderConfirm.html页面中检查必要控件的属性是否添加,如果已添加无需重复添加。

3.在orderConfirm.html页面中的body标签内的最后添加srcipt标签并在标签内部添加处理购物车“订单商品信息”列表展示的代码。

<script type="text/javascript">
$(document).ready(function() {
    // showAddressList();
    showCartList();
});

function showCartList() {
    $("#cart-list").empty();
    $.ajax({
        url: "/carts/list",
        data: location.search.substr(1),
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            let list = json.data;
            console.log("count=" + list.length);
            let allCount = 0;
            let allPrice = 0;
            for (let i = 0; i < list.length; i++) {
                console.log(list[i].title);
                let tr = '<tr>'
                + '<td><img src="..#{image}collect.png" class="img-responsive" /></td>'
                + '<td><input type="hidden" name="cids" value="#{cid}" />#{title}</td>'
                + '<td>¥<span>#{realPrice}</span></td>'
                + '<td>#{num}</td>'
                + '<td>¥<span>#{totalPrice}</span></td>'
                + '</tr>';

                tr = tr.replace(/#{cid}/g, list[i].cid);
                tr = tr.replace(/#{image}/g, list[i].image);
                tr = tr.replace(/#{title}/g, list[i].title);
                tr = tr.replace(/#{realPrice}/g, list[i].realPrice);
                tr = tr.replace(/#{num}/g, list[i].num);
                tr = tr.replace(/#{totalPrice}/g, list[i].realPrice * list[i].num);

                $("#cart-list").append(tr);

                allCount += list[i].num;
                allPrice += list[i].realPrice * list[i].num;
            }
            $("#all-count").html(allCount);
            $("#all-price").html(allPrice);
        }
    });
}
</script>

4.完成后启动项目,先登录再访问http://localhost:8080/web/cart.html页面,勾选商品再点击“结算”按钮进行测试。

4.2 显示选择收货地址-前端页面

1.在orderConfirm.html页面中的body标签内的srcipt标签中添加获取收货地址列表方法的定义。

function showAddressList() {
    $("#address-list").empty();
    $.ajax({
        url: "/addresses",
        type: "GET",
        dataType: "JSON",
        success: function(json) {
            let list = json.data;
            console.log("count=" + list.length);
            for (let i = 0; i < list.length; i++) {
                console.log(list[i].name);
                let opt = '<option value="#{aid}">#{name} | #{tag} | #{province}#{city}#{area}#{address} | #{phone}</option>';

                opt = opt.replace(/#{aid}/g, list[i].aid);
                opt = opt.replace(/#{tag}/g, list[i].tag);
                opt = opt.replace("#{name}", list[i].name);
                opt = opt.replace("#{province}", list[i].provinceName);
                opt = opt.replace("#{city}", list[i].cityName);
                opt = opt.replace("#{area}", list[i].areaName);
                opt = opt.replace("#{address}", list[i].address);
                opt = opt.replace("#{phone}", list[i].phone);

                $("#address-list").append(opt);
            }
        }
    });
}

2.在orderConfirm.html页面中的body标签内的srcipt标签中添加展示收货地址列表方法的调用。

<script type="text/javascript">
    $(document).ready(function() {
        showAddressList();
        showCartList();
    });
</script>

3.完成后启动项目,先登录再访问http://localhost:8080/web/orderConfirm.html页面进行测试。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/192356.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Redis:持久化RDB和AOF

目录 概述RDB持久化流程指定备份文件的名称指定备份文件存放的目录触发RDB备份redis.conf 其他一些配置rdb的备份和恢复优缺点停止RDB AOF持久化流程AOF启动/修复/恢复AOF同步频率设置rewrite压缩原理触发机制重写流程no-appendfsync-on-rewrite 优缺点 如何选择 概述 Redis是…

Ubuntu+Tesla V100环境配置

系统基本信息 nvidia-smi’ nvidia-smi 470.182.03 driver version:470.182.03 cuda version: 11.4 查看系统体系结构 uname -aUTC 2023 x86_64 x86_64 x86_64 GNU/Linux 下载miniconda https://mirrors.tuna.tsinghua.edu.cn/anaconda/miniconda/?CM&OA https://mi…

新时代线下门店如何能够降低创业者的风险?

随着社会的发展和科技的进步&#xff0c;共享经济已经渗透到生活的各个领域。在这个大背景下&#xff0c;共享门店共享股东的商业模式应运而生&#xff0c;为传统门店经营带来了全新的思路和方向。而下面这个故事诠释了一个普通青年的底层崛起之路。 在繁华的都市中&#xff0c…

5、Qt:项目中包含多个子项目(.pro)/子模块(.pri)

一、说明&#xff1a; 在进行项目开发过程中&#xff0c;会涉及子项目/子模块的问题 Qt中使用TEMPLATE subdirs添加多个子项目&#xff1b;子项目可以单独编译生成可执行文件&#xff08;exe&#xff09;或者动态链接库&#xff08;dll&#xff09;等&#xff0c;供其他模块…

阿里云ACE认证之国际版与国内版对比!

大厂疯狂裁员&#xff0c;互联网行业迎来寒冬&#xff0c;技术人员被动陷入疯狂内卷。在愈加内卷的IT领域&#xff0c;“云计算”作为少有的蓝海&#xff0c;无疑是打工人未来实现职场提升、摆脱内卷的绝佳选择&#xff01; 对于云计算行业的人来说&#xff0c;最值得考的肯定是…

Linux中部署MongoDB

在 是一个必要的过程&#xff0c;因为MongoDB是一种流行的NoSQL数据库&#xff0c;它可以在大多数操作系统上使用。在本文中&#xff0c;我们将介绍如何在CentOS 8上部署MongoDB。 MongoDB的下载 您可以从MongoDB官网上下载最新的MongoDB版本。使用以下命令下载MongoDB&#…

C#,《小白学程序》第二十二课:大数的乘法(BigInteger Multiply)

1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary> /// 大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算 /// 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法 /// </summary> p…

python的pandas中如何在dataframe中插入一行或一列数据?

dataframe类型是如何插入一行或一列数据的呢&#xff1f;这个需求在本文中将会进行讨论。相比较ndarray类型的同样的“数据插入”需求&#xff0c;dataframe的实现方式&#xff0c;则不是很好用。本文以一个dataframe类型变量为例&#xff0c;测试插入一行数据或者一列数据的方…

人力资源管理后台 === 登陆+主页鉴权

目录 1. 分析登录流程 2. Vuex中用户模块的实现 3.Vue-cli代理解决跨域 4.axios封装 5.环境区分 6. 登录联调 7.主页权限验证-鉴权 1. 分析登录流程 传统思路都是登录校验通过之后&#xff0c;直接调用接口&#xff0c;获取token之后&#xff0c;跳转到主页。 vue-elemen…

【心得】XXE漏洞利用个人笔记

XML中关于DTD类型(内部(SYSTEM)的和外部(PUBLIC)的区别) xxe的利用 XML Entity 实体注入 当程序处理xml文件时&#xff0c;没有禁止对外部实体的处理&#xff0c;容易造成xxe漏洞 危害 主流是任意文件读取 XML 文件 一般表示带有结构的数据 祖父 3个叔父 8个堂弟堂妹 …

App备案与iOS云管理式证书 ,公钥及证书SHA-1指纹的获取方法

&#x1f4dd; App备案与iOS云管理式证书 &#xff0c;公钥及证书SHA-1指纹的获取方法 引言 在iOS应用程序开发过程中&#xff0c;进行App备案并获取公钥及证书SHA-1指纹是至关重要的步骤。本文将介绍如何通过appuploader工具获取iOS云管理式证书 Distribution Managed 公钥…

Django(十一、auth认证模块)

文章目录 一、auth介绍auth认证相关模块及操作扩展auth_user表 一、auth介绍 Django自带一个admin路由&#xff0c;但是需要我们提供管理员账户和密码&#xff0c;如果想要使用admin后台管理&#xff0c;需要先创建表&#xff0c;然后创建管理员账户。 直接执行数据类迁移命令…

二、Lua数据类型

文章目录 一、数据类型nil二、数据类型boolean三、数据类型number四、数据类型String&#xff08;一&#xff09;用单引号或双引号&#xff1a;&#xff08;二&#xff09;可以包含换行的字符串&#xff08;三&#xff09;字符串与数字做数学运算时&#xff0c;优先将字符串转换…

抖音开新店,十个设置,实操满满全是干货

抖店开店的第一天手足无措不知从哪入手&#xff1f;我给大家分享一个新手开店必须完成的十个设置&#xff0c;实操满满全是干货&#xff0c;每一项都很重要&#xff01;特别是新手一定要认真看&#xff0c;因为这个直接关系到你店铺能否正常经营&#xff0c;跟着我一起来实操一…

C语言线性表的实现(详解)

数据结构之线性表 ​ 线性表的基本概念&#xff1a;线性表是由0个或者多个数据元素的有限序列 ​ 特性是&#xff1a; ​ 1&#xff1a;数据元素之间都是有顺序的 ​ 2&#xff1a;数据元素的个数是有限的&#xff0c; ​ 3&#xff1a;数据元素的类型是相同的 ​ 性质是&…

Java代码生成器,一键在线生成,支持自定义模板

【Java代码生成神器】自动化生成Java实体类、代码、增删改查功能&#xff01;点击访问 推荐一个自己每天都在用的Java代码生成器&#xff01;这个网站支持在线生成Java代码&#xff0c;包含完整的Controller\Service\Entity\Dao代码&#xff0c;完整的增删改查功能&#xff01…

给国外客户价格报低了怎么办

前一段时间有一个单子的货发出去了&#xff0c;被朋友提醒才发现自己报错了价格&#xff0c;造成了亏损&#xff0c;而报错价格的原因并不是自己看错了或者是抄错了价格&#xff0c;而是自己的脑子里记错了产品的价格列表。 如果不是朋友善意的提醒&#xff0c;大概我会一直错…

.NET的Dockerfile文件编写要点——以WOL项目为例

本文以 WOL 的.NET 项目为例&#xff0c;介绍了 Dockerfile 的基础知识和编写要点&#xff0c;旨在帮助读者更好地理解和掌握如何为 .NET 应用创建和优化 Dockerfile。 1. 背景 前面我们已经勾选了 Docker 容器化支持&#xff0c;项目已经生成了一个默认的 Dockerfile。但在实…

快速上手Banana Pi BPI-R4 MediaTek MT7988A 开源路由器开发板

基础开发 准备开发 * 准备8G以上TF卡、USB转串口线、Ubuntu系统* 使用 USB 串行电缆&#xff08;3.3V TTL&#xff0c;波特115200&#xff09;连接到 BPI-R4 上的调试控制台G接地&#xff1b;RXBPI-R4输入&#xff1b;TXBPI-R4输出* BPI-R4 引导程序和设备选择跳线设置* 例子…

部署Jenkins

一、介绍 Jenkins 、Jenkins概念 Jenkins是一个功能强大的应用程序&#xff0c;允许持续集成和持续交付项目&#xff0c;无论用的是什么平台。这是一个免费的源代码&#xff0c;可以处理任何类型的构建或持续集成。集成Jenkins可以用于一些测试和部署技术。Jenkins是一种软件允…