├── .gitignore ├── .idea ├── .gitignore ├── compiler.xml ├── dataSources.xml ├── encodings.xml ├── inspectionProfiles │ └── Project_Default.xml ├── jarRepositories.xml ├── misc.xml ├── uiDesigner.xml └── vcs.xml ├── README.md ├── file ├── db_miaosha.sql └── nacos_config_export_20220409034342.zip ├── miaosha-common ├── pom.xml └── src │ └── main │ └── java │ └── com │ └── ledao │ ├── config │ ├── RabbitMQConfig.java │ └── WebAppConfigurer.java │ ├── entity │ ├── Goods.java │ ├── MiaoShaGoods.java │ ├── Order.java │ ├── PR.java │ ├── User.java │ └── vo │ │ ├── OrderVo.java │ │ └── UserVo.java │ ├── exception │ └── GlobalExceptionHanlder.java │ ├── interceptor │ └── SysInterceptor.java │ └── util │ ├── Md5Util.java │ ├── RedisUtil.java │ ├── StringUtil.java │ └── UUIDUtil.java ├── miaosha-gateway ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ledao │ │ ├── MiaoShaGateWayApplication.java │ │ └── config │ │ └── KeyResolverConfig.java │ └── resources │ ├── application.yml │ └── bootstrap.properties ├── miaosha-goods ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ledao │ │ ├── MiaoShaGoodsApplication.java │ │ ├── controller │ │ └── MiaoShaGoodsController.java │ │ ├── mapper │ │ ├── GoodsMapper.java │ │ ├── MiaoShaGoodsMapper.java │ │ └── OrderMapper.java │ │ └── service │ │ ├── MiaoShaGoodsService.java │ │ ├── OrderService.java │ │ └── impl │ │ ├── MiaoShaGoodsServiceImpl.java │ │ └── OrderServiceImpl.java │ └── resources │ ├── application.yml │ ├── bootstrap.properties │ └── mybatis │ └── mapper │ ├── GoodsMapper.xml │ ├── MiaoShaGoodsMapper.xml │ └── OrderMapper.xml ├── miaosha-order1 ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ledao │ │ ├── MiaoShaOrderApplication1.java │ │ ├── controller │ │ └── OrderController.java │ │ ├── feign │ │ └── RabbitMQFeignService.java │ │ ├── mapper │ │ ├── GoodsMapper.java │ │ ├── MiaoShaGoodsMapper.java │ │ └── OrderMapper.java │ │ └── service │ │ ├── GoodsService.java │ │ ├── MiaoShaGoodsService.java │ │ ├── OrderService.java │ │ └── impl │ │ ├── GoodsServiceImpl.java │ │ ├── MiaoShaGoodsServiceImpl.java │ │ └── OrderServiceImpl.java │ └── resources │ ├── application.yml │ ├── bootstrap.properties │ └── mybatis │ └── mapper │ ├── GoodsMapper.xml │ ├── MiaoShaGoodsMapper.xml │ └── OrderMapper.xml ├── miaosha-order2 ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ledao │ │ ├── MiaoShaOrderApplication2.java │ │ ├── controller │ │ └── OrderController.java │ │ ├── feign │ │ └── RabbitMQFeignService.java │ │ ├── mapper │ │ ├── GoodsMapper.java │ │ ├── MiaoShaGoodsMapper.java │ │ └── OrderMapper.java │ │ └── service │ │ ├── GoodsService.java │ │ ├── MiaoShaGoodsService.java │ │ ├── OrderService.java │ │ └── impl │ │ ├── GoodsServiceImpl.java │ │ ├── MiaoShaGoodsServiceImpl.java │ │ └── OrderServiceImpl.java │ └── resources │ ├── application.yml │ ├── bootstrap.properties │ └── mybatis │ └── mapper │ ├── GoodsMapper.xml │ ├── MiaoShaGoodsMapper.xml │ └── OrderMapper.xml ├── miaosha-rabbitmq ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ledao │ │ ├── MiaoShaRabbitMQApplication.java │ │ ├── controller │ │ └── RabbitMQController.java │ │ ├── mapper │ │ ├── GoodsMapper.java │ │ ├── MiaoShaGoodsMapper.java │ │ └── OrderMapper.java │ │ ├── rabbitmq │ │ ├── RabbitMQConsumerService.java │ │ ├── RabbitMQProducerService.java │ │ └── impl │ │ │ ├── RabbitMQConsumerServiceImpl.java │ │ │ └── RabbitMQProducerServiceImpl.java │ │ └── service │ │ ├── GoodsService.java │ │ ├── MiaoShaGoodsService.java │ │ ├── OrderService.java │ │ └── impl │ │ ├── GoodsServiceImpl.java │ │ ├── MiaoShaGoodsServiceImpl.java │ │ └── OrderServiceImpl.java │ └── resources │ ├── application.yml │ ├── bootstrap.properties │ └── mybatis │ └── mapper │ ├── GoodsMapper.xml │ ├── MiaoShaGoodsMapper.xml │ └── OrderMapper.xml ├── miaosha-user ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── ledao │ │ ├── MiaoShaUserApplication.java │ │ ├── controller │ │ ├── TokenController.java │ │ └── UserContrller.java │ │ ├── mapper │ │ └── UserMapper.java │ │ └── service │ │ ├── UserService.java │ │ └── impl │ │ └── UserServiceImpl.java │ └── resources │ ├── application.yml │ └── bootstrap.properties └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/**/target/ 5 | !**/src/test/**/target/ 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | !**/src/main/**/build/ 30 | !**/src/test/**/build/ 31 | 32 | ### VS Code ### 33 | .vscode/ 34 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Editor-based HTTP Client requests 5 | /httpRequests/ 6 | # Datasource local storage ignored files 7 | /dataSources/ 8 | /dataSources.local.xml 9 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /.idea/dataSources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | mysql.8 6 | true 7 | com.mysql.cj.jdbc.Driver 8 | jdbc:mysql://localhost:3306/db_miaosha?serverTimezone=UTC 9 | $ProjectFileDir$ 10 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 43 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 15 | 16 | 17 | 18 | 19 | 20 | 22 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 需要Java毕设和课设服务的可以加我QQ:3519577180 2 | 3 | ### 有问题请到我的博客下留言,博客链接为:https://blog.zoutl.cn/492.html ,如果本项目对你有帮助,就请你Star一下吧!! 4 | 5 | ### 提问要求 6 | 查看博客:https://blog.zoutl.cn/6670.html ,一定要看,不规范的提问会让我不舒服,会导致我看到你的问题也不想回答 7 | 8 | ### 说明 9 | 10 | 本项目为前后端分离项目,后端代码有两个版本:一个是单体架构,另一个是微服务架构(对单体架构进行了微服务拆分) 11 | 12 | ### 项目地址 13 | 14 | #### GitHub地址 15 | 16 | > 后端代码 17 | 18 | **单体架构版本** 19 | 20 | [a6678696/MiaoSha: 高并发商品秒杀系统后端代码(前后端分离项目,单体架构版本) (github.com)](https://github.com/a6678696/MiaoSha) 21 | 22 | **微服务架构版本** 23 | 24 | [a6678696/miaosha-admin: 高并发商品秒杀系统后端代码(前后端分离项目,微服务架构版本) (github.com)](https://github.com/a6678696/miaosha-admin) 25 | 26 | > 前端代码 27 | 28 | [a6678696/miaosha-web: 高并发商品秒杀系统前端代码(前后端分离项目) (github.com)](https://github.com/a6678696/miaosha-web) 29 | 30 | ### 使用的技术 31 | 32 | #### 单体架构 33 | 34 | | 技术 | 说明 | 35 | | :----------: | :-------------------------: | 36 | | Spring Boot | 后端项目框架 | 37 | | Mybatis-Plus | 持久层框架 | 38 | | MySQL5.6 | 数据库 | 39 | | Redis | 缓存中间件 | 40 | | RabbitMQ | 消息队列(需要安装延迟队列的插件:[RabbitMQ 实现延时队列](https://blog.zoutl.cn/356.html) ) | 41 | | Vue.js | 前端JavaScript框架 | 42 | | Element | 基于 Vue 2.0 的桌面端组件库 | 43 | 44 | #### 微服务架构 45 | 46 | 在单体架构的基础上,多使用了以下技术: 47 | 48 | | 技术 | 说明 | 49 | | :------------------: | :------------: | 50 | | Spring Cloud | 微服务框架 | 51 | | Spring Cloud Alibaba | 阿里微服务框架 | 52 | | Nacos | 微服务注册中心 | 53 | | OpenFeign | Web服务客户端 | 54 | | Gateway | 微服务网关 | 55 | 56 | ### 功能介绍 57 | 58 | 1. 用户注册与登录 59 | 2. 查看正在秒杀的商品列表 60 | 3. 查看正在秒杀的商品详情 61 | 4. 秒杀商品,成功后下单 62 | 5. 30分钟未支付自动取消订单并释放商品和秒杀商品的库存 63 | 6. 模拟支付 64 | 65 | ### 秒杀流程图 66 | 67 | ![](https://image.zoutl.cn/hexo-blog/blogImage/2022-04-21%20205535.png) 68 | 69 | ### 图片展示 70 | 71 | #### 注册界面 72 | 73 | ![image-20220409230821932](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409230821932.png) 74 | 75 | #### 登录界面 76 | 77 | ![image-20220409230831836](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409230831836.png) 78 | 79 | #### 查看正在秒杀的商品 80 | 81 | ![image-20220409230857976](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409230857976.png) 82 | 83 | #### 秒杀页面 84 | 85 | ![image-20220409230919527](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409230919527.png) 86 | 87 | #### 我的订单 88 | 89 | ![image-20220409230953051](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409230953051.png) 90 | 91 | #### 模拟支付 92 | 93 | ![image-20220409231011260](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409231011260.png) 94 | 95 | #### 注销登录 96 | 97 | ![image-20220409231025055](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409231025055.png) 98 | 99 | ### 模拟海量用户秒杀 100 | 101 | #### 用户批量注册 102 | 103 | 下面方法批量注册1000个用户到数据库中,`如果是导入我的数据库文件可忽略此步` 104 | 105 | ![image-20220409231858593](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409231858593.png) 106 | 107 | #### 用户批量登录 108 | 109 | 执行这步前要先注册用户,如果是微服务架构就请求`http://localhost:8080/user/loginAuto` 这个接口即可实现批量登录,并把对应的userId和Token保存到TXT文件中 110 | 111 | ![image-20220409231653964](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409231653964.png) 112 | 113 | #### 测试 114 | 115 | 并发测试使用JMeter这个软件,安装与使用教程查看这几篇博客:[标签: JMeter | LeDao 的博客 (zoutl.cn)](https://blog.zoutl.cn/tags/JMeter/) 116 | 117 | 测试前先删除Redis中对应的秒杀商品的key,确认可秒杀商品的数量不为0 118 | 119 | 测试的接口为:`http://localhost:8080/order/save` ,参数如下图所示 120 | 121 | ![image-20220409232540517](https://image.zoutl.cn/hexo-blog/blogImage/image-20220409232540517.png) 122 | -------------------------------------------------------------------------------- /file/nacos_config_export_20220409034342.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/file/nacos_config_export_20220409034342.zip -------------------------------------------------------------------------------- /miaosha-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-common 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-web 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-openfeign 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-test 26 | test 27 | 28 | 29 | 30 | com.alibaba.cloud 31 | spring-cloud-starter-alibaba-nacos-discovery 32 | 33 | 34 | 35 | com.alibaba.cloud 36 | spring-cloud-starter-alibaba-nacos-config 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-devtools 41 | runtime 42 | true 43 | 44 | 45 | mysql 46 | mysql-connector-java 47 | runtime 48 | 49 | 50 | org.projectlombok 51 | lombok 52 | true 53 | 54 | 55 | com.baomidou 56 | mybatis-plus-boot-starter 57 | 58 | 59 | com.alibaba 60 | druid 61 | 62 | 63 | 64 | org.springframework.boot 65 | spring-boot-starter-amqp 66 | 67 | 68 | com.google.code.gson 69 | gson 70 | 71 | 72 | cn.hutool 73 | hutool-all 74 | 75 | 76 | commons-codec 77 | commons-codec 78 | 79 | 80 | org.springframework.boot 81 | spring-boot-starter-data-redis 82 | 83 | 84 | org.apache.commons 85 | commons-pool2 86 | 87 | 88 | junit 89 | junit 90 | test 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/config/RabbitMQConfig.java: -------------------------------------------------------------------------------- 1 | package com.ledao.config; 2 | 3 | import org.springframework.amqp.core.*; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import java.util.HashMap; 8 | import java.util.Map; 9 | 10 | /** 11 | * RabbitMQ配置类 12 | * 13 | * @author LeDao 14 | * @company 15 | * @create 2022-04-07 0:54 16 | */ 17 | @Configuration 18 | public class RabbitMQConfig { 19 | 20 | /** 21 | * direct交换机名称 22 | */ 23 | public static final String DIRECT_EXCHANGE = "directExchange"; 24 | 25 | /** 26 | * direct队列名称 27 | */ 28 | public static final String DIRECT_QUEUE = "directQueue"; 29 | 30 | /** 31 | * direct路由key 32 | */ 33 | public static final String DIRECT_ROUTINGKEY = "directRoutingKey"; 34 | 35 | /** 36 | * delayed交换机 37 | */ 38 | public static final String DELAYED_EXCHANGE = "delayedExchange"; 39 | 40 | /** 41 | * delayed队列 42 | */ 43 | public static final String DELAYED_QUEUE = "delayedQueue"; 44 | 45 | /** 46 | * delayed路由key 47 | */ 48 | public static final String DELAYED_ROUTING_KEY = "delayedRoutingKey"; 49 | 50 | /** 51 | * 定义一个direct交换机 52 | * 53 | * @return 54 | */ 55 | @Bean 56 | public DirectExchange directExchange() { 57 | return new DirectExchange(DIRECT_EXCHANGE); 58 | } 59 | 60 | /** 61 | * 定义一个direct队列 62 | * 63 | * @return 64 | */ 65 | @Bean 66 | public Queue directQueue() { 67 | return new Queue(DIRECT_QUEUE); 68 | } 69 | 70 | /** 71 | * 定义一个队列和交换机的绑定 72 | * 73 | * @return 74 | */ 75 | @Bean 76 | public Binding directBinding() { 77 | return BindingBuilder.bind(directQueue()).to(directExchange()).with(DIRECT_ROUTINGKEY); 78 | } 79 | 80 | /** 81 | * 定义delayed交换机 82 | * 83 | * @return 84 | */ 85 | @Bean 86 | public CustomExchange delayedExchange() { 87 | Map map = new HashMap<>(16); 88 | map.put("x-delayed-type", "direct"); 89 | return new CustomExchange(DELAYED_EXCHANGE, "x-delayed-message", true, false, map); 90 | } 91 | 92 | /** 93 | * 定义delayed队列 94 | * 95 | * @return 96 | */ 97 | @Bean 98 | public Queue delayedQueue() { 99 | return new Queue(DELAYED_QUEUE); 100 | } 101 | 102 | /** 103 | * delayed队列绑定delayed交换机 104 | * 105 | * @return 106 | */ 107 | @Bean 108 | public Binding delayedBinding() { 109 | return BindingBuilder.bind(delayedQueue()).to(delayedExchange()).with(DELAYED_ROUTING_KEY).noargs(); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/config/WebAppConfigurer.java: -------------------------------------------------------------------------------- 1 | package com.ledao.config; 2 | 3 | import com.ledao.interceptor.SysInterceptor; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import org.springframework.web.servlet.config.annotation.CorsRegistry; 7 | import org.springframework.web.servlet.config.annotation.InterceptorRegistry; 8 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * 实现跨域 15 | * 16 | * @author LeDao 17 | * @company 18 | * @create 2022-03-29 22:32 19 | */ 20 | @Configuration 21 | public class WebAppConfigurer implements WebMvcConfigurer { 22 | 23 | /*@Override 24 | public void addCorsMappings(CorsRegistry registry) { 25 | registry.addMapping("/**") 26 | .allowedOrigins("*") 27 | .allowCredentials(true) 28 | .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS") 29 | .maxAge(3600); 30 | }*/ 31 | 32 | @Bean 33 | public SysInterceptor sysInterceptor() { 34 | return new SysInterceptor(); 35 | } 36 | 37 | @Override 38 | public void addInterceptors(InterceptorRegistry registry) { 39 | //没有登录也不会被拦截的请求 40 | List patterns=new ArrayList<>(); 41 | patterns.add("/user/login"); 42 | patterns.add("/user/checkUserName"); 43 | patterns.add("/user/checkPhone"); 44 | patterns.add("/user/register"); 45 | patterns.add("/user/loginAuto"); 46 | patterns.add("/rabbitmq/sendInformation"); 47 | registry.addInterceptor(sysInterceptor()) 48 | .addPathPatterns("/**") 49 | .excludePathPatterns(patterns); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/Goods.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableId; 4 | import com.baomidou.mybatisplus.annotation.TableName; 5 | import lombok.Data; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * 商品实体类 11 | * 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-01 17:59 15 | */ 16 | @Data 17 | @TableName("t_goods") 18 | public class Goods implements Serializable { 19 | 20 | /** 21 | * 编号 22 | */ 23 | @TableId 24 | private Integer id; 25 | /** 26 | * 名称 27 | */ 28 | private String name; 29 | /** 30 | * 价格 31 | */ 32 | private Double price; 33 | /** 34 | * 图片 35 | */ 36 | private String image; 37 | /** 38 | * 库存 39 | */ 40 | private Integer stock; 41 | /** 42 | * 详情 43 | */ 44 | private String detail; 45 | 46 | private static final long serialVersionUID = 1L; 47 | } -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/MiaoShaGoods.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 秒杀商品实体类 14 | * 15 | * @author LeDao 16 | * @company 17 | * @create 2022-04-01 18:31 18 | */ 19 | @Data 20 | @TableName("t_miaosha_goods") 21 | public class MiaoShaGoods implements Serializable { 22 | 23 | /** 24 | * 编号 25 | */ 26 | @TableId(type = IdType.AUTO) 27 | private Integer id; 28 | /** 29 | * 真实商品id 30 | */ 31 | @TableField(value = "goodsId") 32 | private Integer goodsId; 33 | /** 34 | * 商品实体,获取对应商品的信息 35 | */ 36 | @TableField(exist = false) 37 | private Goods goods; 38 | /** 39 | * 秒杀的价格 40 | */ 41 | private Double price; 42 | /** 43 | * 秒杀的数量 44 | */ 45 | private Integer stock; 46 | /** 47 | * 开始时间 48 | */ 49 | @TableField(value = "startTime") 50 | private Date startTime; 51 | /** 52 | * 结束时间 53 | */ 54 | @TableField(value = "endTime") 55 | private Date endTime; 56 | 57 | private static final long serialVersionUID = 1L; 58 | } -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/Order.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.TableField; 4 | import com.baomidou.mybatisplus.annotation.TableId; 5 | import com.baomidou.mybatisplus.annotation.TableName; 6 | import lombok.Data; 7 | 8 | import java.io.Serializable; 9 | import java.util.Date; 10 | 11 | /** 12 | * 订单实体类 13 | * 14 | * @author LeDao 15 | * @company 16 | * @create 2022-04-02 22:34 17 | */ 18 | @Data 19 | @TableName("t_order") 20 | public class Order implements Serializable { 21 | 22 | /** 23 | * 编号 24 | */ 25 | @TableId 26 | private Integer id; 27 | /** 28 | * 创建时间 29 | */ 30 | @TableField(value = "createTime") 31 | private Date createTime; 32 | /** 33 | * 商品id 34 | */ 35 | @TableField(value = "goodsId") 36 | private Integer goodsId; 37 | /** 38 | * 对应的商品实体类 39 | */ 40 | @TableField(exist = false) 41 | private Goods goods; 42 | /** 43 | * 秒杀商品id 44 | */ 45 | @TableField(value = "miaoShaGoodsId") 46 | private Integer miaoShaGoodsId; 47 | /** 48 | * 支付状态,0代表未支付,1代表已支付,2代表已取消 49 | */ 50 | @TableField(value = "payStatus") 51 | private Integer payStatus; 52 | /** 53 | * 购买数量 54 | */ 55 | private Integer num; 56 | /** 57 | * 用户id 58 | */ 59 | @TableField(value = "userId") 60 | private Integer userId; 61 | /** 62 | * 价格 63 | */ 64 | private double price; 65 | 66 | private static final long serialVersionUID = 1L; 67 | } -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/PR.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 页面响应entity 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-03-31 0:28 12 | */ 13 | public class PR extends HashMap { 14 | 15 | private static final long serialVersionUID = 1L; 16 | 17 | public PR() { 18 | put("code", 0); 19 | } 20 | 21 | public static PR error() { 22 | return error(500, "未知异常,请联系管理员"); 23 | } 24 | 25 | public static PR error(String msg) { 26 | return error(500, msg); 27 | } 28 | 29 | public static PR error(int code, String msg) { 30 | PR r = new PR(); 31 | r.put("code", code); 32 | r.put("msg", msg); 33 | return r; 34 | } 35 | 36 | public static PR ok(String msg) { 37 | PR r = new PR(); 38 | r.put("msg", msg); 39 | return r; 40 | } 41 | 42 | public static PR ok(Map map) { 43 | PR r = new PR(); 44 | r.putAll(map); 45 | return r; 46 | } 47 | 48 | public static PR ok() { 49 | return new PR(); 50 | } 51 | 52 | @Override 53 | public PR put(String key, Object value) { 54 | super.put(key, value); 55 | return this; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/User.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity; 2 | 3 | import com.baomidou.mybatisplus.annotation.IdType; 4 | import com.baomidou.mybatisplus.annotation.TableField; 5 | import com.baomidou.mybatisplus.annotation.TableId; 6 | import com.baomidou.mybatisplus.annotation.TableName; 7 | import lombok.Data; 8 | 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | 12 | /** 13 | * 用户实体类 14 | * 15 | * @author LeDao 16 | * @company 17 | * @create 2022-03-29 16:21 18 | */ 19 | @Data 20 | @TableName("t_user") 21 | public class User implements Serializable { 22 | 23 | /** 24 | * 编号 25 | */ 26 | @TableId(type = IdType.AUTO) 27 | private Integer id; 28 | /** 29 | * 用户名 30 | */ 31 | @TableField(value = "userName") 32 | private String userName; 33 | /** 34 | * 密码 35 | */ 36 | private String password; 37 | /** 38 | * 姓名 39 | */ 40 | private String name; 41 | /** 42 | * 注册时间 43 | */ 44 | @TableField(value = "registerDate") 45 | private Date registerDate; 46 | /** 47 | * 地址 48 | */ 49 | private String address; 50 | /** 51 | * 手机号码 52 | */ 53 | private String phone; 54 | 55 | private static final long serialVersionUID = 1L; 56 | } 57 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/vo/OrderVo.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity.vo; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | * @author LeDao 7 | * @company 8 | * @create 2022-04-02 22:53 9 | */ 10 | @Data 11 | public class OrderVo { 12 | 13 | /** 14 | * 编号 15 | */ 16 | private Integer id; 17 | /** 18 | * 用户id 19 | */ 20 | private Integer userId; 21 | /** 22 | * 商品id 23 | */ 24 | private Integer goodsId; 25 | /** 26 | * 秒杀商品id 27 | */ 28 | private Integer miaoShaGoodsId; 29 | /** 30 | * 支付状态,0代表未支付,1代表已支付 31 | */ 32 | private Integer payStatus; 33 | /** 34 | * 价格 35 | */ 36 | private double price; 37 | } 38 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/entity/vo/UserVo.java: -------------------------------------------------------------------------------- 1 | package com.ledao.entity.vo; 2 | 3 | import lombok.Data; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 用户Vo实体类 9 | * 10 | * @author LeDao 11 | * @company 12 | * @create 2022-03-29 22:48 13 | */ 14 | @Data 15 | public class UserVo implements Serializable { 16 | 17 | /** 18 | * 用户名 19 | */ 20 | private String userName; 21 | /** 22 | * 密码 23 | */ 24 | private String password; 25 | /** 26 | * 手机号 27 | */ 28 | private String phone; 29 | } 30 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/exception/GlobalExceptionHanlder.java: -------------------------------------------------------------------------------- 1 | package com.ledao.exception; 2 | 3 | import com.ledao.entity.PR; 4 | import org.springframework.web.bind.annotation.ControllerAdvice; 5 | import org.springframework.web.bind.annotation.ExceptionHandler; 6 | import org.springframework.web.bind.annotation.ResponseBody; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | /** 11 | * 全局异常处理 12 | * 13 | * @author LeDao 14 | * @company 15 | * @create 2022-03-31 0:18 16 | */ 17 | @ResponseBody 18 | @ControllerAdvice 19 | public class GlobalExceptionHanlder { 20 | 21 | @ExceptionHandler(value = Exception.class) 22 | public PR exceptionHandler(HttpServletRequest request, Exception e) { 23 | return PR.error("服务端异常,请联系管理员" + "
" + e.getMessage() + "
" + e.getStackTrace()); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/interceptor/SysInterceptor.java: -------------------------------------------------------------------------------- 1 | package com.ledao.interceptor; 2 | 3 | import com.ledao.util.RedisUtil; 4 | import com.ledao.util.StringUtil; 5 | import org.springframework.web.method.HandlerMethod; 6 | import org.springframework.web.servlet.HandlerInterceptor; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | import javax.servlet.http.HttpServletResponse; 10 | 11 | /** 12 | * 鉴权拦截器 13 | * 14 | * @author LeDao 15 | * @company 16 | * @create 2022-03-30 23:09 17 | */ 18 | public class SysInterceptor implements HandlerInterceptor { 19 | 20 | @Override 21 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { 22 | if (handler instanceof HandlerMethod) { 23 | String token = request.getHeader("token"); 24 | if (StringUtil.isEmpty(token)) { 25 | throw new RuntimeException("签名验证不存在"); 26 | } else { 27 | boolean key = RedisUtil.existKey(token); 28 | if (key) { 29 | return true; 30 | } else { 31 | throw new RuntimeException("签名失败"); 32 | } 33 | } 34 | } else { 35 | return true; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/util/Md5Util.java: -------------------------------------------------------------------------------- 1 | package com.ledao.util; 2 | 3 | import org.apache.commons.codec.digest.DigestUtils; 4 | 5 | /** 6 | * @author LeDao 7 | * @company 8 | * @create 2022-03-29 23:11 9 | */ 10 | public class Md5Util { 11 | 12 | /** 13 | * 前端加密盐 14 | */ 15 | private static final String FRONT_SALT = "2das8fse5hgb"; 16 | /** 17 | * 后端加密前置盐 18 | */ 19 | private static final String BACK_SALT_BEFORE = "9das1wda5dsa"; 20 | /** 21 | * 后端加密后置盐 22 | */ 23 | private static final String BACK_SALT_AFTER = "4dsa0kjh6ert"; 24 | 25 | /** 26 | * md5加密 27 | * 28 | * @param data 29 | * @return 30 | */ 31 | public static String md5(String data) { 32 | return DigestUtils.md5Hex(data); 33 | } 34 | 35 | /** 36 | * 前端加盐后md5加密 37 | * 38 | * @param frontData 39 | * @return 40 | */ 41 | public static String frontMd5(String frontData) { 42 | return md5(FRONT_SALT + frontData); 43 | } 44 | 45 | /** 46 | * 后端加盐后md5加密 47 | * 48 | * @param backData 49 | * @return 50 | */ 51 | public static String backMd5(String backData) { 52 | return md5(BACK_SALT_BEFORE + backData + BACK_SALT_AFTER); 53 | } 54 | 55 | public static void main(String[] args) { 56 | System.out.println("前端md5加密:" + frontMd5("4")); 57 | System.out.println("后端md5加密验证:" + backMd5(frontMd5("4"))); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/util/RedisUtil.java: -------------------------------------------------------------------------------- 1 | package com.ledao.util; 2 | 3 | import com.google.gson.Gson; 4 | import org.springframework.data.redis.core.StringRedisTemplate; 5 | import org.springframework.stereotype.Component; 6 | 7 | import javax.annotation.PostConstruct; 8 | import javax.annotation.Resource; 9 | import java.util.List; 10 | import java.util.concurrent.TimeUnit; 11 | 12 | /** 13 | * Redis工具类 14 | * 15 | * @author LeDao 16 | * @company 17 | * @create 2022-03-30 2:22 18 | */ 19 | @Component 20 | public class RedisUtil { 21 | 22 | /** 23 | * 维护一个本类的静态变量 24 | */ 25 | private static RedisUtil redisUtil; 26 | 27 | @Resource 28 | private StringRedisTemplate stringRedisTemplate; 29 | 30 | /** 31 | * 使用@PostConstruct注解标记工具类,初始化Bean 32 | */ 33 | @PostConstruct 34 | public void init() { 35 | redisUtil = this; 36 | redisUtil.stringRedisTemplate = this.stringRedisTemplate; 37 | } 38 | 39 | /** 40 | * Java实体转化为json 41 | * 42 | * @param o 43 | * @return 44 | */ 45 | public static String entityToJson(Object o) { 46 | Gson gson = new Gson(); 47 | return gson.toJson(o); 48 | } 49 | 50 | /** 51 | * json转化为Java实体 52 | * 53 | * @param json 54 | * @param o 55 | * @return 56 | */ 57 | public static Object jsonToEntity(String json, Object o) { 58 | Gson gson = new Gson(); 59 | o = gson.fromJson(json, o.getClass()); 60 | return o; 61 | } 62 | 63 | /** 64 | * 设置key 65 | * 66 | * @param key 67 | * @param value 68 | * @return 69 | */ 70 | public static void setKey(String key, String value) { 71 | redisUtil.stringRedisTemplate.opsForValue().set(key, value); 72 | } 73 | 74 | /** 75 | * 获取key对应的值 76 | * 77 | * @param key 78 | * @return 79 | */ 80 | public static String getKeyValue(String key) { 81 | return redisUtil.stringRedisTemplate.opsForValue().get(key); 82 | } 83 | 84 | /** 85 | * key是否存在 86 | * 87 | * @param key 88 | * @return 89 | */ 90 | public static boolean existKey(String key) { 91 | return Boolean.TRUE.equals(redisUtil.stringRedisTemplate.hasKey(key)); 92 | } 93 | 94 | /** 95 | * 删除key 96 | * 97 | * @param key 98 | * @return 99 | */ 100 | public static boolean delKey(String key) { 101 | boolean result = false; 102 | //key存在就删除 103 | if (existKey(key)) { 104 | result = Boolean.TRUE.equals(redisUtil.stringRedisTemplate.delete(key)); 105 | } 106 | return result; 107 | } 108 | 109 | /** 110 | * 从右边添加元素 111 | * 112 | * @param key 113 | * @param value 114 | * @return 115 | */ 116 | public static void listRightPush(String key, String value) { 117 | redisUtil.stringRedisTemplate.opsForList().rightPush(key, value); 118 | } 119 | 120 | /** 121 | * 从右边弹出元素 122 | * 123 | * @param key 124 | * @return 125 | */ 126 | public static void listRightPop(String key) { 127 | redisUtil.stringRedisTemplate.opsForList().rightPop(key); 128 | } 129 | 130 | /** 131 | * 获取list的元素个数 132 | * 133 | * @param key 134 | * @return 135 | */ 136 | public static Long listLength(String key) { 137 | return redisUtil.stringRedisTemplate.opsForList().size(key); 138 | } 139 | 140 | /** 141 | * 获取元素集合(包含头包含尾) 142 | * 143 | * @param key 144 | * @param start 145 | * @param end 146 | * @return 147 | */ 148 | public static List listRange(String key, Long start, Long end) { 149 | return redisUtil.stringRedisTemplate.opsForList().range(key, start, end); 150 | } 151 | 152 | /** 153 | * 给指定key设置过期时间(秒) 154 | * 155 | * @param key 156 | * @param seconds 157 | */ 158 | public static void setKeyTime(String key, Long seconds) { 159 | redisUtil.stringRedisTemplate.expire(key, seconds, TimeUnit.SECONDS); 160 | } 161 | 162 | /** 163 | * 获取指定key的过期时间(秒) 164 | * 165 | * @param key 166 | * @return 167 | */ 168 | public static Long getKeyTime(String key) { 169 | return redisUtil.stringRedisTemplate.getExpire(key); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.ledao.util; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Random; 6 | 7 | /** 8 | * 字符串工具类 9 | * 10 | * @author LeDao 11 | * @company 12 | * @create 2022-03-30 1:36 13 | */ 14 | public class StringUtil { 15 | 16 | /** 17 | * 判断是否为空 18 | * 19 | * @param str 20 | * @return 21 | */ 22 | public static boolean isEmpty(String str) { 23 | if (str == null || "".equals(str.trim())) { 24 | return true; 25 | } else { 26 | return false; 27 | } 28 | } 29 | 30 | /** 31 | * 判断是否不是空 32 | * 33 | * @param str 34 | * @return 35 | */ 36 | public static boolean isNotEmpty(String str) { 37 | if ((str != null) && !"".equals(str.trim())) { 38 | return true; 39 | } else { 40 | return false; 41 | } 42 | } 43 | 44 | /** 45 | * 格式化模糊查询 46 | * 47 | * @param str 48 | * @return 49 | */ 50 | public static String formatLike(String str) { 51 | if (isNotEmpty(str)) { 52 | return "%" + str + "%"; 53 | } else { 54 | return null; 55 | } 56 | } 57 | 58 | /** 59 | * 过滤掉集合里的空格 60 | * 61 | * @param list 62 | * @return 63 | */ 64 | public static List filterWhite(List list) { 65 | List resultList = new ArrayList(); 66 | for (String l : list) { 67 | if (isNotEmpty(l)) { 68 | resultList.add(l); 69 | } 70 | } 71 | return resultList; 72 | } 73 | 74 | /** 75 | * 去除html标签 76 | */ 77 | public static String stripHtml(String content) { 78 | //

段落替换为换行 79 | content = content.replaceAll("

", "\r\n"); 80 | //

替换为换行 81 | content = content.replaceAll("", "\r\n"); 82 | // 去掉其它的<>之间的东西 83 | content = content.replaceAll("\\<.*?>", ""); 84 | // 去掉空格 85 | content = content.replaceAll(" ", ""); 86 | return content; 87 | } 88 | 89 | /** 90 | * 生成六位随机数 91 | * 92 | * @return 93 | */ 94 | public static String genSixRandomNum() { 95 | Random random = new Random(); 96 | String result = ""; 97 | for (int i = 0; i < 6; i++) { 98 | result += random.nextInt(10); 99 | } 100 | return result; 101 | } 102 | 103 | /** 104 | * 生成由[A-Z,0-9]生成的随机字符串 105 | * 106 | * @param length 欲生成的字符串长度 107 | * @return 108 | */ 109 | public static String getRandomString(int length) { 110 | Random random = new Random(); 111 | 112 | StringBuffer sb = new StringBuffer(); 113 | 114 | for (int i = 0; i < length; ++i) { 115 | int number = random.nextInt(2); 116 | long result = 0; 117 | 118 | switch (number) { 119 | case 0: 120 | result = Math.round(Math.random() * 25 + 65); 121 | sb.append(String.valueOf((char) result)); 122 | break; 123 | case 1: 124 | 125 | sb.append(String.valueOf(new Random().nextInt(10))); 126 | break; 127 | } 128 | } 129 | return sb.toString(); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /miaosha-common/src/main/java/com/ledao/util/UUIDUtil.java: -------------------------------------------------------------------------------- 1 | package com.ledao.util; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * uuid工具类 7 | * 8 | * @author LeDao 9 | * @company 10 | * @create 2022-03-30 1:29 11 | */ 12 | public class UUIDUtil { 13 | 14 | public static String genUuid(){ 15 | return UUID.randomUUID().toString().replaceAll("-", ""); 16 | } 17 | 18 | public static void main(String[] args) { 19 | System.out.println(genUuid()); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /miaosha-gateway/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-gateway 13 | 14 | 15 | 16 | 17 | com.alibaba.cloud 18 | spring-cloud-starter-alibaba-nacos-discovery 19 | 20 | 21 | 22 | com.alibaba.cloud 23 | spring-cloud-starter-alibaba-nacos-config 24 | 25 | 26 | 27 | org.springframework.cloud 28 | spring-cloud-starter-gateway 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-redis 35 | 36 | 37 | 38 | org.apache.commons 39 | commons-pool2 40 | 41 | 42 | mysql 43 | mysql-connector-java 44 | runtime 45 | 46 | 47 | com.alibaba 48 | druid 49 | 50 | 51 | -------------------------------------------------------------------------------- /miaosha-gateway/src/main/java/com/ledao/MiaoShaGateWayApplication.java: -------------------------------------------------------------------------------- 1 | package com.ledao; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 6 | 7 | /** 8 | * @author LeDao 9 | * @company 10 | * @create 2022-04-09 1:26 11 | */ 12 | @EnableDiscoveryClient 13 | @SpringBootApplication 14 | public class MiaoShaGateWayApplication { 15 | 16 | public static void main(String[] args) { 17 | SpringApplication.run(MiaoShaGateWayApplication.class, args); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /miaosha-gateway/src/main/java/com/ledao/config/KeyResolverConfig.java: -------------------------------------------------------------------------------- 1 | package com.ledao.config; 2 | 3 | import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import reactor.core.publisher.Mono; 7 | 8 | import java.util.Objects; 9 | 10 | /** 11 | * @author LeDao 12 | * @company 13 | * @create 2022-04-26 15:56 14 | */ 15 | @Configuration 16 | public class KeyResolverConfig { 17 | /** 18 | * IP限流 19 | * 20 | * @return 21 | */ 22 | @Bean 23 | public KeyResolver ipKeyResolver() { 24 | return exchange -> Mono.just(Objects.requireNonNull(exchange.getRequest().getRemoteAddress()).getHostName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /miaosha-gateway/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/miaosha-gateway/src/main/resources/application.yml -------------------------------------------------------------------------------- /miaosha-gateway/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #应用名称,可省略 2 | spring.application.name=miaosha-gateway 3 | #Nacos的IP地址和端口号 4 | spring.cloud.nacos.config.server-addr=192.168.0.141:8848 5 | #Nacos配置文件所在命名空间id 6 | spring.cloud.nacos.config.namespace=8b2d6583-c0a0-43bd-a2a8-b215eba8c70e 7 | #Nacos配置文件所在组名 8 | #spring.cloud.nacos.config.group=miaosha-user 9 | #要读取的配置文件名称 10 | #spring.cloud.nacos.config.name=nacos_config.properties 11 | 12 | #加载mysql.yml的配置 13 | spring.cloud.nacos.config.extension-configs[0].dataId=mysql.yml 14 | spring.cloud.nacos.config.extension-configs[0].group=miaosha-common 15 | spring.cloud.nacos.config.extension-configs[0].refresh=true 16 | 17 | #加载jackson.yml的配置 18 | spring.cloud.nacos.config.extension-configs[1].dataId=jackson.yml 19 | spring.cloud.nacos.config.extension-configs[1].group=miaosha-common 20 | spring.cloud.nacos.config.extension-configs[1].refresh=true 21 | 22 | #加载redis.yml的配置 23 | spring.cloud.nacos.config.extension-configs[2].dataId=redis.yml 24 | spring.cloud.nacos.config.extension-configs[2].group=miaosha-common 25 | spring.cloud.nacos.config.extension-configs[2].refresh=true 26 | 27 | #加载spring-cloud.yml的配置 28 | spring.cloud.nacos.config.extension-configs[3].dataId=spring-cloud.yml 29 | spring.cloud.nacos.config.extension-configs[3].group=miaosha-gateway 30 | spring.cloud.nacos.config.extension-configs[3].refresh=true 31 | 32 | #加载server.yml的配置 33 | spring.cloud.nacos.config.extension-configs[4].dataId=server.yml 34 | spring.cloud.nacos.config.extension-configs[4].group=miaosha-gateway 35 | spring.cloud.nacos.config.extension-configs[4].refresh=true -------------------------------------------------------------------------------- /miaosha-goods/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-goods 13 | 14 | 15 | 16 | org.example 17 | miaosha-common 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/MiaoShaGoodsApplication.java: -------------------------------------------------------------------------------- 1 | package com.ledao; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-07 9:40 12 | */ 13 | @SpringBootApplication 14 | @EnableDiscoveryClient 15 | @MapperScan("com.ledao.mapper") 16 | public class MiaoShaGoodsApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(MiaoShaGoodsApplication.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/controller/MiaoShaGoodsController.java: -------------------------------------------------------------------------------- 1 | package com.ledao.controller; 2 | 3 | import com.ledao.entity.MiaoShaGoods; 4 | import com.ledao.entity.Order; 5 | import com.ledao.service.MiaoShaGoodsService; 6 | import com.ledao.service.OrderService; 7 | import org.springframework.web.bind.annotation.CrossOrigin; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import javax.annotation.Resource; 12 | import javax.servlet.http.HttpServletRequest; 13 | import java.util.*; 14 | 15 | /** 16 | * @author LeDao 17 | * @company 18 | * @create 2022-04-01 22:33 19 | */ 20 | @RestController 21 | @RequestMapping("/miaoShaGoods") 22 | public class MiaoShaGoodsController { 23 | 24 | @Resource 25 | private MiaoShaGoodsService miaoShaGoodsService; 26 | 27 | @Resource 28 | private OrderService orderService; 29 | 30 | @RequestMapping("/listAllNow") 31 | public List listAllNow(HttpServletRequest request) { 32 | List miaoShaGoodsList=miaoShaGoodsService.listAllNow(); 33 | int userId = Integer.parseInt(request.getHeader("userId")); 34 | //已经抢到的秒杀商品不能查看 35 | for (int i = 0; i < miaoShaGoodsList.size(); i++) { 36 | MiaoShaGoods miaoShaGoods = miaoShaGoodsList.get(i); 37 | Map map = new HashMap<>(16); 38 | map.put("userId", userId); 39 | map.put("miaoShaGoodsId", miaoShaGoods.getId()); 40 | Order order = orderService.findByUserIdAndMiaoShaGoodsId(map); 41 | //已经秒杀过就不显示这个商品 42 | if (order != null) { 43 | miaoShaGoodsList.remove(miaoShaGoods); 44 | i--; 45 | } 46 | } 47 | for (MiaoShaGoods miaoShaGoods : miaoShaGoodsList) { 48 | System.out.println(miaoShaGoods.getGoods().getName()); 49 | } 50 | return miaoShaGoodsList; 51 | } 52 | 53 | @RequestMapping("/findById") 54 | public MiaoShaGoods findById(Integer id) { 55 | return miaoShaGoodsService.findById(id); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/mapper/GoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Mapper接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 17:59 12 | */ 13 | public interface GoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | 23 | /** 24 | * 减秒杀商品的数量-1 25 | * 26 | * @param id 27 | * @return 28 | */ 29 | int reduceStock(Integer id); 30 | } -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/mapper/MiaoShaGoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:31 12 | */ 13 | public interface MiaoShaGoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | 30 | /** 31 | * 减秒杀商品的数量-1 32 | * 33 | * @param id 34 | * @return 35 | */ 36 | int reduceStock(Integer id); 37 | } -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 订单Mapper接口实体类 11 | * 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-02 22:34 15 | */ 16 | public interface OrderMapper extends BaseMapper { 17 | 18 | /** 19 | * 根据条件获取订单 20 | * 21 | * @param map 22 | * @return 23 | */ 24 | List list(Map map); 25 | 26 | /** 27 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 28 | * 29 | * @param map 30 | * @return 31 | */ 32 | Order findByUserIdAndMiaoShaGoodsId(Map map); 33 | 34 | /** 35 | * 添加订单 36 | * 37 | * @param order 38 | * @return 39 | */ 40 | int add(Order order); 41 | } -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/service/MiaoShaGoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 22:02 12 | */ 13 | public interface MiaoShaGoodsService extends IService { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | } 30 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author LeDao 11 | * @company 12 | * @create 2022-04-02 22:39 13 | */ 14 | public interface OrderService extends IService { 15 | 16 | /** 17 | * 根据条件获取订单 18 | * 19 | * @param map 20 | * @return 21 | */ 22 | List list(Map map); 23 | 24 | /** 25 | * 添加订单 26 | * 27 | * @param order 28 | * @return 29 | */ 30 | int add(Order order); 31 | 32 | /** 33 | * 修改订单 34 | * 35 | * @param order 36 | * @return 37 | */ 38 | int update(Order order); 39 | 40 | /** 41 | * 根据id查找订单 42 | * 43 | * @param id 44 | * @return 45 | */ 46 | Order findById(Integer id); 47 | 48 | /** 49 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 50 | * 51 | * @param map 52 | * @return 53 | */ 54 | Order findByUserIdAndMiaoShaGoodsId(Map map); 55 | } 56 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/service/impl/MiaoShaGoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.mapper.MiaoShaGoodsMapper; 7 | import com.ledao.service.MiaoShaGoodsService; 8 | import com.ledao.util.RedisUtil; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * @author LeDao 16 | * @company 17 | * @create 2022-04-01 22:04 18 | */ 19 | @Service("miaoShaGoodsService") 20 | public class MiaoShaGoodsServiceImpl extends ServiceImpl implements MiaoShaGoodsService { 21 | 22 | @Resource 23 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 24 | 25 | @Override 26 | public List listAllNow() { 27 | return miaoShaGoodsMapper.listAllNow(); 28 | } 29 | 30 | @Override 31 | public MiaoShaGoods findById(Integer id) { 32 | Gson gson = new Gson(); 33 | String key = "miaoShaGoods_" + id; 34 | MiaoShaGoods miaoShaGoods; 35 | //当这个秒杀商品在Redis中存在时 36 | if (RedisUtil.existKey(key)) { 37 | miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 38 | } else { 39 | miaoShaGoods = miaoShaGoodsMapper.findById(id); 40 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 41 | //获取秒杀时长 42 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 43 | //设置过期时间 44 | RedisUtil.setKeyTime(key, time); 45 | } 46 | return miaoShaGoods; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/java/com/ledao/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.entity.Order; 7 | import com.ledao.mapper.GoodsMapper; 8 | import com.ledao.mapper.MiaoShaGoodsMapper; 9 | import com.ledao.mapper.OrderMapper; 10 | import com.ledao.service.OrderService; 11 | import com.ledao.util.RedisUtil; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author LeDao 21 | * @company 22 | * @create 2022-04-02 22:40 23 | */ 24 | @Service("orderService") 25 | public class OrderServiceImpl extends ServiceImpl implements OrderService { 26 | 27 | @Resource 28 | private OrderMapper orderMapper; 29 | 30 | @Resource 31 | private GoodsMapper goodsMapper; 32 | 33 | @Resource 34 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 35 | 36 | @Override 37 | public List list(Map map) { 38 | return orderMapper.list(map); 39 | } 40 | 41 | @Override 42 | @Transactional(rollbackFor = {Exception.class}) 43 | public int add(Order order) { 44 | miaoShaGoodsMapper.reduceStock(order.getMiaoShaGoodsId()); 45 | goodsMapper.reduceStock(order.getGoodsId()); 46 | int result = orderMapper.add(order); 47 | Gson gson = new Gson(); 48 | String key = "miaoShaGoods_" + order.getMiaoShaGoodsId(); 49 | MiaoShaGoods miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 50 | miaoShaGoods.setStock(miaoShaGoods.getStock() - 1); 51 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 52 | //获取秒杀时长 53 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 54 | //设置过期时间 55 | RedisUtil.setKeyTime(key, time); 56 | return result; 57 | } 58 | 59 | @Override 60 | public int update(Order order) { 61 | return orderMapper.updateById(order); 62 | } 63 | 64 | @Override 65 | public Order findById(Integer id) { 66 | return orderMapper.selectById(id); 67 | } 68 | 69 | @Override 70 | public Order findByUserIdAndMiaoShaGoodsId(Map map) { 71 | return orderMapper.findByUserIdAndMiaoShaGoodsId(map); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/miaosha-goods/src/main/resources/application.yml -------------------------------------------------------------------------------- /miaosha-goods/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #应用名称,可省略 2 | spring.application.name=miaosha-goods 3 | #Nacos的IP地址和端口号 4 | spring.cloud.nacos.config.server-addr=192.168.0.141:8848 5 | #Nacos配置文件所在命名空间id 6 | spring.cloud.nacos.config.namespace=8b2d6583-c0a0-43bd-a2a8-b215eba8c70e 7 | #Nacos配置文件所在组名 8 | #spring.cloud.nacos.config.group=miaosha-user 9 | #要读取的配置文件名称 10 | #spring.cloud.nacos.config.name=nacos_config.properties 11 | 12 | #加载mysql.yml的配置 13 | spring.cloud.nacos.config.extension-configs[0].dataId=mysql.yml 14 | spring.cloud.nacos.config.extension-configs[0].group=miaosha-common 15 | spring.cloud.nacos.config.extension-configs[0].refresh=true 16 | 17 | #加载jackson.yml的配置 18 | spring.cloud.nacos.config.extension-configs[1].dataId=jackson.yml 19 | spring.cloud.nacos.config.extension-configs[1].group=miaosha-common 20 | spring.cloud.nacos.config.extension-configs[1].refresh=true 21 | 22 | #加载redis.yml的配置 23 | spring.cloud.nacos.config.extension-configs[2].dataId=redis.yml 24 | spring.cloud.nacos.config.extension-configs[2].group=miaosha-common 25 | spring.cloud.nacos.config.extension-configs[2].refresh=true 26 | 27 | #加载spring-cloud.yml的配置 28 | spring.cloud.nacos.config.extension-configs[3].dataId=spring-cloud.yml 29 | spring.cloud.nacos.config.extension-configs[3].group=miaosha-goods 30 | spring.cloud.nacos.config.extension-configs[3].refresh=true 31 | 32 | #加载server.yml的配置 33 | spring.cloud.nacos.config.extension-configs[4].dataId=server.yml 34 | spring.cloud.nacos.config.extension-configs[4].group=miaosha-goods 35 | spring.cloud.nacos.config.extension-configs[4].refresh=true 36 | 37 | #加载mybatis-plus.yml的配置 38 | spring.cloud.nacos.config.extension-configs[5].dataId=mybatis-plus.yml 39 | spring.cloud.nacos.config.extension-configs[5].group=miaosha-common 40 | spring.cloud.nacos.config.extension-configs[5].refresh=true -------------------------------------------------------------------------------- /miaosha-goods/src/main/resources/mybatis/mapper/GoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | update t_goods 21 | set stock=stock - 1 22 | where id = #{id} 23 | 24 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/resources/mybatis/mapper/MiaoShaGoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | id, goodsId, price, stock, startTime, endTime 19 | 20 | 21 | 29 | 30 | 35 | 36 | 37 | update t_miaosha_goods 38 | set stock=stock - 1 39 | where id = #{id} 40 | and stock > 0; 41 | 42 | -------------------------------------------------------------------------------- /miaosha-goods/src/main/resources/mybatis/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | id, createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId 21 | 22 | 23 | 35 | 36 | 42 | 43 | 44 | insert into t_order (createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId) 45 | values (now(), #{goodsId}, #{payStatus}, #{num}, #{userId}, #{price}, #{miaoShaGoodsId}); 46 | 47 | -------------------------------------------------------------------------------- /miaosha-order1/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-order1 13 | 14 | 15 | 16 | org.example 17 | miaosha-common 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-openfeign 23 | 24 | 25 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/MiaoShaOrderApplication1.java: -------------------------------------------------------------------------------- 1 | package com.ledao; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.openfeign.EnableFeignClients; 8 | 9 | /** 10 | * @author LeDao 11 | * @company 12 | * @create 2022-04-08 14:48 13 | */ 14 | @SpringBootApplication 15 | @EnableDiscoveryClient 16 | @MapperScan("com.ledao.mapper") 17 | @EnableFeignClients(basePackages = "com.ledao.feign") 18 | public class MiaoShaOrderApplication1 { 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(MiaoShaOrderApplication1.class, args); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.ledao.controller; 2 | 3 | import com.ledao.entity.MiaoShaGoods; 4 | import com.ledao.entity.Order; 5 | import com.ledao.entity.vo.OrderVo; 6 | import com.ledao.feign.RabbitMQFeignService; 7 | import com.ledao.service.MiaoShaGoodsService; 8 | import com.ledao.service.OrderService; 9 | import com.ledao.util.RedisUtil; 10 | import org.springframework.web.bind.annotation.CrossOrigin; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | /** 19 | * @author LeDao 20 | * @company 21 | * @create 2022-04-02 22:41 22 | */ 23 | @RestController 24 | @RequestMapping("/order") 25 | public class OrderController { 26 | 27 | @Resource 28 | private OrderService orderService; 29 | 30 | @Resource 31 | private MiaoShaGoodsService miaoShaGoodsService; 32 | 33 | @Resource 34 | private RabbitMQFeignService rabbitMQFeignService; 35 | 36 | /** 37 | * 根据条件获取订单 38 | * 39 | * @param orderVo 40 | * @return 41 | */ 42 | @RequestMapping("/list") 43 | public Map list(OrderVo orderVo) { 44 | Map resultMap = new HashMap<>(16); 45 | Map map = new HashMap<>(16); 46 | map.put("userId", orderVo.getUserId()); 47 | resultMap.put("rows", orderService.list(map)); 48 | return resultMap; 49 | } 50 | 51 | /** 52 | * 添加或修改订单 53 | * 54 | * @param orderVo 55 | * @return 56 | */ 57 | @RequestMapping("/save") 58 | public Map save(OrderVo orderVo) { 59 | Map resultMap = new HashMap<>(16); 60 | int key = 0; 61 | if (orderVo.getId() == null) { 62 | System.out.println("------------开始秒杀-----------"); 63 | MiaoShaGoods miaoShaGoods = miaoShaGoodsService.findById(orderVo.getMiaoShaGoodsId()); 64 | //判断是否已经过了秒杀时间,时间过了不可以秒杀 65 | if (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis() >= 0) { 66 | //当前秒杀商品的库存大于0时才放进消息队列 67 | if (miaoShaGoods.getStock() > 0) { 68 | rabbitMQFeignService.sendInformation(RedisUtil.entityToJson(orderVo)); 69 | key = 1; 70 | } else { 71 | resultMap.put("errorInfo", "你手慢了,该商品已经被秒杀完了!!"); 72 | } 73 | } 74 | } else { 75 | Order order = orderService.findById(orderVo.getId()); 76 | order.setPayStatus(orderVo.getPayStatus()); 77 | key = orderService.update(order); 78 | } 79 | if (key > 0) { 80 | resultMap.put("success", true); 81 | } else { 82 | resultMap.put("success", false); 83 | } 84 | return resultMap; 85 | } 86 | 87 | /** 88 | * 检验是否秒杀成功,返回1代表秒杀成功,返回0代表排队中,返回-1代表秒杀失败 89 | * 90 | * @param userId 91 | * @param miaoShaGoodsId 92 | * @return 93 | */ 94 | @RequestMapping("/checkStatus") 95 | public int checkStatus(int userId, int miaoShaGoodsId) { 96 | Map map = new HashMap<>(16); 97 | map.put("userId", userId); 98 | map.put("miaoShaGoodsId", miaoShaGoodsId); 99 | Order order = orderService.findByUserIdAndMiaoShaGoodsId(map); 100 | //订单存在,代表秒杀成功 101 | if (order != null) { 102 | return 1; 103 | } else { 104 | MiaoShaGoods miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId); 105 | //还有库存,代表在排队中 106 | if (miaoShaGoods.getStock() > 0) { 107 | return 0; 108 | } else {//没有库存,代表秒杀已结束 109 | return -1; 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/feign/RabbitMQFeignService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.feign; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | /** 8 | * @author LeDao 9 | * @company 10 | * @create 2022-04-08 16:33 11 | */ 12 | @FeignClient("miaosha-rabbitmq") 13 | public interface RabbitMQFeignService { 14 | 15 | /** 16 | * 调用miaosha-rabbitmq微服务的/rabbitmq/sendInformation 17 | * 18 | * @param information 19 | */ 20 | @RequestMapping("/rabbitmq/sendInformation") 21 | void sendInformation(@RequestParam("information") String information); 22 | } 23 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/mapper/GoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Mapper接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 17:59 12 | */ 13 | public interface GoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | 23 | /** 24 | * 减秒杀商品的数量-1 25 | * 26 | * @param id 27 | * @return 28 | */ 29 | int reduceStock(Integer id); 30 | } -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/mapper/MiaoShaGoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:31 12 | */ 13 | public interface MiaoShaGoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | 30 | /** 31 | * 减秒杀商品的数量-1 32 | * 33 | * @param id 34 | * @return 35 | */ 36 | int reduceStock(Integer id); 37 | } -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 订单Mapper接口实体类 11 | * 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-02 22:34 15 | */ 16 | public interface OrderMapper extends BaseMapper { 17 | 18 | /** 19 | * 根据条件获取订单 20 | * 21 | * @param map 22 | * @return 23 | */ 24 | List list(Map map); 25 | 26 | /** 27 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 28 | * 29 | * @param map 30 | * @return 31 | */ 32 | Order findByUserIdAndMiaoShaGoodsId(Map map); 33 | 34 | /** 35 | * 添加订单 36 | * 37 | * @param order 38 | * @return 39 | */ 40 | int add(Order order); 41 | } -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/service/GoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Service接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:06 12 | */ 13 | public interface GoodsService extends IService { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | } 23 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/service/MiaoShaGoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 22:02 12 | */ 13 | public interface MiaoShaGoodsService extends IService { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | } 30 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author LeDao 11 | * @company 12 | * @create 2022-04-02 22:39 13 | */ 14 | public interface OrderService extends IService { 15 | 16 | /** 17 | * 根据条件获取订单 18 | * 19 | * @param map 20 | * @return 21 | */ 22 | List list(Map map); 23 | 24 | /** 25 | * 添加订单 26 | * 27 | * @param order 28 | * @return 29 | */ 30 | int add(Order order); 31 | 32 | /** 33 | * 修改订单 34 | * 35 | * @param order 36 | * @return 37 | */ 38 | int update(Order order); 39 | 40 | /** 41 | * 根据id查找订单 42 | * 43 | * @param id 44 | * @return 45 | */ 46 | Order findById(Integer id); 47 | 48 | /** 49 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 50 | * 51 | * @param map 52 | * @return 53 | */ 54 | Order findByUserIdAndMiaoShaGoodsId(Map map); 55 | } 56 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/service/impl/GoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.ledao.entity.Goods; 5 | import com.ledao.mapper.GoodsMapper; 6 | import com.ledao.service.GoodsService; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-01 18:07 15 | */ 16 | @Service("goodsService") 17 | public class GoodsServiceImpl extends ServiceImpl implements GoodsService { 18 | 19 | @Resource 20 | private GoodsMapper goodsMapper; 21 | 22 | @Override 23 | public Goods findById(Integer id) { 24 | return goodsMapper.findById(id); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/service/impl/MiaoShaGoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.mapper.MiaoShaGoodsMapper; 7 | import com.ledao.service.MiaoShaGoodsService; 8 | import com.ledao.util.RedisUtil; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * @author LeDao 16 | * @company 17 | * @create 2022-04-01 22:04 18 | */ 19 | @Service("miaoShaGoodsService") 20 | public class MiaoShaGoodsServiceImpl extends ServiceImpl implements MiaoShaGoodsService { 21 | 22 | @Resource 23 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 24 | 25 | @Override 26 | public List listAllNow() { 27 | return miaoShaGoodsMapper.listAllNow(); 28 | } 29 | 30 | @Override 31 | public MiaoShaGoods findById(Integer id) { 32 | Gson gson = new Gson(); 33 | String key = "miaoShaGoods_" + id; 34 | MiaoShaGoods miaoShaGoods; 35 | //当这个秒杀商品在Redis中存在时 36 | if (RedisUtil.existKey(key)) { 37 | miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 38 | } else { 39 | miaoShaGoods = miaoShaGoodsMapper.findById(id); 40 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 41 | //获取秒杀时长 42 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 43 | //设置过期时间 44 | RedisUtil.setKeyTime(key, time); 45 | } 46 | return miaoShaGoods; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/java/com/ledao/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.entity.Order; 7 | import com.ledao.mapper.GoodsMapper; 8 | import com.ledao.mapper.MiaoShaGoodsMapper; 9 | import com.ledao.mapper.OrderMapper; 10 | import com.ledao.service.OrderService; 11 | import com.ledao.util.RedisUtil; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author LeDao 21 | * @company 22 | * @create 2022-04-02 22:40 23 | */ 24 | @Service("orderService") 25 | public class OrderServiceImpl extends ServiceImpl implements OrderService { 26 | 27 | @Resource 28 | private OrderMapper orderMapper; 29 | 30 | @Resource 31 | private GoodsMapper goodsMapper; 32 | 33 | @Resource 34 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 35 | 36 | @Override 37 | public List list(Map map) { 38 | return orderMapper.list(map); 39 | } 40 | 41 | @Override 42 | @Transactional(rollbackFor = {Exception.class}) 43 | public int add(Order order) { 44 | miaoShaGoodsMapper.reduceStock(order.getMiaoShaGoodsId()); 45 | goodsMapper.reduceStock(order.getGoodsId()); 46 | int result = orderMapper.add(order); 47 | Gson gson = new Gson(); 48 | String key = "miaoShaGoods_" + order.getMiaoShaGoodsId(); 49 | MiaoShaGoods miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 50 | miaoShaGoods.setStock(miaoShaGoods.getStock() - 1); 51 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 52 | //获取秒杀时长 53 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 54 | //设置过期时间 55 | RedisUtil.setKeyTime(key, time); 56 | return result; 57 | } 58 | 59 | @Override 60 | public int update(Order order) { 61 | return orderMapper.updateById(order); 62 | } 63 | 64 | @Override 65 | public Order findById(Integer id) { 66 | return orderMapper.selectById(id); 67 | } 68 | 69 | @Override 70 | public Order findByUserIdAndMiaoShaGoodsId(Map map) { 71 | return orderMapper.findByUserIdAndMiaoShaGoodsId(map); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/miaosha-order1/src/main/resources/application.yml -------------------------------------------------------------------------------- /miaosha-order1/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #应用名称,可省略 2 | spring.application.name=miaosha-order1 3 | #Nacos的IP地址和端口号 4 | spring.cloud.nacos.config.server-addr=192.168.0.141:8848 5 | #Nacos配置文件所在命名空间id 6 | spring.cloud.nacos.config.namespace=8b2d6583-c0a0-43bd-a2a8-b215eba8c70e 7 | #Nacos配置文件所在组名 8 | #spring.cloud.nacos.config.group=miaosha-user 9 | #要读取的配置文件名称 10 | #spring.cloud.nacos.config.name=nacos_config.properties 11 | 12 | #加载mysql.yml的配置 13 | spring.cloud.nacos.config.extension-configs[0].dataId=mysql.yml 14 | spring.cloud.nacos.config.extension-configs[0].group=miaosha-common 15 | spring.cloud.nacos.config.extension-configs[0].refresh=true 16 | 17 | #加载jackson.yml的配置 18 | spring.cloud.nacos.config.extension-configs[1].dataId=jackson.yml 19 | spring.cloud.nacos.config.extension-configs[1].group=miaosha-common 20 | spring.cloud.nacos.config.extension-configs[1].refresh=true 21 | 22 | #加载redis.yml的配置 23 | spring.cloud.nacos.config.extension-configs[2].dataId=redis.yml 24 | spring.cloud.nacos.config.extension-configs[2].group=miaosha-common 25 | spring.cloud.nacos.config.extension-configs[2].refresh=true 26 | 27 | #加载mybatis-plus.yml的配置 28 | spring.cloud.nacos.config.extension-configs[3].dataId=mybatis-plus.yml 29 | spring.cloud.nacos.config.extension-configs[3].group=miaosha-common 30 | spring.cloud.nacos.config.extension-configs[3].refresh=true 31 | 32 | #加载spring-cloud.yml的配置 33 | spring.cloud.nacos.config.extension-configs[4].dataId=spring-cloud.yml 34 | spring.cloud.nacos.config.extension-configs[4].group=miaosha-order1 35 | spring.cloud.nacos.config.extension-configs[4].refresh=true 36 | 37 | #加载server.yml的配置 38 | spring.cloud.nacos.config.extension-configs[5].dataId=server.yml 39 | spring.cloud.nacos.config.extension-configs[5].group=miaosha-order1 40 | spring.cloud.nacos.config.extension-configs[5].refresh=true 41 | 42 | #加载rabbitmq.yml的配置 43 | spring.cloud.nacos.config.extension-configs[6].dataId=rabbitmq.yml 44 | spring.cloud.nacos.config.extension-configs[6].group=miaosha-common 45 | spring.cloud.nacos.config.extension-configs[6].refresh=true -------------------------------------------------------------------------------- /miaosha-order1/src/main/resources/mybatis/mapper/GoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | update t_goods 21 | set stock=stock - 1 22 | where id = #{id} 23 | 24 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/resources/mybatis/mapper/MiaoShaGoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | id, goodsId, price, stock, startTime, endTime 19 | 20 | 21 | 29 | 30 | 35 | 36 | 37 | update t_miaosha_goods 38 | set stock=stock - 1 39 | where id = #{id} 40 | and stock > 0; 41 | 42 | -------------------------------------------------------------------------------- /miaosha-order1/src/main/resources/mybatis/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | id, createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId 21 | 22 | 23 | 35 | 36 | 42 | 43 | 44 | insert into t_order (createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId) 45 | values (now(), #{goodsId}, #{payStatus}, #{num}, #{userId}, #{price}, #{miaoShaGoodsId}); 46 | 47 | -------------------------------------------------------------------------------- /miaosha-order2/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-order2 13 | 14 | 15 | 16 | org.example 17 | miaosha-common 18 | 19 | 20 | 21 | org.springframework.cloud 22 | spring-cloud-starter-openfeign 23 | 24 | 25 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/MiaoShaOrderApplication2.java: -------------------------------------------------------------------------------- 1 | package com.ledao; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | import org.springframework.cloud.openfeign.EnableFeignClients; 8 | 9 | /** 10 | * @author LeDao 11 | * @company 12 | * @create 2022-04-08 14:48 13 | */ 14 | @SpringBootApplication 15 | @EnableDiscoveryClient 16 | @MapperScan("com.ledao.mapper") 17 | @EnableFeignClients(basePackages = "com.ledao.feign") 18 | public class MiaoShaOrderApplication2 { 19 | 20 | public static void main(String[] args) { 21 | SpringApplication.run(MiaoShaOrderApplication2.class, args); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/controller/OrderController.java: -------------------------------------------------------------------------------- 1 | package com.ledao.controller; 2 | 3 | import com.ledao.entity.MiaoShaGoods; 4 | import com.ledao.entity.Order; 5 | import com.ledao.entity.vo.OrderVo; 6 | import com.ledao.feign.RabbitMQFeignService; 7 | import com.ledao.service.MiaoShaGoodsService; 8 | import com.ledao.service.OrderService; 9 | import com.ledao.util.RedisUtil; 10 | import org.springframework.web.bind.annotation.CrossOrigin; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.annotation.Resource; 15 | import java.util.HashMap; 16 | import java.util.Map; 17 | 18 | /** 19 | * @author LeDao 20 | * @company 21 | * @create 2022-04-02 22:41 22 | */ 23 | @RestController 24 | @RequestMapping("/order") 25 | public class OrderController { 26 | 27 | @Resource 28 | private OrderService orderService; 29 | 30 | @Resource 31 | private MiaoShaGoodsService miaoShaGoodsService; 32 | 33 | @Resource 34 | private RabbitMQFeignService rabbitMQFeignService; 35 | 36 | /** 37 | * 根据条件获取订单 38 | * 39 | * @param orderVo 40 | * @return 41 | */ 42 | @RequestMapping("/list") 43 | public Map list(OrderVo orderVo) { 44 | Map resultMap = new HashMap<>(16); 45 | Map map = new HashMap<>(16); 46 | map.put("userId", orderVo.getUserId()); 47 | resultMap.put("rows", orderService.list(map)); 48 | return resultMap; 49 | } 50 | 51 | /** 52 | * 添加或修改订单 53 | * 54 | * @param orderVo 55 | * @return 56 | */ 57 | @RequestMapping("/save") 58 | public Map save(OrderVo orderVo) { 59 | Map resultMap = new HashMap<>(16); 60 | int key = 0; 61 | if (orderVo.getId() == null) { 62 | System.out.println("------------开始秒杀-----------"); 63 | MiaoShaGoods miaoShaGoods = miaoShaGoodsService.findById(orderVo.getMiaoShaGoodsId()); 64 | //判断是否已经过了秒杀时间,时间过了不可以秒杀 65 | if (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis() >= 0) { 66 | //当前秒杀商品的库存大于0时才放进消息队列 67 | if (miaoShaGoods.getStock() > 0) { 68 | rabbitMQFeignService.sendInformation(RedisUtil.entityToJson(orderVo)); 69 | key = 1; 70 | } else { 71 | resultMap.put("errorInfo", "你手慢了,该商品已经被秒杀完了!!"); 72 | } 73 | } 74 | } else { 75 | Order order = orderService.findById(orderVo.getId()); 76 | order.setPayStatus(orderVo.getPayStatus()); 77 | key = orderService.update(order); 78 | } 79 | if (key > 0) { 80 | resultMap.put("success", true); 81 | } else { 82 | resultMap.put("success", false); 83 | } 84 | return resultMap; 85 | } 86 | 87 | /** 88 | * 检验是否秒杀成功,返回1代表秒杀成功,返回0代表排队中,返回-1代表秒杀失败 89 | * 90 | * @param userId 91 | * @param miaoShaGoodsId 92 | * @return 93 | */ 94 | @RequestMapping("/checkStatus") 95 | public int checkStatus(int userId, int miaoShaGoodsId) { 96 | Map map = new HashMap<>(16); 97 | map.put("userId", userId); 98 | map.put("miaoShaGoodsId", miaoShaGoodsId); 99 | Order order = orderService.findByUserIdAndMiaoShaGoodsId(map); 100 | //订单存在,代表秒杀成功 101 | if (order != null) { 102 | return 1; 103 | } else { 104 | MiaoShaGoods miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId); 105 | //还有库存,代表在排队中 106 | if (miaoShaGoods.getStock() > 0) { 107 | return 0; 108 | } else {//没有库存,代表秒杀已结束 109 | return -1; 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/feign/RabbitMQFeignService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.feign; 2 | 3 | import org.springframework.cloud.openfeign.FeignClient; 4 | import org.springframework.web.bind.annotation.RequestMapping; 5 | import org.springframework.web.bind.annotation.RequestParam; 6 | 7 | /** 8 | * @author LeDao 9 | * @company 10 | * @create 2022-04-08 16:33 11 | */ 12 | @FeignClient("miaosha-rabbitmq") 13 | public interface RabbitMQFeignService { 14 | 15 | /** 16 | * 调用miaosha-rabbitmq微服务的/rabbitmq/sendInformation 17 | * 18 | * @param information 19 | */ 20 | @RequestMapping("/rabbitmq/sendInformation") 21 | void sendInformation(@RequestParam("information") String information); 22 | } 23 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/mapper/GoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Mapper接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 17:59 12 | */ 13 | public interface GoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | 23 | /** 24 | * 减秒杀商品的数量-1 25 | * 26 | * @param id 27 | * @return 28 | */ 29 | int reduceStock(Integer id); 30 | } -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/mapper/MiaoShaGoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:31 12 | */ 13 | public interface MiaoShaGoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | 30 | /** 31 | * 减秒杀商品的数量-1 32 | * 33 | * @param id 34 | * @return 35 | */ 36 | int reduceStock(Integer id); 37 | } -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 订单Mapper接口实体类 11 | * 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-02 22:34 15 | */ 16 | public interface OrderMapper extends BaseMapper { 17 | 18 | /** 19 | * 根据条件获取订单 20 | * 21 | * @param map 22 | * @return 23 | */ 24 | List list(Map map); 25 | 26 | /** 27 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 28 | * 29 | * @param map 30 | * @return 31 | */ 32 | Order findByUserIdAndMiaoShaGoodsId(Map map); 33 | 34 | /** 35 | * 添加订单 36 | * 37 | * @param order 38 | * @return 39 | */ 40 | int add(Order order); 41 | } -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/service/GoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Service接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:06 12 | */ 13 | public interface GoodsService extends IService { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | } 23 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/service/MiaoShaGoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 22:02 12 | */ 13 | public interface MiaoShaGoodsService extends IService { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | } 30 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author LeDao 11 | * @company 12 | * @create 2022-04-02 22:39 13 | */ 14 | public interface OrderService extends IService { 15 | 16 | /** 17 | * 根据条件获取订单 18 | * 19 | * @param map 20 | * @return 21 | */ 22 | List list(Map map); 23 | 24 | /** 25 | * 添加订单 26 | * 27 | * @param order 28 | * @return 29 | */ 30 | int add(Order order); 31 | 32 | /** 33 | * 修改订单 34 | * 35 | * @param order 36 | * @return 37 | */ 38 | int update(Order order); 39 | 40 | /** 41 | * 根据id查找订单 42 | * 43 | * @param id 44 | * @return 45 | */ 46 | Order findById(Integer id); 47 | 48 | /** 49 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 50 | * 51 | * @param map 52 | * @return 53 | */ 54 | Order findByUserIdAndMiaoShaGoodsId(Map map); 55 | } 56 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/service/impl/GoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.ledao.entity.Goods; 5 | import com.ledao.mapper.GoodsMapper; 6 | import com.ledao.service.GoodsService; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-01 18:07 15 | */ 16 | @Service("goodsService") 17 | public class GoodsServiceImpl extends ServiceImpl implements GoodsService { 18 | 19 | @Resource 20 | private GoodsMapper goodsMapper; 21 | 22 | @Override 23 | public Goods findById(Integer id) { 24 | return goodsMapper.findById(id); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/service/impl/MiaoShaGoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.mapper.MiaoShaGoodsMapper; 7 | import com.ledao.service.MiaoShaGoodsService; 8 | import com.ledao.util.RedisUtil; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * @author LeDao 16 | * @company 17 | * @create 2022-04-01 22:04 18 | */ 19 | @Service("miaoShaGoodsService") 20 | public class MiaoShaGoodsServiceImpl extends ServiceImpl implements MiaoShaGoodsService { 21 | 22 | @Resource 23 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 24 | 25 | @Override 26 | public List listAllNow() { 27 | return miaoShaGoodsMapper.listAllNow(); 28 | } 29 | 30 | @Override 31 | public MiaoShaGoods findById(Integer id) { 32 | Gson gson = new Gson(); 33 | String key = "miaoShaGoods_" + id; 34 | MiaoShaGoods miaoShaGoods; 35 | //当这个秒杀商品在Redis中存在时 36 | if (RedisUtil.existKey(key)) { 37 | miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 38 | } else { 39 | miaoShaGoods = miaoShaGoodsMapper.findById(id); 40 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 41 | //获取秒杀时长 42 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 43 | //设置过期时间 44 | RedisUtil.setKeyTime(key, time); 45 | } 46 | return miaoShaGoods; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/java/com/ledao/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.entity.Order; 7 | import com.ledao.mapper.GoodsMapper; 8 | import com.ledao.mapper.MiaoShaGoodsMapper; 9 | import com.ledao.mapper.OrderMapper; 10 | import com.ledao.service.OrderService; 11 | import com.ledao.util.RedisUtil; 12 | import org.springframework.stereotype.Service; 13 | import org.springframework.transaction.annotation.Transactional; 14 | 15 | import javax.annotation.Resource; 16 | import java.util.List; 17 | import java.util.Map; 18 | 19 | /** 20 | * @author LeDao 21 | * @company 22 | * @create 2022-04-02 22:40 23 | */ 24 | @Service("orderService") 25 | public class OrderServiceImpl extends ServiceImpl implements OrderService { 26 | 27 | @Resource 28 | private OrderMapper orderMapper; 29 | 30 | @Resource 31 | private GoodsMapper goodsMapper; 32 | 33 | @Resource 34 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 35 | 36 | @Override 37 | public List list(Map map) { 38 | return orderMapper.list(map); 39 | } 40 | 41 | @Override 42 | @Transactional(rollbackFor = {Exception.class}) 43 | public int add(Order order) { 44 | miaoShaGoodsMapper.reduceStock(order.getMiaoShaGoodsId()); 45 | goodsMapper.reduceStock(order.getGoodsId()); 46 | int result = orderMapper.add(order); 47 | Gson gson = new Gson(); 48 | String key = "miaoShaGoods_" + order.getMiaoShaGoodsId(); 49 | MiaoShaGoods miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 50 | miaoShaGoods.setStock(miaoShaGoods.getStock() - 1); 51 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 52 | //获取秒杀时长 53 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 54 | //设置过期时间 55 | RedisUtil.setKeyTime(key, time); 56 | return result; 57 | } 58 | 59 | @Override 60 | public int update(Order order) { 61 | return orderMapper.updateById(order); 62 | } 63 | 64 | @Override 65 | public Order findById(Integer id) { 66 | return orderMapper.selectById(id); 67 | } 68 | 69 | @Override 70 | public Order findByUserIdAndMiaoShaGoodsId(Map map) { 71 | return orderMapper.findByUserIdAndMiaoShaGoodsId(map); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/miaosha-order2/src/main/resources/application.yml -------------------------------------------------------------------------------- /miaosha-order2/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #应用名称,可省略 2 | spring.application.name=miaosha-order2 3 | #Nacos的IP地址和端口号 4 | spring.cloud.nacos.config.server-addr=192.168.0.141:8848 5 | #Nacos配置文件所在命名空间id 6 | spring.cloud.nacos.config.namespace=8b2d6583-c0a0-43bd-a2a8-b215eba8c70e 7 | #Nacos配置文件所在组名 8 | #spring.cloud.nacos.config.group=miaosha-user 9 | #要读取的配置文件名称 10 | #spring.cloud.nacos.config.name=nacos_config.properties 11 | 12 | #加载mysql.yml的配置 13 | spring.cloud.nacos.config.extension-configs[0].dataId=mysql.yml 14 | spring.cloud.nacos.config.extension-configs[0].group=miaosha-common 15 | spring.cloud.nacos.config.extension-configs[0].refresh=true 16 | 17 | #加载jackson.yml的配置 18 | spring.cloud.nacos.config.extension-configs[1].dataId=jackson.yml 19 | spring.cloud.nacos.config.extension-configs[1].group=miaosha-common 20 | spring.cloud.nacos.config.extension-configs[1].refresh=true 21 | 22 | #加载redis.yml的配置 23 | spring.cloud.nacos.config.extension-configs[2].dataId=redis.yml 24 | spring.cloud.nacos.config.extension-configs[2].group=miaosha-common 25 | spring.cloud.nacos.config.extension-configs[2].refresh=true 26 | 27 | #加载mybatis-plus.yml的配置 28 | spring.cloud.nacos.config.extension-configs[3].dataId=mybatis-plus.yml 29 | spring.cloud.nacos.config.extension-configs[3].group=miaosha-common 30 | spring.cloud.nacos.config.extension-configs[3].refresh=true 31 | 32 | #加载spring-cloud.yml的配置 33 | spring.cloud.nacos.config.extension-configs[4].dataId=spring-cloud.yml 34 | spring.cloud.nacos.config.extension-configs[4].group=miaosha-order2 35 | spring.cloud.nacos.config.extension-configs[4].refresh=true 36 | 37 | #加载server.yml的配置 38 | spring.cloud.nacos.config.extension-configs[5].dataId=server.yml 39 | spring.cloud.nacos.config.extension-configs[5].group=miaosha-order2 40 | spring.cloud.nacos.config.extension-configs[5].refresh=true 41 | 42 | #加载rabbitmq.yml的配置 43 | spring.cloud.nacos.config.extension-configs[6].dataId=rabbitmq.yml 44 | spring.cloud.nacos.config.extension-configs[6].group=miaosha-common 45 | spring.cloud.nacos.config.extension-configs[6].refresh=true -------------------------------------------------------------------------------- /miaosha-order2/src/main/resources/mybatis/mapper/GoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | update t_goods 21 | set stock=stock - 1 22 | where id = #{id} 23 | 24 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/resources/mybatis/mapper/MiaoShaGoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | id, goodsId, price, stock, startTime, endTime 19 | 20 | 21 | 29 | 30 | 35 | 36 | 37 | update t_miaosha_goods 38 | set stock=stock - 1 39 | where id = #{id} 40 | and stock > 0; 41 | 42 | -------------------------------------------------------------------------------- /miaosha-order2/src/main/resources/mybatis/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | id, createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId 21 | 22 | 23 | 35 | 36 | 42 | 43 | 44 | insert into t_order (createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId) 45 | values (now(), #{goodsId}, #{payStatus}, #{num}, #{userId}, #{price}, #{miaoShaGoodsId}); 46 | 47 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-rabbitmq 13 | 14 | 15 | 16 | org.example 17 | miaosha-common 18 | 19 | 20 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/MiaoShaRabbitMQApplication.java: -------------------------------------------------------------------------------- 1 | package com.ledao; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-08 16:25 12 | */ 13 | @SpringBootApplication 14 | @EnableDiscoveryClient 15 | @MapperScan("com.ledao.mapper") 16 | public class MiaoShaRabbitMQApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(MiaoShaRabbitMQApplication.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/controller/RabbitMQController.java: -------------------------------------------------------------------------------- 1 | package com.ledao.controller; 2 | 3 | import com.ledao.rabbitmq.RabbitMQProducerService; 4 | import org.springframework.web.bind.annotation.CrossOrigin; 5 | import org.springframework.web.bind.annotation.RequestMapping; 6 | import org.springframework.web.bind.annotation.RestController; 7 | 8 | import javax.annotation.Resource; 9 | 10 | /** 11 | * @author LeDao 12 | * @company 13 | * @create 2022-04-08 16:30 14 | */ 15 | @RestController 16 | @RequestMapping("/rabbitmq") 17 | public class RabbitMQController { 18 | 19 | @Resource 20 | private RabbitMQProducerService rabbitMQProducerService; 21 | 22 | @RequestMapping("/sendInformation") 23 | public void sendInformation(String information) { 24 | rabbitMQProducerService.sendInformation(information); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/mapper/GoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Mapper接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 17:59 12 | */ 13 | public interface GoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | 23 | /** 24 | * 减秒杀商品的数量-1 25 | * 26 | * @param id 27 | * @return 28 | */ 29 | int reduceStock(Integer id); 30 | } -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/mapper/MiaoShaGoodsMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:31 12 | */ 13 | public interface MiaoShaGoodsMapper extends BaseMapper { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | 30 | /** 31 | * 减秒杀商品的数量-1 32 | * 33 | * @param id 34 | * @return 35 | */ 36 | int reduceStock(Integer id); 37 | } -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/mapper/OrderMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * 订单Mapper接口实体类 11 | * 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-02 22:34 15 | */ 16 | public interface OrderMapper extends BaseMapper { 17 | 18 | /** 19 | * 根据条件获取订单 20 | * 21 | * @param map 22 | * @return 23 | */ 24 | List list(Map map); 25 | 26 | /** 27 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 28 | * 29 | * @param map 30 | * @return 31 | */ 32 | Order findByUserIdAndMiaoShaGoodsId(Map map); 33 | 34 | /** 35 | * 添加订单 36 | * 37 | * @param order 38 | * @return 39 | */ 40 | int add(Order order); 41 | } -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/rabbitmq/RabbitMQConsumerService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.rabbitmq; 2 | 3 | /** 4 | * RabbitMQService消费者接口 5 | * 6 | * @author LeDao 7 | * @company 8 | * @create 2022-04-07 1:07 9 | */ 10 | public interface RabbitMQConsumerService { 11 | 12 | /** 13 | * 处理秒杀请求 14 | * 15 | * @param message 16 | */ 17 | void handleMiaoShaRequst(String message); 18 | 19 | /** 20 | * 监听队列接收delayed消息 21 | * 22 | * @param message 23 | */ 24 | void receiveMessageDelayed(String message); 25 | } 26 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/rabbitmq/RabbitMQProducerService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.rabbitmq; 2 | 3 | /** 4 | * RabbitMQService生产者接口 5 | * 6 | * @author LeDao 7 | * @company 8 | * @create 2022-04-07 0:57 9 | */ 10 | public interface RabbitMQProducerService { 11 | 12 | /** 13 | * 发送消息 14 | * 15 | * @param infotmation 16 | */ 17 | void sendInformation(String infotmation); 18 | 19 | /** 20 | * 发送延时消息 21 | * 22 | * @param message 消息内容 23 | * @param delayTime 延时时间,单位为毫秒 24 | */ 25 | void sendMessageDelayed(String message, Integer delayTime); 26 | } 27 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/rabbitmq/impl/RabbitMQConsumerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.rabbitmq.impl; 2 | 3 | import com.google.gson.Gson; 4 | import com.ledao.config.RabbitMQConfig; 5 | import com.ledao.entity.Goods; 6 | import com.ledao.entity.MiaoShaGoods; 7 | import com.ledao.entity.Order; 8 | import com.ledao.entity.vo.OrderVo; 9 | import com.ledao.rabbitmq.RabbitMQConsumerService; 10 | import com.ledao.service.GoodsService; 11 | import com.ledao.service.MiaoShaGoodsService; 12 | import com.ledao.service.OrderService; 13 | import com.ledao.util.RedisUtil; 14 | import org.springframework.amqp.rabbit.annotation.RabbitListener; 15 | import org.springframework.stereotype.Service; 16 | 17 | import javax.annotation.Resource; 18 | import java.util.HashMap; 19 | import java.util.Map; 20 | 21 | /** 22 | * RabbitMQService消费者接口实现类 23 | * 24 | * @author LeDao 25 | * @company 26 | * @create 2022-04-07 1:08 27 | */ 28 | @Service("rabbitMQConsumerService") 29 | public class RabbitMQConsumerServiceImpl implements RabbitMQConsumerService { 30 | 31 | @Resource 32 | private MiaoShaGoodsService miaoShaGoodsService; 33 | 34 | @Resource 35 | private GoodsService goodsService; 36 | 37 | @Resource 38 | private OrderService orderService; 39 | 40 | @Override 41 | @RabbitListener(queues = {RabbitMQConfig.DIRECT_QUEUE}) 42 | public void handleMiaoShaRequst(String message) { 43 | System.out.println(message + ": 消费者1"); 44 | Gson gson = new Gson(); 45 | OrderVo orderVo = gson.fromJson(message, OrderVo.class); 46 | Map map = new HashMap<>(16); 47 | map.put("userId", orderVo.getUserId()); 48 | map.put("miaoShaGoodsId", orderVo.getMiaoShaGoodsId()); 49 | MiaoShaGoods miaoShaGoods = miaoShaGoodsService.findById(orderVo.getMiaoShaGoodsId()); 50 | //判断秒杀商品的数量是否大于0,不大于0不可以秒杀 51 | if (miaoShaGoods.getStock() > 0) { 52 | //判断用户是否重复秒杀,已经秒杀过不能秒杀,即使订单因为30分钟未支付被取消了也不能重新秒杀 53 | if (orderService.findByUserIdAndMiaoShaGoodsId(map) == null) { 54 | Order order = new Order(); 55 | order.setGoodsId(orderVo.getGoodsId()); 56 | order.setUserId(orderVo.getUserId()); 57 | order.setPrice(orderVo.getPrice()); 58 | order.setMiaoShaGoodsId(orderVo.getMiaoShaGoodsId()); 59 | order.setPayStatus(0); 60 | order.setNum(1); 61 | orderService.add(order); 62 | } 63 | } 64 | } 65 | 66 | @Override 67 | @RabbitListener(queues = {RabbitMQConfig.DELAYED_QUEUE}) 68 | public void receiveMessageDelayed(String message) { 69 | int orderId = Integer.parseInt(message.split("_")[1]); 70 | Order order = orderService.findById(orderId); 71 | if (order.getPayStatus() == 0) { 72 | //将状态设置为已取消 73 | order.setPayStatus(2); 74 | orderService.update(order); 75 | //恢复商品的库存 76 | Goods goods = goodsService.findById(order.getGoodsId()); 77 | goods.setStock(goods.getStock() + order.getNum()); 78 | goodsService.update(goods); 79 | MiaoShaGoods miaoShaGoods = miaoShaGoodsService.findById(order.getMiaoShaGoodsId()); 80 | //如果秒杀时间还没过,释放秒杀商品库存 81 | if (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis() >= 0) { 82 | miaoShaGoods.setStock(miaoShaGoods.getStock() + order.getNum()); 83 | miaoShaGoodsService.update(miaoShaGoods); 84 | Gson gson = new Gson(); 85 | String key = "miaoShaGoods_" + order.getMiaoShaGoodsId(); 86 | miaoShaGoods.setStock(miaoShaGoods.getStock()); 87 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 88 | //获取秒杀时长 89 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 90 | //设置过期时间 91 | RedisUtil.setKeyTime(key, time); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/rabbitmq/impl/RabbitMQProducerServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.rabbitmq.impl; 2 | 3 | import com.ledao.config.RabbitMQConfig; 4 | import com.ledao.rabbitmq.RabbitMQProducerService; 5 | import org.springframework.amqp.core.AmqpTemplate; 6 | import org.springframework.stereotype.Service; 7 | 8 | import javax.annotation.Resource; 9 | 10 | /** 11 | * @author LeDao 12 | * @company 13 | * @create 2022-04-07 0:58 14 | */ 15 | @Service("rabbitMQProducerService") 16 | public class RabbitMQProducerServiceImpl implements RabbitMQProducerService { 17 | 18 | @Resource 19 | private AmqpTemplate amqpTemplate; 20 | 21 | @Override 22 | public void sendInformation(String infotmation) { 23 | amqpTemplate.convertAndSend(RabbitMQConfig.DIRECT_EXCHANGE, RabbitMQConfig.DIRECT_ROUTINGKEY, infotmation); 24 | } 25 | 26 | @Override 27 | public void sendMessageDelayed(String message, Integer delayTime) { 28 | amqpTemplate.convertAndSend(RabbitMQConfig.DELAYED_EXCHANGE, RabbitMQConfig.DELAYED_ROUTING_KEY, message, a -> { 29 | a.getMessageProperties().setDelay(delayTime); 30 | return a; 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/service/GoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Goods; 5 | 6 | /** 7 | * 商品Service接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 18:06 12 | */ 13 | public interface GoodsService extends IService { 14 | 15 | /** 16 | * 根据id查找用户 17 | * 18 | * @param id 19 | * @return 20 | */ 21 | Goods findById(Integer id); 22 | 23 | /** 24 | * 修改商品 25 | * 26 | * @param goods 27 | * @return 28 | */ 29 | int update(Goods goods); 30 | } 31 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/service/MiaoShaGoodsService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.MiaoShaGoods; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-01 22:02 12 | */ 13 | public interface MiaoShaGoodsService extends IService { 14 | 15 | /** 16 | * 获取正在秒杀的商品 17 | * 18 | * @return 19 | */ 20 | List listAllNow(); 21 | 22 | /** 23 | * 根据id查找 24 | * 25 | * @param id 26 | * @return 27 | */ 28 | MiaoShaGoods findById(Integer id); 29 | 30 | /** 31 | * 修改秒杀商品 32 | * 33 | * @param miaoShaGoods 34 | * @return 35 | */ 36 | int update(MiaoShaGoods miaoShaGoods); 37 | } 38 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/service/OrderService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.Order; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author LeDao 11 | * @company 12 | * @create 2022-04-02 22:39 13 | */ 14 | public interface OrderService extends IService { 15 | 16 | /** 17 | * 根据条件获取订单 18 | * 19 | * @param map 20 | * @return 21 | */ 22 | List list(Map map); 23 | 24 | /** 25 | * 添加订单 26 | * 27 | * @param order 28 | * @return 29 | */ 30 | int add(Order order); 31 | 32 | /** 33 | * 修改订单 34 | * 35 | * @param order 36 | * @return 37 | */ 38 | int update(Order order); 39 | 40 | /** 41 | * 根据id查找订单 42 | * 43 | * @param id 44 | * @return 45 | */ 46 | Order findById(Integer id); 47 | 48 | /** 49 | * 根据用户id和秒杀商品id获取订单(用于判断用户是否重复秒杀) 50 | * 51 | * @param map 52 | * @return 53 | */ 54 | Order findByUserIdAndMiaoShaGoodsId(Map map); 55 | } 56 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/service/impl/GoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.ledao.entity.Goods; 5 | import com.ledao.mapper.GoodsMapper; 6 | import com.ledao.service.GoodsService; 7 | import org.springframework.stereotype.Service; 8 | 9 | import javax.annotation.Resource; 10 | 11 | /** 12 | * @author LeDao 13 | * @company 14 | * @create 2022-04-01 18:07 15 | */ 16 | @Service("goodsService") 17 | public class GoodsServiceImpl extends ServiceImpl implements GoodsService { 18 | 19 | @Resource 20 | private GoodsMapper goodsMapper; 21 | 22 | @Override 23 | public Goods findById(Integer id) { 24 | return goodsMapper.findById(id); 25 | } 26 | 27 | @Override 28 | public int update(Goods goods) { 29 | return goodsMapper.updateById(goods); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/service/impl/MiaoShaGoodsServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.mapper.MiaoShaGoodsMapper; 7 | import com.ledao.service.MiaoShaGoodsService; 8 | import com.ledao.util.RedisUtil; 9 | import org.springframework.stereotype.Service; 10 | 11 | import javax.annotation.Resource; 12 | import java.util.List; 13 | 14 | /** 15 | * @author LeDao 16 | * @company 17 | * @create 2022-04-01 22:04 18 | */ 19 | @Service("miaoShaGoodsService") 20 | public class MiaoShaGoodsServiceImpl extends ServiceImpl implements MiaoShaGoodsService { 21 | 22 | @Resource 23 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 24 | 25 | @Override 26 | public List listAllNow() { 27 | return miaoShaGoodsMapper.listAllNow(); 28 | } 29 | 30 | @Override 31 | public MiaoShaGoods findById(Integer id) { 32 | Gson gson = new Gson(); 33 | String key = "miaoShaGoods_" + id; 34 | MiaoShaGoods miaoShaGoods; 35 | //当这个秒杀商品在Redis中存在时 36 | if (RedisUtil.existKey(key)) { 37 | miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 38 | } else { 39 | miaoShaGoods = miaoShaGoodsMapper.findById(id); 40 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 41 | //获取秒杀时长 42 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 43 | //设置过期时间 44 | RedisUtil.setKeyTime(key, time); 45 | } 46 | return miaoShaGoods; 47 | } 48 | 49 | @Override 50 | public int update(MiaoShaGoods miaoShaGoods) { 51 | return miaoShaGoodsMapper.updateById(miaoShaGoods); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/java/com/ledao/service/impl/OrderServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 4 | import com.google.gson.Gson; 5 | import com.ledao.entity.MiaoShaGoods; 6 | import com.ledao.entity.Order; 7 | import com.ledao.mapper.GoodsMapper; 8 | import com.ledao.mapper.MiaoShaGoodsMapper; 9 | import com.ledao.mapper.OrderMapper; 10 | import com.ledao.rabbitmq.RabbitMQProducerService; 11 | import com.ledao.service.OrderService; 12 | import com.ledao.util.RedisUtil; 13 | import org.springframework.stereotype.Service; 14 | import org.springframework.transaction.annotation.Transactional; 15 | 16 | import javax.annotation.Resource; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | /** 21 | * @author LeDao 22 | * @company 23 | * @create 2022-04-02 22:40 24 | */ 25 | @Service("orderService") 26 | public class OrderServiceImpl extends ServiceImpl implements OrderService { 27 | 28 | @Resource 29 | private OrderMapper orderMapper; 30 | 31 | @Resource 32 | private GoodsMapper goodsMapper; 33 | 34 | @Resource 35 | private MiaoShaGoodsMapper miaoShaGoodsMapper; 36 | 37 | @Resource 38 | private RabbitMQProducerService rabbitMQProducerService; 39 | 40 | @Override 41 | public List list(Map map) { 42 | return orderMapper.list(map); 43 | } 44 | 45 | @Override 46 | @Transactional(rollbackFor = {Exception.class}) 47 | public int add(Order order) { 48 | //秒杀商品库存-1 49 | miaoShaGoodsMapper.reduceStock(order.getMiaoShaGoodsId()); 50 | //秒杀商品对应商品库存-1 51 | goodsMapper.reduceStock(order.getGoodsId()); 52 | int result = orderMapper.add(order); 53 | //将订单号放进延时消息队列 54 | Integer orderId = order.getId(); 55 | rabbitMQProducerService.sendMessageDelayed("order_" + orderId, 1000 * 60 * 30); 56 | Gson gson = new Gson(); 57 | String key = "miaoShaGoods_" + order.getMiaoShaGoodsId(); 58 | MiaoShaGoods miaoShaGoods = gson.fromJson(RedisUtil.getKeyValue(key), MiaoShaGoods.class); 59 | //Redis的秒杀商品剩余数量-1 60 | miaoShaGoods.setStock(miaoShaGoods.getStock() - 1); 61 | RedisUtil.setKey(key, gson.toJson(miaoShaGoods)); 62 | //获取秒杀时长 63 | long time = (miaoShaGoods.getEndTime().getTime() - System.currentTimeMillis()) / 1000; 64 | //设置过期时间 65 | RedisUtil.setKeyTime(key, time); 66 | return result; 67 | } 68 | 69 | @Override 70 | public int update(Order order) { 71 | return orderMapper.updateById(order); 72 | } 73 | 74 | @Override 75 | public Order findById(Integer id) { 76 | return orderMapper.selectById(id); 77 | } 78 | 79 | @Override 80 | public Order findByUserIdAndMiaoShaGoodsId(Map map) { 81 | return orderMapper.findByUserIdAndMiaoShaGoodsId(map); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/miaosha-rabbitmq/src/main/resources/application.yml -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #应用名称,可省略 2 | spring.application.name=miaosha-rabbitmq 3 | #Nacos的IP地址和端口号 4 | spring.cloud.nacos.config.server-addr=192.168.0.141:8848 5 | #Nacos配置文件所在命名空间id 6 | spring.cloud.nacos.config.namespace=8b2d6583-c0a0-43bd-a2a8-b215eba8c70e 7 | #Nacos配置文件所在组名 8 | #spring.cloud.nacos.config.group=miaosha-user 9 | #要读取的配置文件名称 10 | #spring.cloud.nacos.config.name=nacos_config.properties 11 | 12 | #加载mysql.yml的配置 13 | spring.cloud.nacos.config.extension-configs[0].dataId=mysql.yml 14 | spring.cloud.nacos.config.extension-configs[0].group=miaosha-common 15 | spring.cloud.nacos.config.extension-configs[0].refresh=true 16 | 17 | #加载jackson.yml的配置 18 | spring.cloud.nacos.config.extension-configs[1].dataId=jackson.yml 19 | spring.cloud.nacos.config.extension-configs[1].group=miaosha-common 20 | spring.cloud.nacos.config.extension-configs[1].refresh=true 21 | 22 | #加载redis.yml的配置 23 | spring.cloud.nacos.config.extension-configs[2].dataId=redis.yml 24 | spring.cloud.nacos.config.extension-configs[2].group=miaosha-common 25 | spring.cloud.nacos.config.extension-configs[2].refresh=true 26 | 27 | #加载mybatis-plus.yml的配置 28 | spring.cloud.nacos.config.extension-configs[3].dataId=mybatis-plus.yml 29 | spring.cloud.nacos.config.extension-configs[3].group=miaosha-common 30 | spring.cloud.nacos.config.extension-configs[3].refresh=true 31 | 32 | #加载spring-cloud.yml的配置 33 | spring.cloud.nacos.config.extension-configs[4].dataId=spring-cloud.yml 34 | spring.cloud.nacos.config.extension-configs[4].group=miaosha-rabbitmq 35 | spring.cloud.nacos.config.extension-configs[4].refresh=true 36 | 37 | #加载server.yml的配置 38 | spring.cloud.nacos.config.extension-configs[5].dataId=server.yml 39 | spring.cloud.nacos.config.extension-configs[5].group=miaosha-rabbitmq 40 | spring.cloud.nacos.config.extension-configs[5].refresh=true 41 | 42 | #加载rabbitmq.yml的配置 43 | spring.cloud.nacos.config.extension-configs[6].dataId=rabbitmq.yml 44 | spring.cloud.nacos.config.extension-configs[6].group=miaosha-common 45 | spring.cloud.nacos.config.extension-configs[6].refresh=true -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/resources/mybatis/mapper/GoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | update t_goods 21 | set stock=stock - 1 22 | where id = #{id} 23 | 24 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/resources/mybatis/mapper/MiaoShaGoodsMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 15 | 16 | 17 | 18 | id, goodsId, price, stock, startTime, endTime 19 | 20 | 21 | 29 | 30 | 35 | 36 | 37 | update t_miaosha_goods 38 | set stock=stock - 1 39 | where id = #{id} 40 | and stock > 0; 41 | 42 | -------------------------------------------------------------------------------- /miaosha-rabbitmq/src/main/resources/mybatis/mapper/OrderMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | id, createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId 21 | 22 | 23 | 35 | 36 | 42 | 43 | 44 | insert into t_order (createTime, goodsId, payStatus, num, userId, price, miaoShaGoodsId) 45 | values (now(), #{goodsId}, #{payStatus}, #{num}, #{userId}, #{price}, #{miaoShaGoodsId}); 46 | 47 | -------------------------------------------------------------------------------- /miaosha-user/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | miaosha-admin 7 | org.example 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | miaosha-user 13 | 14 | 15 | 16 | org.example 17 | miaosha-common 18 | 19 | 20 | -------------------------------------------------------------------------------- /miaosha-user/src/main/java/com/ledao/MiaoShaUserApplication.java: -------------------------------------------------------------------------------- 1 | package com.ledao; 2 | 3 | import org.mybatis.spring.annotation.MapperScan; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 7 | 8 | /** 9 | * @author LeDao 10 | * @company 11 | * @create 2022-04-07 7:37 12 | */ 13 | @SpringBootApplication 14 | @EnableDiscoveryClient 15 | @MapperScan("com.ledao.mapper") 16 | public class MiaoShaUserApplication { 17 | 18 | public static void main(String[] args) { 19 | SpringApplication.run(MiaoShaUserApplication.class, args); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /miaosha-user/src/main/java/com/ledao/controller/TokenController.java: -------------------------------------------------------------------------------- 1 | package com.ledao.controller; 2 | 3 | import com.ledao.util.RedisUtil; 4 | import org.springframework.web.bind.annotation.CrossOrigin; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.RequestMapping; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | 11 | /** 12 | * Token控制层 13 | * 14 | * @author LeDao 15 | * @company 16 | * @create 2022-03-30 3:20 17 | */ 18 | @RestController 19 | @RequestMapping("/user/token") 20 | public class TokenController { 21 | 22 | /** 23 | * 刷新token保持登录状态 24 | * 25 | * @param request 26 | * @return 27 | */ 28 | @GetMapping("/refreshToken") 29 | public boolean refreshToken(HttpServletRequest request) { 30 | //从前端获取token 31 | String token = request.getHeader("token"); 32 | //将token的过期时间重新设置为30分钟 33 | RedisUtil.setKeyTime(token, (long) (30 * 60)); 34 | return RedisUtil.existKey(token); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /miaosha-user/src/main/java/com/ledao/controller/UserContrller.java: -------------------------------------------------------------------------------- 1 | package com.ledao.controller; 2 | 3 | import cn.hutool.core.io.file.FileAppender; 4 | import com.ledao.entity.User; 5 | import com.ledao.entity.vo.UserVo; 6 | import com.ledao.service.UserService; 7 | import com.ledao.util.Md5Util; 8 | import com.ledao.util.RedisUtil; 9 | import com.ledao.util.UUIDUtil; 10 | import org.springframework.beans.factory.annotation.Autowired; 11 | import org.springframework.web.bind.annotation.RequestMapping; 12 | import org.springframework.web.bind.annotation.RestController; 13 | 14 | import javax.servlet.http.HttpServletRequest; 15 | import java.io.File; 16 | import java.util.Date; 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | 20 | /** 21 | * @author LeDao 22 | * @company 23 | * @create 2022-03-29 16:50 24 | */ 25 | @RestController 26 | @RequestMapping("/user") 27 | public class UserContrller { 28 | 29 | private UserService userService; 30 | 31 | @Autowired 32 | public void setUserService(UserService userService) { 33 | this.userService = userService; 34 | } 35 | 36 | /** 37 | * 登录 38 | * 39 | * @param userVo 40 | * @return 41 | */ 42 | @RequestMapping("/login") 43 | public Map login(UserVo userVo) { 44 | Map resultMap = new HashMap<>(16); 45 | User user = userService.findByUserName(userVo.getUserName()); 46 | if (user != null && user.getPassword().equals(Md5Util.backMd5(userVo.getPassword()))) { 47 | String token = "tk" + UUIDUtil.genUuid(); 48 | RedisUtil.setKey(token, RedisUtil.entityToJson(user)); 49 | RedisUtil.setKeyTime(token, (long) (30 * 60)); 50 | resultMap.put("user", user); 51 | resultMap.put("token", token); 52 | return resultMap; 53 | } 54 | return null; 55 | } 56 | 57 | /** 58 | * 用户注册时检验用户名是否已经存在于数据库中 59 | * 60 | * @param userVo 61 | * @return 62 | */ 63 | @RequestMapping("/checkUserName") 64 | public boolean checkUserName(UserVo userVo) { 65 | User user = userService.findByUserName(userVo.getUserName()); 66 | return user == null; 67 | } 68 | 69 | /** 70 | * 用户注册时检验用户名是否已经存在于数据库中 71 | * 72 | * @param userVo 73 | * @return 74 | */ 75 | @RequestMapping("/checkPhone") 76 | public boolean checkPhone(UserVo userVo) { 77 | User user = userService.findByPhone(userVo.getPhone()); 78 | return user == null; 79 | } 80 | 81 | /** 82 | * 用户注册 83 | * 84 | * @param user 85 | * @return 86 | */ 87 | @RequestMapping("/register") 88 | public boolean register(User user) { 89 | user.setRegisterDate(new Date()); 90 | user.setPassword(Md5Util.backMd5(user.getPassword())); 91 | int key = userService.add(user); 92 | return key > 0; 93 | } 94 | 95 | /** 96 | * 注销 97 | * 98 | * @param request 99 | * @return 100 | */ 101 | @RequestMapping("/logout") 102 | public boolean logout(HttpServletRequest request) { 103 | //从前端获取token 104 | String token = request.getHeader("token"); 105 | return RedisUtil.delKey(token); 106 | } 107 | 108 | @RequestMapping("/loginAuto") 109 | public void loginAuto(){ 110 | File file = new File("C:\\Users\\LeDao\\Desktop\\1.txt"); 111 | for (int i = 1; i <= 1000; i++) { 112 | FileAppender fileAppender = new FileAppender(file, 16, true); 113 | User user = userService.findByUserName("user" + i); 114 | String token = "tk" + UUIDUtil.genUuid(); 115 | RedisUtil.setKey(token, RedisUtil.entityToJson(user)); 116 | RedisUtil.setKeyTime(token, (long) (60 * 60 * 24)); 117 | fileAppender.append(user.getId() + "," + token); 118 | fileAppender.flush(); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /miaosha-user/src/main/java/com/ledao/mapper/UserMapper.java: -------------------------------------------------------------------------------- 1 | package com.ledao.mapper; 2 | 3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; 4 | import com.ledao.entity.User; 5 | 6 | /** 7 | * 用户Mapper接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-03-29 16:44 12 | */ 13 | public interface UserMapper extends BaseMapper { 14 | } 15 | -------------------------------------------------------------------------------- /miaosha-user/src/main/java/com/ledao/service/UserService.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service; 2 | 3 | import com.baomidou.mybatisplus.extension.service.IService; 4 | import com.ledao.entity.User; 5 | 6 | /** 7 | * 用户Service接口 8 | * 9 | * @author LeDao 10 | * @company 11 | * @create 2022-03-29 16:46 12 | */ 13 | public interface UserService extends IService { 14 | 15 | /** 16 | * 根据用户名查找用户 17 | * 18 | * @param userName 19 | * @return 20 | */ 21 | User findByUserName(String userName); 22 | 23 | /** 24 | * 根据手机号查找用户 25 | * 26 | * @param phone 27 | * @return 28 | */ 29 | User findByPhone(String phone); 30 | 31 | /** 32 | * 添加用户 33 | * 34 | * @param user 35 | * @return 36 | */ 37 | Integer add(User user); 38 | } 39 | -------------------------------------------------------------------------------- /miaosha-user/src/main/java/com/ledao/service/impl/UserServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.ledao.service.impl; 2 | 3 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 5 | import com.ledao.entity.User; 6 | import com.ledao.mapper.UserMapper; 7 | import com.ledao.service.UserService; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | /** 12 | * 用户Service接口实现类 13 | * 14 | * @author LeDao 15 | * @company 16 | * @create 2022-03-29 16:48 17 | */ 18 | @Service("userService") 19 | public class UserServiceImpl extends ServiceImpl implements UserService { 20 | 21 | private UserMapper userMapper; 22 | 23 | @Autowired 24 | public void setUserMapper(UserMapper userMapper) { 25 | this.userMapper = userMapper; 26 | } 27 | 28 | @Override 29 | public User findByUserName(String userName) { 30 | QueryWrapper userQueryWrapper = new QueryWrapper<>(); 31 | userQueryWrapper.eq("userName", userName); 32 | return userMapper.selectOne(userQueryWrapper); 33 | } 34 | 35 | @Override 36 | public User findByPhone(String phone) { 37 | QueryWrapper userQueryWrapper = new QueryWrapper<>(); 38 | userQueryWrapper.eq("phone", phone); 39 | return userMapper.selectOne(userQueryWrapper); 40 | } 41 | 42 | @Override 43 | public Integer add(User user) { 44 | return userMapper.insert(user); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /miaosha-user/src/main/resources/application.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/a6678696/miaosha-admin/ed2784503c0fe767161b3b83adec2e42392b2d34/miaosha-user/src/main/resources/application.yml -------------------------------------------------------------------------------- /miaosha-user/src/main/resources/bootstrap.properties: -------------------------------------------------------------------------------- 1 | #应用名称,可省略 2 | spring.application.name=miaosha-user 3 | #Nacos的IP地址和端口号 4 | spring.cloud.nacos.config.server-addr=192.168.0.141:8848 5 | #Nacos配置文件所在命名空间id 6 | spring.cloud.nacos.config.namespace=8b2d6583-c0a0-43bd-a2a8-b215eba8c70e 7 | #Nacos配置文件所在组名 8 | #spring.cloud.nacos.config.group=miaosha-user 9 | #要读取的配置文件名称 10 | #spring.cloud.nacos.config.name=nacos_config.properties 11 | 12 | #加载server.yml的配置 13 | spring.cloud.nacos.config.extension-configs[0].dataId=server.yml 14 | spring.cloud.nacos.config.extension-configs[0].group=miaosha-user 15 | spring.cloud.nacos.config.extension-configs[0].refresh=true 16 | 17 | #加载mysql.yml的配置 18 | spring.cloud.nacos.config.extension-configs[1].dataId=mysql.yml 19 | spring.cloud.nacos.config.extension-configs[1].group=miaosha-common 20 | spring.cloud.nacos.config.extension-configs[1].refresh=true 21 | 22 | #加载jackson.yml的配置 23 | spring.cloud.nacos.config.extension-configs[2].dataId=jackson.yml 24 | spring.cloud.nacos.config.extension-configs[2].group=miaosha-common 25 | spring.cloud.nacos.config.extension-configs[2].refresh=true 26 | 27 | #加载redis.yml的配置 28 | spring.cloud.nacos.config.extension-configs[3].dataId=redis.yml 29 | spring.cloud.nacos.config.extension-configs[3].group=miaosha-common 30 | spring.cloud.nacos.config.extension-configs[3].refresh=true 31 | 32 | #加载mybatis-plus.yml的配置 33 | spring.cloud.nacos.config.extension-configs[4].dataId=mybatis-plus.yml 34 | spring.cloud.nacos.config.extension-configs[4].group=miaosha-common 35 | spring.cloud.nacos.config.extension-configs[4].refresh=true 36 | 37 | #加载spring-cloud.yml的配置 38 | spring.cloud.nacos.config.extension-configs[5].dataId=spring-cloud.yml 39 | spring.cloud.nacos.config.extension-configs[5].group=miaosha-user 40 | spring.cloud.nacos.config.extension-configs[5].refresh=true -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | org.example 8 | miaosha-admin 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | miaosha-common 13 | miaosha-user 14 | miaosha-goods 15 | miaosha-order1 16 | miaosha-order2 17 | miaosha-rabbitmq 18 | miaosha-gateway 19 | 20 | 21 | 22 | UTF-8 23 | 1.8 24 | 1.8 25 | Hoxton.SR9 26 | 2.3.2.RELEASE 27 | 2.2.6.RELEASE 28 | 3.5.1 29 | 1.2.8 30 | 5.8.0.M2 31 | 2.9.0 32 | 1.0-SNAPSHOT 33 | 34 | 35 | 36 | 37 | 38 | org.springframework.cloud 39 | spring-cloud-dependencies 40 | ${spring-cloud.version} 41 | pom 42 | import 43 | 44 | 45 | org.springframework.boot 46 | spring-boot-dependencies 47 | ${springboot.version} 48 | pom 49 | import 50 | 51 | 52 | com.alibaba.cloud 53 | spring-cloud-alibaba-dependencies 54 | ${springcloudalibaba.version} 55 | pom 56 | import 57 | 58 | 59 | com.baomidou 60 | mybatis-plus-boot-starter 61 | ${mybatis-plus.version} 62 | 63 | 64 | com.alibaba 65 | druid 66 | ${druid.version} 67 | 68 | 69 | 70 | cn.hutool 71 | hutool-all 72 | ${hutool.version} 73 | 74 | 75 | org.example 76 | miaosha-common 77 | ${miaosha-common.version} 78 | 79 | 80 | 81 | com.google.code.gson 82 | gson 83 | ${gson.version} 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | org.springframework.boot 92 | spring-boot-maven-plugin 93 | 94 | 95 | 96 | --------------------------------------------------------------------------------