文章目录  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.测试     
 
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; 
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; 
 
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; 
} 
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; 
} 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; 
} 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 ( ) ; 
} 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"  > < mappernamespace = " com.sxs.seckill.mapper.GoodsMapper" > < selectid = " findGoodsVo" resultType = " com.sxs.seckill.vo.GoodsVo" > </ select> </ mapper> 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 ( ) ; 
} 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 ( ) ; } 
} 
 
< htmllang = " en" xmlns: th= " http://www.thymeleaf.org" > < head> < metacharset = " UTF-8" > < title> </ title> < linkrel = " stylesheet" type = " text/css" th: href= " @{/bootstrap/css/bootstrap.min.css}" /> < scripttype = " text/javascript" th: src= " @{/js/jquery.min.js}" > </ script> < scripttype = " text/javascript" th: src= " @{/jquery-validation/jquery.validate.min.js}" > </ script> < scripttype = " text/javascript" th: src= " @{/jquery-validation/localization/messages_zh.min.js}" > </ script> < scripttype = " text/javascript" th: src= " @{/layer/layer.js}" > </ script> < scripttype = " text/javascript" th: src= " @{/js/md5.min.js}" > </ script> < scripttype = " 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> < headerid = " site-header" class = " main-header" > < aclass = " logo" th: href= " @{/goods/toList}" > < spanclass = " logo-lg" > < b> </ b> </ span> </ a> < navclass = " navbar navbar-static-top" > < ahref = " #" class = " sidebar-toggle" data-toggle = " push-menu" role = " button" > < spanclass = " sr-only" > </ span> < spanclass = " icon-bar" > </ span> < spanclass = " icon-bar" > </ span> < spanclass = " icon-bar" > </ span> </ a> < divclass = " navbar-custom-menu" > < ulclass = " nav navbar-nav" > < liclass = " dropdown user user-menu" > < ahref = " #" class = " dropdown-toggle" data-toggle = " dropdown" > < imgclass = " user-image" src = " /imgs/user.png" height = " 42" alt = " User
Image" > < spanclass = " hidden-xs" > </ span> </ a> < ulclass = " dropdown-menu" > < liclass = " user-header" > < imgclass = " img-circle" alt = " User Image" > < p> < small> </ small> </ p> </ li> < liclass = " user-body" > </ li> < liclass = " user-footer" > < divclass = " pull-middle" > < ath: href= " @{/login/out}" class = " btn btn-lg btn-default
btn-block" > </ a> </ div> </ li> </ ul> </ li> </ ul> </ div> </ nav> </ header> < divclass = " container" > < divclass = " panel-heading" > </ div> < tableclass = " table" id = " goodslist" > < tr> < td> </ td> < td> </ td> < td> </ td> < td> </ td> < td> </ td> < td> </ td> </ tr> < trth: each= " goods,goodstStat : ${goodsList}" > < tdth: text= " ${goods.goodsName}" > </ td> < td> < imgth: src= " @{${goods.goodsImg}}" width = " 100" height = " 100" /> </ td> < tdth: text= " ${goods.goodsPrice}" > </ td> < tdth: text= " ${goods.seckillPrice}" > </ td> < tdth: text= " ${goods.stockCount}" > </ td> < td> < ath: href= " ' /goods/toDetail/'+${goods.id}" > </ a> </ td> </ tr> </ table> </ div> < script> 
 </ script> 
 
 
 
 
 
 
 
 
    GoodsVo  findGoodsVoByGoodsId ( Long  goodsId) ; 
    < selectid = " findGoodsVoByGoodsId" resultType = " com.sxs.seckill.vo.GoodsVo" > </ select>     GoodsVo  findGoodsVoByGoodsId ( Long  goodsId) ; 
    @Override public  GoodsVo  findGoodsVoByGoodsId ( Long  goodsId)  { return  goodsMapper. findGoodsVoByGoodsId ( goodsId) ; } 
    @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" ; } 
 
<! DOCTYPE  html > < htmllang = " en" xmlns: th= " http://www.thymeleaf.org" > < head> < metacharset = " UTF-8" > < title> </ title> < scripttype = " text/javascript" th: src= " @{/js/jquery.min.js}" > </ script> < linkrel = " stylesheet" type = " text/css" th: href= " @{/bootstrap/css/bootstrap.min.css}" /> < scripttype = " text/javascript" th: src= " @{/bootstrap/js/bootstrap.js}" > </ script> < scripttype = " text/javascript" th: src= " @{/layer/layer.js}" > </ script> < scripttype = " 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> < headerid = " site-header" class = " main-header" > < aclass = " logo" onclick = " toList ( ) " > < spanclass = " logo-lg" > < b> </ b> </ span> </ a> < navclass = " navbar navbar-static-top" > < ahref = " #" class = " sidebar-toggle" data-toggle = " push-menu" role = " button" > < spanclass = " sr-only" > </ span> < spanclass = " icon-bar" > </ span> < spanclass = " icon-bar" > </ span> < spanclass = " icon-bar" > </ span> </ a> < divclass = " navbar-custom-menu" > < ulclass = " nav navbar-nav" > < liclass = " dropdown user user-menu" > < ahref = " #" class = " dropdown-toggle" data-toggle = " dropdown" > < imgclass = " user-image" src = " /imgs/user.png" height = " 32" alt = " User
Image" > < spanclass = " hidden-xs" > </ span> </ a> < ulclass = " dropdown-menu" > < liclass = " user-header" > < imgclass = " img-circle" alt = " User Image" > < p> < small> </ small> </ p> </ li> < liclass = " user-body" > </ li> < liclass = " user-footer" > < divclass = " pull-middle" > < aonclick = " toOut ( ) " class = " btn btn-lg btn-default btn-block" > </ a> </ div> </ li> </ ul> </ li> </ ul> </ div> </ nav> </ header> < divclass = " panel panel-default" > < divclass = " panel-heading" style = " background :  #c9302c; color :  white" > </ div> < divclass = " panel-body" > < spanth: if= " ${user eq null}" > < br/> </ span> < span> </ span> </ div> < divclass = " container" > < tableclass = " table" id = " good" > < tr> < td> </ td> < tdcolspan = " 3" id = " goodName" th: text= " ${goods.goodsName}" > </ td> </ tr> < tr> < td> </ td> < tdcolspan = " 3" > < imgid = " goodImg" th: src= " @{${goods.goodsImg}}" width = " 200" heights = " 200" /> </ td> </ tr> < tr> < td> </ td> < tdid = " secKillPrice" th: text= " ${goods.seckillPrice}" > </ td> < td> < imgid = " captchaImg" class = " captchaImg" /> </ td> < td> < inputid = " captcha" class = " captchaImg" /> < inputtype = " button" id = " captchabtn" onclick = " verifyCaptcha ( ) " value = " 验证
输入的验证码是否正确" > </ td> </ tr> < tr> < td> </ td> < tdcolspan = " 3" id = " goodPrice" th: text= " ${goods.goodsPrice}" > </ td> </ tr> < tr> < td> </ td> < tdcolspan = " 3" id = " stockCount" th: text= " ${goods.stockCount}" > </ td> </ tr> </ table> </ div> </ div> </ body> < script> 
 </ script> </ html>