京东秒杀之商品展示

news2024/11/25 22:28:59

1 在gitee上添加.yml文件

1.1 添加good-server.yml文件

server:
  port: 8084
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/shop_goods?serverTimezone=GMT%2B8
    driverClassName: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: 123456
mybatis:
  configuration:
    default-fetch-size: 100
    default-statement-timeout: 3000
    map-underscore-to-camel-case: true

1.2 添加seckill-server.yml文件

在这里插入图片描述

server:
  port: 8085
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/shop_seckill?serverTimezone=GMT%2B8
    driverClassName: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    username: root
    password: 123456
mybatis:
  configuration:
    default-fetch-size: 100
    default-statement-timeout: 3000
    map-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}, //启用cookie
            success: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 {
    @Override
    public 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 {

    @Autowired
    private GoodMapper goodMapper;

    @Override
    public 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 {

    @Autowired
    private GoodService goodService;
    @Override
    public 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 {

    @Autowired
    private SeckillGoodMapper seckillGoodMapper;

    @Autowired
    private GoodFeignApi goodFeignApi;

    @Override
    public List<SeckillGoodVo> query() {
        //1. 单表查询 数据 t_seckill_good 数据 秒杀的商品 列表  SeckillGoodList
        List<SeckillGood> seckillGoodList = seckillGoodMapper.query();
        //2. 获取 good_id 集合 ids[1,2]

        //3  远程调用 good-server   传递参数 [1,2] 在商品表中查询   t_goods 数据 GoodList
        List<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) {
            //去除重复的goodid
            idSet.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());//场次id
            vo.setStartDate(seckillGood.getStartDate());//秒杀开始时间
            vo.setStockCount(seckillGood.getStockCount());//秒杀商品的数量
            vo.setSeckillPrice(seckillGood.getSeckillPrice());//秒杀价格
            //添加到集合中
            seckillGoodVoList.add(vo);

        }
        return seckillGoodVoList;
    }
}

4 创建controller层

@RestController
@RequestMapping("/seckillGood")
public class SeckillGoodController {

    @Autowired
    private SeckillGoodService seckillGoodService;

    @RequestMapping("/query")
    public Result query(){

        List<SeckillGoodVo> seckillGoodVoList = seckillGoodService.query();
        return Result.success(seckillGoodVoList);
    }
}

4.4 登录测试

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【JMeter】使用BeanShell写入内容到文件

一、前言 在我们日常工作中&#xff0c;可能会遇到需要将请求返回的数据写入到文件中。在我们使用JMeter进行性能测试时&#xff0c;就经常能够遇到这种情况。要想达到这种目的&#xff0c;我们一般采取BeanShell后置处理器来将内容写入到文件。 二、提取 在目前大多数的性能…

华为云CDN刷新与查询余量的Go实现及在Jenkins中的部署

引言 在华为云上&#xff0c;对CDN缓存内容进行刷新是一个常见的需求&#xff0c;以确保最新的内容能尽快被用户访问到。通过使用Go语言&#xff0c;我们可以开发一个自动化的工具来实现这一需求&#xff0c;并将其集成到Jenkins中以实现持续部署。下面我们将分步骤讲解如何实…

力扣hot100 和为 K 的子数组 前缀和

&#x1f468;‍&#x1f3eb; 题目地址 &#x1f37b; AC code class Solution {public int subarraySum(int[] nums, int k){int ans 0;int n nums.length;int[] s new int[n 1];// 前缀和s[0] 0;s[1] nums[0];for (int i 2; i < n; i)s[i] s[i - 1] nums[i - 1…

Termius 一款优秀的跨平台 SSH 客户端工具

&#x1f525;&#x1f525;&#x1f525; 作为程序员或者运维管理人员&#xff0c;我们经常需要使用终端工具来进行服务器管理及各种操作&#xff0c;比如部署项目、调试代码、查看/优化服务、管理服务器等。 而实现远程服务器连接需要借助 SSH 协议来进行&#xff0c;SSH&am…

Ubuntu知识积累

修改当前Ubuntu环境下时间 sudo date --set "2023-11-21 10:01:00"查看进程 过滤bs开头的进程 ps -aux|grep Bs查看ubuntu系统的磁盘大小 要查看Ubuntu系统的磁盘大小&#xff0c;可以使用df命令。df命令用于报告文件系统的磁盘空间使用情况&#xff0c;包括每个…

ESP32-Web-Server编程- JS 基础 4

ESP32-Web-Server编程- JS 基础 4 概述 HTML 内联事件处理器&#xff0c;你永远不应该使用 HTML 事件处理器属性——因为那些已经过时了&#xff0c;使用它们是不好的做法。 在前端编程中&#xff0c;除了将期望发生的事件写为 JS 文件外&#xff0c;还可以使用一些组件自带…

springboot+vue智能企业设备管理系统05k50

智能设备管理系统主要是为了提高工作人员的工作效率和更方便快捷的满足用户&#xff0c;更好存储所有数据信息及快速方便的检索功能&#xff0c;对系统的各个模块是通过许多今天的发达系统做出合理的分析来确定考虑用户的可操作性&#xff0c;遵循开发的系统优化的原则&#xf…

电子学会C/C++编程等级考试2021年12月(三级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:我家的门牌号 我家住在一条短胡同里,这条胡同的门牌号从1开始顺序编号。 若所有的门牌号之和减去我家门牌号的两倍,恰好等于n,求我家的门牌号及总共有多少家。 数据保证有唯一解。 时间限制:1000 内存限制:65536输入 一个…

艾森股份将上市在即:募资约6亿元,张兵、蔡卡敦夫妇为实控人

11月27日&#xff0c;江苏艾森半导体材料股份有限公司&#xff08;下称“艾森股份”&#xff0c;SH:688720&#xff09;开启申购&#xff0c;将在科创板上市。本次上市&#xff0c;艾森股份的发行价为28.03元/股&#xff0c;发行数量约2203万股&#xff0c;预计募资总额约6.18亿…

C++ :const修饰成员函数

常函数&#xff1a; 常函数&#xff1a; 成员函数后加const后我们称为这个函数为常函数 常函数内不可以修改成员属性 成员属性声明时加关键字mutable后&#xff0c;在常函数中依然可以修改 属性可修改&#xff1a; class Person { public: void showPerson() …

UI自动化测试工具有哪些优势?

UI自动化测试工具通过提高测试效率、覆盖率&#xff0c;减少测试时间和成本&#xff0c;以及支持持续集成等方式&#xff0c;为软件开发团队提供了一系列重要的优势&#xff0c;有助于提升软件质量和开发效率。 自动化执行&#xff1a;UI自动化测试工具可以模拟用户与应用程序的…

访问对象的方式

创建对象自然是为了后续使用该对象&#xff0c;我们的Java程序会通过栈上的reference数据来操作堆上的具体对象。由于reference类型在《Java虚拟机规范》里面只规定了它是一个指向对象的引用&#xff0c;并没有定义这个引用应该通过什么方式去定位、访问到堆中对象的具体位置&a…

C++:OJ练习(每日练习系列)

编程题&#xff1a; 题一&#xff1a;把字符串转换成整数 把字符串转换成整数_牛客题霸_牛客网 示例1 输入&#xff1a; "2147483647" 返回值&#xff1a; 2147483647思路一&#xff1a; 第一步&#xff1a;it从str的第一个字符开始遍历&#xff0c;定义一个最后输…

记录一次如何查询mysql分库分表数据

一、前言 本次查询是在未知如何分库分表的情况下&#xff0c;对表数据进行查询&#xff0c;其中有的字段为JSON结构。需要提取JSON中某个字段的内容。 二、查询步骤 1、第一方式是将所有分表数据进行union all select * from apporder.ord_shopping_order union all sel…

线性分类器--图像表示

整个模型 图像表示 二进制图像 灰度图像 彩色图像 大多数分类算法都要求输入向量&#xff01; rbg的图像矩阵转列向量 大小为 32X32 的话&#xff0c;图像矩阵转列向量是多少维&#xff1f; 32x32x3 3072 维列向量

2024 年应该使用 Bun、Node.js 还是 Deno

2024 年应该使用 Bun、Node.js 还是 Deno 到 2024 年&#xff0c;构建基于 JavaScript 的现代 API 相对简单。我们可以使用Express.js等库并在几分钟内启动可用的 API。但是&#xff0c;现在最具挑战性的部分是选择正确的 JavaScript 引擎。 目前主流的三个运行时是&#xff…

MidJourney笔记(4)-settings

前面已经大概介绍了MidJourney的基础知识,后面我主要是基于实操来分享自己的笔记。可能内容顺序会有点乱,请大家理解。 这次主要是想讲讲settings这个命令。我们只需在控制台输入/settings,然后回车,就可以执行这个命令。 (2023年11月26日版本界面) 可能有些朋友出来的界…

前端OFD文件预览(vue案例cafe-ofd)

0、提示 下面只有vue的使用示例demo &#xff0c;官文档参考 cafe-ofd - npm 其他平台可以参考 ofd - npm 官方线上demo: ofd 1、安装包 npm install cafe-ofd --save 2、引入 import cafeOfd from cafe-ofd import cafe-ofd/package/index.css Vue.use(cafeOfd) 3、使…

unity UGUI中获取点击位置处的URL链接

需求是&#xff0c;我们在一个text组件中像写网页那样写入链接&#xff0c;然后点击这个链接&#xff0c;就能访问配置的网页啥的。比如&#xff1a; <a href"hello">链接文本</a></summary> 最终的效果如下&#xff1a; 图中&#xff0c;image区…

血的教训------入侵redis之利用python来破解redis密码

血的教训------入侵redis之利用python来破解redis密码 利用强大的python来进行redis的密码破解&#xff0c;过程不亦乐乎&#xff0c;当然也可以用shell脚本 本篇文章只供学习交流&#xff0c;请勿他用&#xff0c;谢谢。 其他相关联的文章 [1]VMware安装部署kail镜像服务器【…