商品列表功能 +商品列表详情
GoodsController
package com.duing.controller;
import com.duing.model.Goods;
import com.duing.service.GoodsService;
import com.duing.vo.GoodsDetailVo;
import com.duing.vo.GoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Controller
public class GoodsController {
@Autowired
private GoodsService goodsService;
@GetMapping("/")
public String list(Model model) {
List<GoodsVo> voList = goodsService.getGoods();
model.addAttribute("voList",voList);
return "list";
}
@GetMapping("/goodsDetail/{goodsId}")
public String goodsDetail(Model model, @PathVariable String goodsId){
GoodsDetailVo goodsDetailVo= goodsService.goodsDetail(goodsId);
Date startTime=goodsDetailVo.getStartTime();
Date endTime=goodsDetailVo.getEndTime();
Date nowTime=new Date();
int status,remainSeconds=-1;
if (nowTime.before(startTime)){
status=0;
remainSeconds=(int)((startTime.getTime()- nowTime.getTime())/1000);
}else if (nowTime.after(endTime)){
status=2;
remainSeconds=(int)((endTime.getTime()- nowTime.getTime())/1000);
}else {
status=1;
}
model.addAttribute("detailVo",goodsDetailVo);
model.addAttribute("status",status);
model.addAttribute("remainSeconds",remainSeconds);
return "detail";
}
}
GoodsMapper
package com.duing.mapper;
import com.duing.model.Goods;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@Mapper
public interface GoodsMapper {
List<Goods> getGoods();
Goods getGoodsById(String goodsId);
}
SeckillGoodsMapper
package com.duing.mapper;
import com.duing.model.SeckillGoods;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SeckillGoodsMapper {
SeckillGoods getSeckillGoodsById(String goodsId);
}
Goods
package com.duing.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Goods {
private long id;
private String goodsId;
private String goodsName;
private String goodsType;
private Double price;
private String imgPath;
}
SeckillGoods
package com.duing.model;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SeckillGoods {
private long id;
private String goodsId;
private Double seckillPrice;
private int stockNum;
private Date startTime;
private Date endTime;
}
GoodsServiceImpl
package com.duing.service.impl;
import com.duing.mapper.GoodsMapper;
import com.duing.mapper.SeckillGoodsMapper;
import com.duing.model.Goods;
import com.duing.model.SeckillGoods;
import com.duing.service.GoodsService;
import com.duing.vo.GoodsDetailVo;
import com.duing.vo.GoodsVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsMapper goodsMapper;
@Autowired
private SeckillGoodsMapper seckillGoodsMapper;
@Override
public List<GoodsVo> getGoods() {
List<Goods> goodsList=goodsMapper.getGoods();
List<GoodsVo> voList=new ArrayList<>();
for (Goods goods:goodsList){
GoodsVo vo=new GoodsVo();
BeanUtils.copyProperties(goods,vo);
System.out.println(vo.getGoodsId());
SeckillGoods seckillGoods= seckillGoodsMapper.getSeckillGoodsById(vo.getGoodsId());
BeanUtils.copyProperties(seckillGoods,vo);
voList.add(vo);
}
return voList;
}
@Override
public GoodsDetailVo goodsDetail(String goodsId) {
Goods goods= goodsMapper.getGoodsById(goodsId);
SeckillGoods seckillGoods= seckillGoodsMapper.getSeckillGoodsById(goodsId);
GoodsDetailVo vo=new GoodsDetailVo();
BeanUtils.copyProperties(goods,vo);
BeanUtils.copyProperties(seckillGoods,vo);
return vo;
}
}
GoodsService
package com.duing.service;
import com.duing.vo.GoodsDetailVo;
import com.duing.vo.GoodsVo;
import java.util.List;
public interface GoodsService {
List<GoodsVo> getGoods();
GoodsDetailVo goodsDetail(String goodsId);
}
GoodsDetailVo
package com.duing.vo;
// 商品详情的展示数据
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GoodsDetailVo {
private String name;
private String goodsId;
private String imgPath;
private Double price;
private Double seckillPrice;
private int stockNum;
private Date startTime;
private Date endTime;
}
GoodsVo
package com.duing.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class GoodsVo {
private String goodsId;
private String goodsName;
private String goodsType;
private Double price;
private String imgPath;
private Double seckillPrice;
private int stockNum;
}
GoodsMapper.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.duing.mapper.GoodsMapper">
<resultMap id="single" type="com.duing.model.Goods">
<id property="id" column="id"/>
<result property="goodsId" column="goods_id"/>
<result property="goodsName" column="goods_name"/>
<result property="goodsType" column="goods_type"/>
<result property="price" column="price"/>
<result property="imgPath" column="img_path"/>
</resultMap>
<select id="getGoods" resultType="com.duing.model.Goods" resultMap="single">
select id, goods_id, goods_name, goods_type, price, img_path
from goods
</select>
<select id="getGoodsById" resultType="com.duing.model.Goods" resultMap="single">
select id, goods_id, goods_name, goods_type, price, img_path
from goods where goods_id = #{goodsId}
</select>
</mapper>
SeckillGoodsMapper.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.duing.mapper.SeckillGoodsMapper">
<resultMap id="single" type="com.duing.model.SeckillGoods">
<id property="id" column="id"/>
<result property="goodsId" column="goods_id"/>
<result property="seckillPrice" column="seckill_price"/>
<result property="stockNum" column="stock_num"/>
<result property="startTime" column="start_time"/>
<result property="endTime" column="end_time"/>
</resultMap>
<select id="getSeckillGoodsById" resultType="com.duing.model.SeckillGoods" resultMap="single">
select id, goods_id, seckill_price, stock_num, start_time, end_time
from seckill_goods where goods_id = #{goodsId}
</select>
</mapper>
detail.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/detail.css}"/>
<script type="text/javascript" th:src="@{/js/jquery-3.6.0.min.js}"></script>
</head>
<body>
<h1> 商品详情 </h1>
<br/><br/>
<table class="table table-hover">
<tr>
<td>商品名称</td>
<td clospan="3" th:text="${detailVo.name}"></td>
</tr>
<tr>
<td>商品图片</td>
<td clospan="3">
<img th:src="@{${detailVo.imgPath}}" width="200" height="200"/>
</td>
</tr>
<td>秒杀开始时间</td>
<td colspan="3" th:text="${#dates.format(detailVo.startTime,'yyyy-MM-dd HH:mm:ss')}"></td>
<td id="seckillTip">
<input type="hidden" id="remainSeconds" th:value="${remainSeconds}">
<input type="hidden" id="status" th:value="${status}">
<span th:if="${status eq 0}">秒杀倒计时:
<span id="countDown" th:text="${remainSeconds}"></span>秒
</span>
<span th:if="${status eq 1}">秒杀进行中</span>
<span th:if="${status eq 2}">秒杀已结束</span>
</td>
<td>
<form id="seckillForm" method="post" action="/toSeckill">
<input type="hidden" name="goodsId" th:value="${detailVo.goodsId}">
<button type="submit" id="buyButton">抢购</button>
</form>
</td>
<tr>
<td>商品原价</td>
<td clospan="3" th:text="${detailVo.price}"></td>
</tr>
<tr>
<td>商品秒杀价</td>
<td clospan="3" th:text="${detailVo.seckillPrice}"></td>
</tr>
<tr>
<td>库存数量</td>
<td clospan="3" th:text="${detailVo.stockNum}"></td>
</tr>
</table>
</body>
</html>
list.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>秒杀商品列表</title>
<link rel="stylesheet" th:href="@{/css/bootstrap.css}">
<link rel="stylesheet" type="text/css" th:href="@{/css/goods.css}"/>
</head>
<body>
<div class="seckill_content">
<div class="title"><h2>秒杀商品列表</h2></div>
<div class="all_seckill_goods">
<div class="seckill_goods" th:each="goodsVo: ${voList}">
<h4 th:text="${goodsVo.goodsName}"></h4>
<img th:src="@{${goodsVo.imgPath}}" width="250" height="270"/>
<br/><br/>
<div class="seckill_price">
<p th:text="${goodsVo.goodsType}"></p>
<p>
<span class="price1" th:text="${goodsVo.seckillPrice}+'元 '"></span>
<del><span class="price2" th:text="${goodsVo.price}+'元'"></span></del>
</p>
<a th:href="'/goodsDetail/'+${goodsVo.goodsId}">
<button class="btn btn-default" type="submit">进入详情页...</button>
</a>
</div>
</div>
</div>
</div>
</body>
</html>
application.yml
spring:
datasource:
url: jdbc:mysql://localhost:3306/seckill
username: root
password: cy414ljh212,,,
driver-class-name: com.mysql.cj.jdbc.Driver
mybatis:
mapper-locations: classpath*:/mappers/*.xml
type-aliases-package: com.duing.model
bootstrap.cssdetail.cssgoods.css111.png222.png333.pngjquery-3.6.0.min.jspom.xml