文章目录  1.数据库表设计 1.商品表 2.秒杀商品表 3.修改一下秒杀时间为今天到明天     2.pojo和vo编写 1.com/sxs/seckill/pojo/Goods.java 2.com/sxs/seckill/pojo/SeckillGoods.java 3.com/sxs/seckill/vo/GoodsVo.java     3.Mapper编写 1.GoodsMapper.java 2.GoodsMapper.xml 3.分别编写SeckillGoodsMapper.java和SeckillGoodsMapper.xml     4.Service编写 1.GoodsService.java 2.GoodsServiceImpl.java 3.分别编写SeckillGoodsService.java和SeckillGoodsServiceImpl.java     5.Controller编写   6.展示商品列表页 1.goodsList.html 2.测试使用 1.报错,GoodsService没被注入 2.加一下Service注解即可 3.登录成功 4.访问 http://localhost:9092/seckill/goods/toList 没有图片 5.把图片放到imgs下即可 6.重新访问   3.调整templates/login.html 登录成功后直接跳转到商品列表页       7.商品详情页 1.Mapper编写 根据商品id获取商品详情 1.GoodsMapper.java 2.GoodsMapper.xml   2.Service编写 1.GoodsService.java 2.GoodsServiceImpl.java   3.Controller编写   4.前端界面编写 1.goodsList.html 修改请求(使用环境变量+资源路径的形式) 2.goodsDetail.html 商品详情页   5.测试           
  
 
 1.数据库表设计  
 1.商品表  
use  seckill; DROP  TABLE  IF  EXISTS  ` t_goods` ; 
CREATE  TABLE  ` t_goods`  
( ` id`             BIGINT ( 20 )   NOT  NULL  AUTO_INCREMENT  COMMENT  '商品 id' , ` goods_name`     VARCHAR ( 16 )  not  null  DEFAULT  '' , ` goods_title`    VARCHAR ( 64 )  not  null  DEFAULT  ''  COMMENT  '商品标题' , ` goods_img`      VARCHAR ( 64 )  not  null  DEFAULT  ''  COMMENT  '商品图片' , ` goods_detail`   LONGTEXT     not  null  COMMENT  '商品详情' , ` goods_price`    DECIMAL ( 10 ,  2 )        DEFAULT  '0.00'  COMMENT  '商品价格' , ` goods_stock`    INT ( 11 )               DEFAULT  '0'  COMMENT  '商品库存' , PRIMARY  KEY  ( ` id` ) 
)  ENGINE  =  INNODB AUTO_INCREMENT  =  3 DEFAULT  CHARSET  =  utf8mb4; INSERT  INTO  ` t_goods`  
VALUES  ( '1' ,  '整体厨房设计-套件' ,  '整体厨房设计-套件' ,  '/imgs/kitchen.jpg' ,  '整体厨房设计-套件' ,  '15266.00' ,  '100' ) ; 
INSERT  INTO  ` t_goods`  
VALUES  ( '2' ,  '学习书桌-套件' ,  '学习书桌-套件' ,  '/imgs/desk.jpg' ,  '学习书桌-套件' ,  '5690.00' ,  '100' ) ; select  *  from  t_goods; 
  
 2.秒杀商品表  
use  seckill; DROP  TABLE  IF  EXISTS  ` t_seckill_goods` ; 
CREATE  TABLE  ` t_seckill_goods`  
( ` id`              BIGINT ( 20 )  NOT  NULL  AUTO_INCREMENT , ` goods_id`        BIGINT ( 20 )      DEFAULT  0 , ` seckill_price`   DECIMAL ( 10 ,  2 )  DEFAULT  '0.00' , ` stock_count`     INT ( 10 )         DEFAULT  0 , ` start_date`      DATETIME        DEFAULT  NULL , ` end_date`        DATETIME        DEFAULT  NULL , PRIMARY  KEY  ( ` id` ) 
)  ENGINE  =  INNODB AUTO_INCREMENT  =  3 DEFAULT  CHARSET  =  utf8mb4; INSERT  INTO  ` t_seckill_goods`  
VALUES  ( '1' ,  '1' ,  '5266.00' ,  '10' ,  '2022-11-18 19:36:00' ,  '2022-11-19 09:00:00' ) ; 
INSERT  INTO  ` t_seckill_goods`  
VALUES  ( '2' ,  '2' ,  '690.00' ,  '10' ,  '2022-11-18 08:00:00' ,  '2022-11-19 09:00:00' ) ; select  *  from  t_seckill_goods; 
  
 3.修改一下秒杀时间为今天到明天  
 
 2.pojo和vo编写  
 1.com/sxs/seckill/pojo/Goods.java  
package  com. sxs. seckill. pojo ; import  com. baomidou. mybatisplus. annotation.  IdType ; 
import  com. baomidou. mybatisplus. annotation.  TableId ; 
import  com. baomidou. mybatisplus. annotation.  TableName ; 
import  lombok.  Data ; import  java. io.  Serializable ; 
import  java. math.  BigDecimal ; 
@Data 
@TableName ( "t_goods" ) 
public  class  Goods  implements  Serializable  { private  static  final  long  serialVersionUID =  1L ; @TableId ( value =  "id" ,  type =  IdType . AUTO ) private  Long  id; private  String  goodsName; private  String  goodsTitle; private  String  goodsImg; private  String  goodsDetail; private  BigDecimal  goodsPrice; private  Integer  goodsStock; 
} 
  
 2.com/sxs/seckill/pojo/SeckillGoods.java  
package  com. sxs. seckill. pojo ; import  com. baomidou. mybatisplus. annotation.  IdType ; 
import  com. baomidou. mybatisplus. annotation.  TableId ; 
import  com. baomidou. mybatisplus. annotation.  TableName ; 
import  lombok.  Data ; import  java. io.  Serializable ; 
import  java. math.  BigDecimal ; 
import  java. util.  Date ; 
@Data 
@TableName ( "t_seckill_goods" ) 
public  class  SeckillGoods  implements  Serializable  { private  static  final  long  serialVersionUID =  1L ; @TableId ( value =  "id" ,  type =  IdType . AUTO ) private  Long  id; private  Long  goodsId; private  BigDecimal  seckillPrice; private  Integer  stockCount; private  Date  startDate; private  Date  endDate; 
}   
 3.com/sxs/seckill/vo/GoodsVo.java  
package  com. sxs. seckill. vo ; import  com. sxs. seckill. pojo.  Goods ; 
import  lombok.  AllArgsConstructor ; 
import  lombok.  Data ; 
import  lombok.  NoArgsConstructor ; import  java. math.  BigDecimal ; 
import  java. util.  Date ; 
@Data 
@AllArgsConstructor 
@NoArgsConstructor 
public  class  GoodsVo  extends  Goods  { private  BigDecimal  seckillPrice; private  Integer  stockCount; private  Date  startDate; private  Date  endDate; 
}   
 3.Mapper编写  
 1.GoodsMapper.java  
package  com. sxs. seckill. mapper ; import  com. baomidou. mybatisplus. core. mapper.  BaseMapper ; 
import  com. sxs. seckill. pojo.  Goods ; 
import  com. sxs. seckill. vo.  GoodsVo ; 
import  org. apache. ibatis. annotations.  Mapper ; import  java. util.  List ; 
@Mapper 
public  interface  GoodsMapper  extends  BaseMapper < Goods >   { List < GoodsVo >   findGoodsVo ( ) ; 
}   
 2.GoodsMapper.xml  
resultType为GoodsVo,则可以自动按照驼峰命名法进行匹配   
<?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.sxs.seckill.mapper.GoodsMapper" > < select  id = " findGoodsVo"   resultType = " com.sxs.seckill.vo.GoodsVo" >  select g.id,g.goods_name,g.goods_title,g.goods_img,g.goods_detail,g.goods_price,g.goods_stock,t_seckill_goods.seckill_price,t_seckill_goods.stock_count,t_seckill_goods.start_date,t_seckill_goods.end_datefrom t_goods gleft join t_seckill_goods on g.id = t_seckill_goods.goods_id;</ select>  
</ mapper>  
  
 3.分别编写SeckillGoodsMapper.java和SeckillGoodsMapper.xml  
 4.Service编写  
 1.GoodsService.java  
package  com. sxs. seckill. service ; import  com. baomidou. mybatisplus. extension. service.  IService ; 
import  com. sxs. seckill. pojo.  Goods ; 
import  com. sxs. seckill. vo.  GoodsVo ; import  java. util.  List ; 
public  interface  GoodsService  extends  IService < Goods >   { List < GoodsVo >   findGoodsVo ( ) ; 
}   
 2.GoodsServiceImpl.java  
package  com. sxs. seckill. service. impl ; import  com. baomidou. mybatisplus. extension. service. impl.  ServiceImpl ; 
import  com. sxs. seckill. mapper.  GoodsMapper ; 
import  com. sxs. seckill. pojo.  Goods ; 
import  com. sxs. seckill. service.  GoodsService ; 
import  com. sxs. seckill. vo.  GoodsVo ; import  javax. annotation.  Resource ; 
import  java. util.  List ; 
public  class  GoodsServiceImpl  extends  ServiceImpl < GoodsMapper ,  Goods >   implements  GoodsService  { @Resource private  GoodsMapper  goodsMapper; @Override public  List < GoodsVo >   findGoodsVo ( )  { return  goodsMapper. findGoodsVo ( ) ; } 
}   
 3.分别编写SeckillGoodsService.java和SeckillGoodsServiceImpl.java  
 5.Controller编写  
 1.GoodsController.java  
 
 6.展示商品列表页  
 1.goodsList.html  
< html  lang = " en"   xmlns: th= " http://www.thymeleaf.org" >  
< head> < meta  charset = " UTF-8" > < title>  商品列表</ title> < link  rel = " stylesheet"   type = " text/css"   th: href= " @{/bootstrap/css/bootstrap.min.css}" /> < script  type = " text/javascript"   th: src= " @{/js/jquery.min.js}" > </ script> < script  type = " text/javascript"   th: src= " @{/jquery-validation/jquery.validate.min.js}" > </ script> < script  type = " text/javascript" th: src= " @{/jquery-validation/localization/messages_zh.min.js}" > </ script> < script  type = " text/javascript"   th: src= " @{/layer/layer.js}" > </ script> < script  type = " text/javascript"   th: src= " @{/js/md5.min.js}" > </ script> < script  type = " text/javascript"   th: src= " @{/js/common.js}" > </ script> < style> *  { margin :  0; padding :  0; font-family :  "Open Sans" ,  sans-serif; text-transform :  uppercase; letter-spacing :  3px; font-size :  11px; } body  { background :  #c9302c; } .main-header  { width :  100%; height :  100px; background :  whitesmoke; display :  block; } .navbar  { display :  inline-block; float :  right; margin-right :  50px; margin-top :  30px; } .logo  { display :  inline-block; margin-top :  30px; margin-left :  30px; text-decoration :  none; } .logo-lg  { font-size :  20px; font-weight :  lighter; color :  #232324; } .logo-lg > b  { font-size :  20px; font-weight :  lighter; color :  #232324; } .container  { background :  #FFFFFF; } .add-good  { padding-top :  12px; padding-bottom :  20px; border-radius :  10px; outline :  none; display :  block; margin-right :  30px; background :  #f6f6f6; color :  #ce7d88; border :  solid 1px #eac7cc; } </ style>  
</ head>  
< body>  
< header  id = " site-header"   class = " main-header" > < a  class = " logo"   th: href= " @{/goods/toList}" > < span  class = " logo-lg" > < b>  商品抢购</ b> </ span> </ a> < nav  class = " navbar navbar-static-top" > < a  href = " #"   class = " sidebar-toggle"   data-toggle = " push-menu"   role = " button" > < span  class = " sr-only" >  Toggle navigation</ span> < span  class = " icon-bar" > </ span> < span  class = " icon-bar" > </ span> < span  class = " icon-bar" > </ span> </ a> < div  class = " navbar-custom-menu" > < ul  class = " nav navbar-nav" > < li  class = " dropdown user user-menu" > < a  href = " #"   class = " dropdown-toggle"   data-toggle = " dropdown" > < img  class = " user-image"   src = " /imgs/user.png"   height = " 42"   alt = " User
Image" > < span  class = " hidden-xs" > </ span> </ a> < ul  class = " dropdown-menu" > < li  class = " user-header" > < img  class = " img-circle"   alt = " User Image" > < p>  Hello ABC - Hello ABC< small>  Hello ABC</ small> </ p> </ li> < li  class = " user-body" > </ li> < li  class = " user-footer" > < div  class = " pull-middle" > < a  th: href= " @{/login/out}"   class = " btn btn-lg btn-default
btn-block" >  退出系统</ a> </ div> </ li> </ ul> </ li> </ ul> </ div> </ nav>  
</ header>  
< div  class = " container" > < div  class = " panel-heading" >  秒杀商品列表</ div> < table  class = " table"   id = " goodslist" > < tr> < td>  名称</ td> < td>  图片</ td> < td>  原价</ td> < td>  秒杀价</ td> < td>  库存</ td> < td>  详情</ td> </ tr> < tr  th: each= " goods,goodstStat : ${goodsList}" > < td  th: text= " ${goods.goodsName}" > </ td> < td> < img  th: src= " @{${goods.goodsImg}}"   width = " 100"   height = " 100" /> </ td> < td  th: text= " ${goods.goodsPrice}" > </ td> < td  th: text= " ${goods.seckillPrice}" > </ td> < td  th: text= " ${goods.stockCount}" > </ td> < td> < a  th: href= " ' /goods/toDetail/'+${goods.id}" >  查看详情</ a> </ td> </ tr> </ table>  
</ div>  
< script> 
 </ script>  
  
 2.测试使用  
 1.报错,GoodsService没被注入  
 
 2.加一下Service注解即可  
 
 3.登录成功  
 
 4.访问 http://localhost:9092/seckill/goods/toList 没有图片  
 
 5.把图片放到imgs下即可  
 
 6.重新访问  
 
 3.调整templates/login.html 登录成功后直接跳转到商品列表页  
 1.新增超链接  
 
 2.登录成功后自动跳转  
 
 7.商品详情页  
 1.Mapper编写 根据商品id获取商品详情  
 1.GoodsMapper.java  
    GoodsVo  findGoodsVoByGoodsId ( Long  goodsId) ; 
  
 2.GoodsMapper.xml  
    < select  id = " findGoodsVoByGoodsId"   resultType = " com.sxs.seckill.vo.GoodsVo" >  select g.id,g.goods_name,g.goods_title,g.goods_img,g.goods_detail,g.goods_price,g.goods_stock,t_seckill_goods.seckill_price,t_seckill_goods.stock_count,t_seckill_goods.start_date,t_seckill_goods.end_datefrom t_goods gleft join t_seckill_goods on g.id = t_seckill_goods.goods_idwhere g.id = #{goodsId};</ select>  
  
 2.Service编写  
 1.GoodsService.java  
    GoodsVo  findGoodsVoByGoodsId ( Long  goodsId) ; 
  
 2.GoodsServiceImpl.java  
    @Override public  GoodsVo  findGoodsVoByGoodsId ( Long  goodsId)  { return  goodsMapper. findGoodsVoByGoodsId ( goodsId) ; } 
  
 3.Controller编写  
 GoodsController.java  
    @RequestMapping ( "/toDetail/{goodsId}" ) public  String  toDetail ( Model  model,  User  user,  @PathVariable  Long  goodsId)  { if  ( null  ==  user)  { return  "login" ; } model. addAttribute ( "goods" ,  goodsService. findGoodsVoByGoodsId ( goodsId) ) ; model. addAttribute ( "user" ,  user) ; return  "goodsDetail" ; } 
  
 4.前端界面编写  
 1.goodsList.html 修改请求(使用环境变量+资源路径的形式)  
 
 2.goodsDetail.html 商品详情页  
<! DOCTYPE  html >  
< html  lang = " en"   xmlns: th= " http://www.thymeleaf.org" >  
< head> < meta  charset = " UTF-8" > < title>  商品详情</ title> < script  type = " text/javascript"   th: src= " @{/js/jquery.min.js}" > </ script> < link  rel = " stylesheet"   type = " text/css"   th: href= " @{/bootstrap/css/bootstrap.min.css}" /> < script  type = " text/javascript"   th: src= " @{/bootstrap/js/bootstrap.js}" > </ script> < script  type = " text/javascript"   th: src= " @{/layer/layer.js}" > </ script> < script  type = " text/javascript"   th: src= " @{/js/common.js}" > </ script> < style> *  { margin :  0; padding :  0; font-family :  "Open Sans" ,  sans-serif; text-transform :  uppercase; letter-spacing :  3px; font-size :  11px; } body  { background :  #c9302c; } .main-header  { width :  100%; height :  100px; background :  whitesmoke; display :  block; } .navbar  { display :  inline-block; float :  right; margin-right :  50px; margin-top :  30px; } .logo  { display :  inline-block; margin-top :  30px; margin-left :  30px; text-decoration :  none; } .logo-lg  { font-size :  20px; font-weight :  lighter; color :  #232324; } .logo-lg > b  { font-size :  20px; font-weight :  lighter; color :  #232324; } .container  { background :  #FFFFFF; margin-right :  auto; margin-left :  auto; width :  900px; } .captcha  { display :  none; } .captchaImg  { display :  none; width :  130px; height :  32px; } </ style>  
</ head>  
< body>  
< header  id = " site-header"   class = " main-header" > < a  class = " logo"   onclick = " toList ( ) " > < span  class = " logo-lg" > < b>  商品抢购</ b> </ span> </ a> < nav  class = " navbar navbar-static-top" > < a  href = " #"   class = " sidebar-toggle"   data-toggle = " push-menu"   role = " button" > < span  class = " sr-only" >  Toggle navigation</ span> < span  class = " icon-bar" > </ span> < span  class = " icon-bar" > </ span> < span  class = " icon-bar" > </ span> </ a> < div  class = " navbar-custom-menu" > < ul  class = " nav navbar-nav" > < li  class = " dropdown user user-menu" > < a  href = " #"   class = " dropdown-toggle"   data-toggle = " dropdown" > < img  class = " user-image"   src = " /imgs/user.png"   height = " 32"   alt = " User
Image" > < span  class = " hidden-xs" > </ span> </ a> < ul  class = " dropdown-menu" > < li  class = " user-header" > < img  class = " img-circle"   alt = " User Image" > < p>  Hello ABC - Hello ABC< small>  Hello ABC</ small> </ p> </ li> < li  class = " user-body" > </ li> < li  class = " user-footer" > < div  class = " pull-middle" > < a  onclick = " toOut ( ) "   class = " btn btn-lg btn-default btn-block" >  退出系统</ a> </ div> </ li> </ ul> </ li> </ ul> </ div> </ nav>  
</ header>  
< div  class = " panel panel-default" > < div  class = " panel-heading"   style = " background :  #c9302c; color :  white" >  秒杀商品详情</ div> < div  class = " panel-body" > < span  th: if= " ${user eq null}" >   您还没有登录,请登陆后再操作< br/> </ span> < span>  production 参数</ span> </ div> < div  class = " container" > < table  class = " table"   id = " good" > < tr> < td>  名称</ td> < td  colspan = " 3"   id = " goodName"   th: text= " ${goods.goodsName}" > </ td> </ tr> < tr> < td>  图片</ td> < td  colspan = " 3" > < img  id = " goodImg"   th: src= " @{${goods.goodsImg}}"   width = " 200"   heights = " 200" /> </ td> </ tr> < tr> < td>  秒杀价</ td> < td  id = " secKillPrice"   th: text= " ${goods.seckillPrice}" > </ td> < td> < img  id = " captchaImg"   class = " captchaImg" /> </ td> < td> < input  id = " captcha"   class = " captchaImg" /> < input  type = " button"   id = " captchabtn"   onclick = " verifyCaptcha ( ) "   value = " 验证
输入的验证码是否正确" > </ td> </ tr> < tr> < td>  原价</ td> < td  colspan = " 3"   id = " goodPrice"   th: text= " ${goods.goodsPrice}" > </ td> </ tr> < tr> < td>  库存</ td> < td  colspan = " 3"   id = " stockCount"   th: text= " ${goods.stockCount}" > </ td> </ tr> </ table> </ div>  
</ div>  
</ body>  
< script> 
 </ script>  
</ html>  
  
 5.测试  
 1.点击查看详情  
 
 2.数据正常展示