Java十天上手做一个自己的web商城笔记-商品列表与商品详情(11)

 该系列博客主要记录笔者的开发过程,参考B站系列视频:【SpringBoot项目实战完整版】SpringBoot+MyBatis+MySQL电脑商城项目实战_哔哩哔哩_bilibili

所用的一些版本信息:

IDEA开发、JDK1.8版本以上、maven3.61版本以上,springboot,DataGrip管理数据库

商品页面(热销排行):

商品详情页面: 

 0 前置准备

0.1 创建表

创建商品表t_product 与t_product_category表

构建的语句文档可以在我的github上找到:

store_java_springboot/t_product.sql at main · LYJAntelope/store_java_springboot · GitHub

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;

CREATE TABLE t_product_category (
  id int(20) NOT NULL COMMENT '主键',
  parent_id bigint(20) DEFAULT NULL COMMENT '父分类id',
  name varchar(150) DEFAULT NULL COMMENT '名称',
  status int(1) DEFAULT '1' COMMENT '状态   1:正常   0:删除',
  sort_order int(4) DEFAULT NULL COMMENT '排序号',
  is_parent int(1) DEFAULT NULL COMMENT '是否是父分类   1:是  0:否',
  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;

 0.2 创建实体类

创建:store\src\main\java\com\cy\store\entity\Product.java

package com.cy.store.entity;

import java.io.Serializable;

/** 商品数据的实体类 */
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;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(Integer categoryId) {
        this.categoryId = categoryId;
    }

    public String getItemType() {
        return itemType;
    }

    public void setItemType(String itemType) {
        this.itemType = itemType;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getSellPoint() {
        return sellPoint;
    }

    public void setSellPoint(String sellPoint) {
        this.sellPoint = sellPoint;
    }

    public Long getPrice() {
        return price;
    }

    public void setPrice(Long price) {
        this.price = price;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    public String getImage() {
        return image;
    }

    public void setImage(String image) {
        this.image = image;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Integer getPriority() {
        return priority;
    }

    public void setPriority(Integer priority) {
        this.priority = priority;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Product)) return false;

        Product product = (Product) o;

        if (getId() != null ? !getId().equals(product.getId()) : product.getId() != null) return false;
        if (getCategoryId() != null ? !getCategoryId().equals(product.getCategoryId()) : product.getCategoryId() != null)
            return false;
        if (getItemType() != null ? !getItemType().equals(product.getItemType()) : product.getItemType() != null)
            return false;
        if (getTitle() != null ? !getTitle().equals(product.getTitle()) : product.getTitle() != null) return false;
        if (getSellPoint() != null ? !getSellPoint().equals(product.getSellPoint()) : product.getSellPoint() != null)
            return false;
        if (getPrice() != null ? !getPrice().equals(product.getPrice()) : product.getPrice() != null) return false;
        if (getNum() != null ? !getNum().equals(product.getNum()) : product.getNum() != null) return false;
        if (getImage() != null ? !getImage().equals(product.getImage()) : product.getImage() != null) return false;
        if (getStatus() != null ? !getStatus().equals(product.getStatus()) : product.getStatus() != null) return false;
        return getPriority() != null ? getPriority().equals(product.getPriority()) : product.getPriority() == null;
    }

    @Override
    public int hashCode() {
        int result = getId() != null ? getId().hashCode() : 0;
        result = 31 * result + (getCategoryId() != null ? getCategoryId().hashCode() : 0);
        result = 31 * result + (getItemType() != null ? getItemType().hashCode() : 0);
        result = 31 * result + (getTitle() != null ? getTitle().hashCode() : 0);
        result = 31 * result + (getSellPoint() != null ? getSellPoint().hashCode() : 0);
        result = 31 * result + (getPrice() != null ? getPrice().hashCode() : 0);
        result = 31 * result + (getNum() != null ? getNum().hashCode() : 0);
        result = 31 * result + (getImage() != null ? getImage().hashCode() : 0);
        result = 31 * result + (getStatus() != null ? getStatus().hashCode() : 0);
        result = 31 * result + (getPriority() != null ? getPriority().hashCode() : 0);
        return result;
    }

    @Override
    public String toString() {
        return "Product{" +
                "id=" + id +
                ", categoryId=" + categoryId +
                ", itemType='" + itemType + '\'' +
                ", title='" + title + '\'' +
                ", sellPoint='" + sellPoint + '\'' +
                ", price=" + price +
                ", num=" + num +
                ", image='" + image + '\'' +
                ", status=" + status +
                ", priority=" + priority +
                "} " + super.toString();
    }
}

1 持久层

1.1 规划SQL语句

1 查询热销商品 select

2 根据商品id查询商品

1.2 接口与方法

新建:store\src\main\java\com\cy\store\mapper\ProducterMapper.java

package com.cy.store.mapper;

import com.cy.store.entity.Product;

import java.util.List;

/** 商品mapper接口 */
public interface ProducterMapper {
    /**
     * 查询热销商品的前四名
     * @return 热销商品前四名的集合
     */
    List<Product> findHotList();

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

1.3 SQL映射

新建:store\src\main\resources\mapper\ProducterMapper.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">
<!--namespace需要映射到java中的接口,指定路径-->
<mapper namespace="com.cy.store.mapper.ProducterMapper">
    <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>

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

2 业务层

2.1 规划异常

存在商品找不到的异常 ProductNotFound

2.2 接口与抽象方法

新建:store\src\main\java\com\cy\store\service\IProductService.java

package com.cy.store.service;

import com.cy.store.entity.Product;

import java.util.List;

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

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

2.3 抽象方法实现

新建:store\src\main\java\com\cy\store\service\impl\ProductServiceImpl.java

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 com.cy.store.service.ex.ProductNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/** 处理商品数据的业务层实现类 */
@Service
public class ProductServiceImpl implements IProductService {
    @Resource
    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;
    }

    @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;
    }
}

3 控制层

3.1 处理异常

在store\src\main\java\com\cy\store\controller\BaseController.java中处理异常

 

3.2 设计请求

查询热销商品列表:

URL:/products/hot_list
请求方式:GET
请求参数:无
返回值:JsonResult<List<Product>>

查询某个商品的详情:

URL:/{id}/details
请求方式:GET
请求参数:@PathVariable("id") Integer id
返回值:JsonResult<Product>

我们需要将上面两个请求添加到白名单中。

在store\src\main\java\com\cy\store\config\LoginInterceptorConfigurer.java中进行配置

3.3 处理请求

新建:store\src\main\java\com\cy\store\controller\ProductController.java

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.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;

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

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

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

4 前端页面

store\src\main\resources\static\web\index.html中添加:

		<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>

store\src\main\resources\static\web\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);
						}
					}
				});
			});

			$("#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";
					}
				});
			});
		</script>

5 测试

结合前端页面进行测试

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值