京东秒杀之商品展示

1 在gitee上添加.yml文件

1.1 添加good-server.yml文件

server:port: 8084
spring:datasource:url: jdbc:mysql://localhost:3306/shop_goods?serverTimezone=GMT%2B8driverClassName: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceusername: rootpassword: 123456
mybatis:configuration:default-fetch-size: 100default-statement-timeout: 3000map-underscore-to-camel-case: true

1.2 添加seckill-server.yml文件

在这里插入图片描述

server:port: 8085
spring:datasource:url: jdbc:mysql://localhost:3306/shop_seckill?serverTimezone=GMT%2B8driverClassName: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceusername: rootpassword: 123456
mybatis:configuration:default-fetch-size: 100default-statement-timeout: 3000map-underscore-to-camel-case: true

2 创建启动类

2.1 创建商品服务启动类

@SpringBootApplication
@EnableEurekaClient
public class GoodServerApp {public static void main(String[] args) {SpringApplication.run(GoodServerApp.class, args);}
}

2.2 创建秒杀启动类

在这里插入图片描述

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
public class SeckillServerApp {public static void main(String[] args) {SpringApplication.run(SeckillServerApp.class, args);}
}

3 编写前端商品页面

<!DOCTYPE html>
<html lang="en">
<head><title>商品列表</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><script type="text/javascript" src="/js/jquery.min.js"></script><link rel="stylesheet" type="text/css" href="/bootstrap/css/bootstrap.min.css" /><!-- bootstrap --><script type="text/javascript" src="/bootstrap/js/bootstrap.min.js"></script><script type="text/javascript" src="/jquery-validation/jquery.validate.min.js"></script> <!-- jquery-validator --><script type="text/javascript" src="/jquery-validation/localization/messages_zh.min.js"></script><script type="text/javascript" src="/layer/layer.js"></script><!-- layer --><script type="text/javascript" src="/js/md5.min.js"></script><!-- md5.js --><script type="text/javascript" src="/js/common.js"></script><!-- common.js -->
</head>
<body>
<div class="panel panel-default"><div class="panel-heading">秒杀商品列表</div><table class="table" id="goodlist"><tr><td>商品名称</td><td>商品图片</td><td>商品原价</td><td>秒杀价</td><td>库存数量</td><td>详情</td></tr></table>
</div><script type="text/javascript">String.prototype.format=function () {if(arguments.length==0){return this;}var obj=arguments[0];var s = this;for(var key in obj){s= s.replace(new RegExp("\\{\\{"+key+"\\}\\}","g"),obj[key]);}return s;};var template="<tr><td>{{goodName}}</td>" +"<td><img src='{{goodImg}}' width='100px' height='100px' /> </td>" +"<td>{{goodPrice}}</td>" +"<td>{{seckillPrice}}</td>" +"<td>{{stockCount}}</td>" +"<td> <a href='good_detail.html?seckillId={{id}}'>详情</a> </td></tr>";$(function () {$.ajax({url: "http://localhost:9000/seckill/seckillGood/query",type: "get",xhrFields: {withCredentials: true}, //启用cookiesuccess:function (data) {if(data.code==200){//填充表格中的数据render(data.data);}else{layer.msg(data.msg)}}});});function render(goodlist) {for(var i=0;i<goodlist.length;i++){$("#goodlist").append(template.format(goodlist[i]));}}</script>
</body>
</html>

4 商品查询

由于在前端页面展示的信息来自不同的两张表,因此需要运用远程调用:

    1. 在单表查询 数据 t_seckill_good 数据 秒杀的商品 列表 SeckillGoodList
    1. 获取 good_id 集合 ids[1,2]
    1. 远程调用 good-server 传递参数 [1,2] 在商品表中查询 t_goods 数据 GoodList

4.1 创建实体类

1 创建商品类

@Data
public class Good implements Serializable {private Long id;private String goodName;private String  goodTitle;private String  goodImg;private String goodDetail;private BigDecimal goodPrice;private Integer  goodStock;
}

2 创建秒杀类

@Data
public class SeckillGoods implements Serializable {private Long id;private Long goodId;private BigDecimal seckillPrice;private Integer stockCount;//时间的问题后续得处理 ----@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date startDate;@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")private Date endDate;
}

3 创建前端封装类(对应前端页面需要展示的数据)

@Data
public class SeckillGoodVo extends SeckillGood implements Serializable{private String goodName;private String  goodTitle;private String  goodImg;private String goodDetail;private BigDecimal goodPrice;
}

4.2 实现远程调用(通过远程调用传递的ids来查找商品信息)

1 创建断路器

public class GoodFeignHystrix implements GoodFeignApi {@Overridepublic Result<List<Good>> queryByIds(List<Long> ids) {return null;}
}

2 创建远程调用接口

@FeignClient(name = "good-server", fallbackFactory = GoodFeignHystrix.class)
public interface GoodFeignApi {@RequestMapping("/queryByIds")public Result<List<Good>> queryByIds(@RequestParam("ids") List<Long> ids);}

3 创建Mapper接口

@Mapper
public interface GoodMapper {/*** 根据id查询商品信息* @param ids* @return*/@SelectProvider(type = GoodMapperSQLProvider.class, method = "queryByIds")public List<Good> queryByIds(@Param("ids") List<Long> ids);/*** 由于没有mapper的配置文件,不能使用foreach标签,因此在这里实现SQL的循环*/class GoodMapperSQLProvider{/*** select * from t_goods where id in (x, x, x,....),将ids循环遍历到()内* @param ids* @return*/public String queryByIds(@Param("ids") List<Long> ids){StringBuilder sb = new StringBuilder();sb.append("select * from t_goods ");if (ids != null || ids.size() > 0){sb.append(" where id in (");for (int i = 0; i < ids.size(); i++) {if (i != 0){sb.append(",");}sb.append(ids.get(i));}sb.append(")");}return sb.toString();}}
}

4 创建service业务逻辑接口及其实现类


service业务逻辑接口

public interface GoodService {/*** 根据id查询商品信息* @param ids* @return*/public List<Good> queryByIds(List<Long> ids);
}

实现类

@Service
public class GoodServiceImpl implements GoodService {@Autowiredprivate GoodMapper goodMapper;@Overridepublic List<Good> queryByIds(List<Long> ids) {if (ids == null || ids.size() == 0){return Collections.emptyList();}return goodMapper.queryByIds(ids);}
}

5 创建controller层

@RestController
public class GoodFeignClient implements GoodFeignApi {@Autowiredprivate GoodService goodService;@Overridepublic Result<List<Good>> queryByIds(List<Long> ids) {List<Good> goodlist = goodService.queryByIds(ids);return Result.success(goodlist);}
}

4.3 数据聚合(把商品信息和秒杀信息聚合为前端页面所需的类)

1 创建秒杀的CodeMsg

public class SeckillCodeMsg extends CodeMsg {public SeckillCodeMsg() {}public SeckillCodeMsg(Integer code, String msg) {super(code, msg);}public static  final SeckillCodeMsg PRODUCT_SERVER_ERROR= new SeckillCodeMsg(500010,"商品微服务繁忙");public static  final SeckillCodeMsg LOGIN_TIMEOUT= new SeckillCodeMsg(500011,"登录信息过期了");public static  final SeckillCodeMsg OP_ERROR= new SeckillCodeMsg(500012,"非法操作");}

2 创建Mapper接口

@Mapper
public interface SeckillGoodMapper {@Select("SELECT * FROM t_seckill_goods")public List<SeckillGood> query();
}

3 创建service业务逻辑接口及其实现类


service业务逻辑接口

public interface SeckillGoodService {/*** 查询商品数据* @return*/public List<SeckillGoodVo> query();
}

实现类

@Service
public class SeckillGoodServiceImpl implements SeckillGoodService {@Autowiredprivate SeckillGoodMapper seckillGoodMapper;@Autowiredprivate GoodFeignApi goodFeignApi;@Overridepublic List<SeckillGoodVo> query() {//1. 单表查询 数据 t_seckill_good 数据 秒杀的商品 列表  SeckillGoodListList<SeckillGood> seckillGoodList = seckillGoodMapper.query();//2. 获取 good_id 集合 ids[1,2]//3  远程调用 good-server   传递参数 [1,2] 在商品表中查询   t_goods 数据 GoodListList<SeckillGoodVo> seckillGoodVoList = getSeckillGoodVos(seckillGoodList);return seckillGoodVoList;}/*** 获取秒杀商品列表** @param seckillGoodList* @return*/private List<SeckillGoodVo> getSeckillGoodVos(List<SeckillGood> seckillGoodList) {//利用set集合来进行数据去重Set<Long> idSet = new HashSet<>();for (SeckillGood seckillGood : seckillGoodList) {//去除重复的goodididSet.add(seckillGood.getGoodId());}List<Long> ids = new ArrayList<>(idSet);//远程调用获取商品信息Result<List<Good>> result = goodFeignApi.queryByIds(ids);//远程调用失败if (result == null || result.hasError()) {throw new BusinessException(SeckillCodeMsg.PRODUCT_SERVER_ERROR);}//远程调用成功List<Good> goodList = result.getData();//获取商品信息存到Map中Map<Long, Good> goodMap = new HashMap<>();for (Good good : goodList) {goodMap.put(good.getId(), good);}//将商品信息和秒杀信息聚合List<SeckillGoodVo> seckillGoodVoList = new ArrayList<>();for (SeckillGood seckillGood : seckillGoodList) {//获取商品Good good = goodMap.get(seckillGood.getGoodId());//聚合SeckillGoodVo vo = new SeckillGoodVo();vo.setGoodDetail(good.getGoodDetail());vo.setGoodImg(good.getGoodImg());vo.setGoodName(good.getGoodName());vo.setGoodPrice(good.getGoodPrice());vo.setGoodTitle(good.getGoodTitle());//秒杀的结束时间vo.setEndDate(seckillGood.getEndDate());vo.setGoodId(good.getId());vo.setId(seckillGood.getId());//场次idvo.setStartDate(seckillGood.getStartDate());//秒杀开始时间vo.setStockCount(seckillGood.getStockCount());//秒杀商品的数量vo.setSeckillPrice(seckillGood.getSeckillPrice());//秒杀价格//添加到集合中seckillGoodVoList.add(vo);}return seckillGoodVoList;}
}

4 创建controller层

@RestController
@RequestMapping("/seckillGood")
public class SeckillGoodController {@Autowiredprivate SeckillGoodService seckillGoodService;@RequestMapping("/query")public Result query(){List<SeckillGoodVo> seckillGoodVoList = seckillGoodService.query();return Result.success(seckillGoodVoList);}
}

4.4 登录测试

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C语言:输入一行字符,分别统计出其中英文字母、空格、数字和其他字符的个数

分析&#xff1a; 在主函数 main 中&#xff0c;程序首先定义一个字符变量 c&#xff0c;以及四个整型变量 letters、k、s 和 o&#xff0c;并初始化它们的值为 0。然后使用 printf 函数输出提示信息&#xff0c;让用户输入一行字符。 接下来&#xff0c;程序通过 while 循环结…

线性分类器---损失函数与优化算法

如何衡量分类器对当前样本的效果好坏&#xff1f; 需要损失函数 什么是损失函数&#xff1f; 损失函数搭建了模型性能与模型参数之间的桥梁&#xff0c;指导 模型参数优化。  损失函数是一个函数&#xff0c;用于度量给定分类器的预测值与真实值 的不一致程度&#xff0c;…

线性分类器--分类模型

记录学习 北京邮电大学计算机学院 鲁鹏 为什么从线性分类器开始&#xff1f;  形式简单、易于理解  通过层级结构&#xff08;神经网络&#xff09;或者高维映射&#xff08;支撑向量机&#xff09;可以 形成功能强大的非线性模型 什么是线性分类器&#xff1f; 线性分…

入侵redis之准备---VMware安装部署kail镜像服务器【详细包含云盘镜像】

入侵redis之准备—VMware安装部署kail镜像服务器【详细包含云盘镜像】 kail是一个很好玩的操作系统&#xff0c;不多说了哈 下载kail镜像 kail官网:https://www.kali.org/get-kali/#kali-platforms 百度云盘下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1PRjo…

什么是半监督学习

1 概述 1.1 定义 半监督学习&#xff08;Semi-Supervised Learning&#xff09;是机器学习中的一个重要分支&#xff0c;它介于监督学习和无监督学习之间。半监督学习利用少量标注数据和大量未标注数据共同训练模型&#xff0c;旨在充分挖掘未标注数据中潜在的信息和模式&…

还不懂缓存穿透?Redis缓存穿透深度剖析

&#x1f388;个人公众号:&#x1f388; :✨✨✨ 可为编程✨ &#x1f35f;&#x1f35f; &#x1f511;个人信条:&#x1f511; 知足知不足 有为有不为 为与不为皆为可为&#x1f335; &#x1f349;本篇简介:&#x1f349;本篇记录Redis缓存穿透深度剖析命令操作&#xff0c;…

【云备份】数据管理模块

文章目录 1. 数据管理模块要管理什么数据&#xff1f;2. 数据管理模块如何管理数据&#xff1f;3. 数据管理模块的具体实现BackupInfo 数据信息类NewBackupInfo —— 获取各项属性信息 DataManager 数据管理类构造函数析构函数insert —— 新增update —— 修改GetOneByURL——…

Portraiture2024最新Photoshop磨皮插件更新啦

Portraiture是一款由Imagenomic公司研发的Photoshop磨皮插件。该插件以其优秀的磨皮效果&#xff0c;成为了众多摄影师和化妆师使用的首选插件。Portraiture主要用于影楼、婚纱、时尚摄影等各个领域。其主要特点是能够轻松地模拟人眼的视觉感受&#xff0c;自然地修饰人像照片。…

netty(三) taskQueue自定义任务,http服务器快速入门,netty核心模块,Unpooled

如果执行某些业务比较复杂&#xff0c;比较耗时&#xff0c;可以使用异步来完成 当然可以有多个任务 上面的结果是&#xff0c;在第一个任务处理完&#xff0c;再等20秒执行&#xff0c;简单来说&#xff0c;就是第一个在10秒执行&#xff0c;第二个在第30秒的时候执行&#…

Linux:通过VMWare,定制化Linux系统

一、原理图 二、新增磁盘&#xff08;对应上图sdb盘&#xff09; 三、挂载磁盘 主要是四步&#xff1a;查看磁盘&#xff0c;分区磁盘&#xff0c;格式化磁盘&#xff0c;挂载磁盘 1、查看磁盘 2、分区磁盘 3、格式化磁盘 4、挂载磁盘 创建两个备用目录&#xff0c;用于磁盘…

Qt_一个由单例引发的崩溃

Qt_一个由单例引发的崩溃 文章目录 Qt_一个由单例引发的崩溃摘要关于 Q_GLOBAL_STATIC代码测试布局管理器源码分析Demo 验证关于布局管理器析构Qt 类声明周期探索更新代码获取父类分析Qt 单例宏源码 关键字&#xff1a; Qt、 Q_GLOBAL_STATIC、 单例、 UI、 崩溃 摘要 今…

网页设计--第5次课后作业

1、快速学习JavaScript的基本知识第11-14章 JavaScript入门 - 绿叶学习网 2、使用所学的知识完成以下练习。 1&#xff09;点击 “点亮”按钮 点亮灯泡&#xff0c;点击“熄灭”按钮 熄灭灯泡 2&#xff09;输入框鼠标聚焦后&#xff0c;展示小写&#xff1b;鼠标离焦后…