(十)Alian 的 Spring Cloud 库存系统
目录
- 一、背景
- 二、数据库
- 1.1、创建数据库
- 1.2、创建表
- 1.3、初始数据
- 1.4、配置中心数据
- 三、domain-stock
- 3.1、实体类
- 3.2、持久层
- 3.3、打包到私服
- 四、maven依赖
- 五、编码
- 5.1、controller
- 5.2、service
- 5.3、dto
- 六、配置
- 6.1、主类
- 6.2、bootstrap.properties
- 6.3、ebean.properties
- 6.4、build.properties
- 6.5、dozerMapping.xml
- 七、验证
一、背景
既然我们已经搭建了配置中心了,也实现了自定义的 db starter 和公共的 API starter ,现在我们就把它整合到一起,完成一个库存系统的设计,你就可以感受到简单了。
二、数据库
1.1、创建数据库
#创建库
create databases stock;
CREATE DATABASE IF NOT EXISTS stock
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_general_ci;
字符集推荐使用: utf8mb4
1.2、创建表
#创建一个库存表
CREATE TABLE `tb_goods_stock` (`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',`goods_id` int unsigned NOT NULL DEFAULT '0' COMMENT '商品id',`inventory` int unsigned NOT NULL DEFAULT '0' COMMENT '库存',`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间',PRIMARY KEY (`id`),KEY `idx_goods_id` (`goods_id`),KEY `idx_create_time` (`create_time`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COMMENT='库存表';
1.3、初始数据
#插入商品编号为10001和10002的库存分别为100,200
insert into tb_goods_stock(goods_id,inventory) values(10001,100);
insert into tb_goods_stock(goods_id,inventory) values(10002,200);
1.4、配置中心数据
三、domain-stock
3.1、实体类
GoodsStock.java
package cn.alian.domain.stock.domain;import lombok.Getter;
import lombok.Setter;import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;@Setter
@Getter
@Entity
@Table(name = "tb_goods_stock")
public class GoodsStock implements Serializable {private static final long serialVersionUID = 1L;/*** 主键*/@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", insertable = false, nullable = false)private Integer id;/*** 商品id*/@Column(name = "goods_id", nullable = false)private int goodsId;/*** 库存数量*/@Column(name = "inventory", nullable = false)private int inventory;/*** 创建时间*/@Column(name = "create_time", nullable = false, insertable = false, updatable = false)private LocalDateTime createTime;/*** 更新时间*/@Column(name = "update_time", nullable = false, insertable = false, updatable = false)private LocalDateTime updateTime;}
3.2、持久层
GoodsStockRepository.java
package cn.alian.domain.stock.repository;import cn.alian.domain.stock.domain.GoodsStock;
import org.springframework.data.ebean.repository.EbeanRepository;
import org.springframework.stereotype.Repository;@Repository
public interface GoodsStockRepository extends EbeanRepository<GoodsStock, Integer> {}
3.3、打包到私服
通过maven自动生成Ebean QueryBean,之前的文章说了,就不再列出了,具体可以参考:(四)Alian 的 Spring Cloud Ebean自动生成Query Bean
四、maven依赖
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>cn.alian.microservice</groupId><artifactId>parent</artifactId><version>1.0.0-SNAPSHOT</version></parent><groupId>cn.alian.mall</groupId><artifactId>stock</artifactId><version>1.0.0-SNAPSHOT</version><name>stock</name><description>库存服务</description><dependencies><!--自定义的db starter--><dependency><groupId>cn.alian.microservice</groupId><artifactId>common-db</artifactId><version>1.0.0-SNAPSHOT</version></dependency><!--自定义的API starter--><dependency><groupId>cn.alian.microservice</groupId><artifactId>common-api</artifactId><version>1.0.0-SNAPSHOT</version></dependency><!--domain Query Bean--><dependency><groupId>cn.alian.domain</groupId><artifactId>domain-stock</artifactId><version>1.0.0-SNAPSHOT</version></dependency><!--配置中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><!--注册中心--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><!--sql日志输出--><dependency><groupId>com.googlecode.log4jdbc</groupId><artifactId>log4jdbc</artifactId></dependency><!--mysql驱动--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency></dependencies><repositories><repository><id>nexus-repos</id><name>Team Nexus Repository</name><url>http://192.168.0.210:8081/nexus/content/groups/public</url></repository><repository><id>nexus-repos-snapshots</id><name>Team Nexus Repository Snapshots</name><url>http://192.168.0.210:8081/nexus/content/groups/public-snapshots</url></repository><repository><id>aliyun-maven-repo</id><url>https://maven.aliyun.com/repository/public</url></repository></repositories><pluginRepositories><pluginRepository><id>nexus-repos</id><name>Team Nexus Repository</name><url>http://192.168.0.210:8081/nexus/content/groups/public</url></pluginRepository><pluginRepository><id>nexus-repos-snapshots</id><name>Team Nexus Repository Snapshots</name><url>http://192.168.0.210:8081/nexus/content/groups/public-snapshots</url></pluginRepository></pluginRepositories></project>
五、编码
5.1、controller
StockController.java
package cn.alian.mall.stock.controller;import cn.alian.mall.stock.dto.DeductInventoryRequestDto;
import cn.alian.mall.stock.dto.DeductInventoryResponseDto;
import cn.alian.mall.stock.service.StockService;
import cn.alian.microservice.common.dto.ApiResponseDto;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.validation.Valid;@Slf4j
@Validated
@RestController
@RequestMapping({"/api/v1/stock"})
@Api(description = "库存相关接口")
public class StockController {@Autowiredprivate StockService stockService;@ApiOperation("扣减商品库存")@PostMapping("/deductInventory")public ApiResponseDto<DeductInventoryResponseDto> request(@ApiParam @Valid @RequestBody DeductInventoryRequestDto dto) {log.info("扣减商品库存请求信息:{}", JSON.toJSONString(dto));DeductInventoryResponseDto responseDto = new DeductInventoryResponseDto();Pair<Boolean, String> pair = stockService.deductInventory(dto.getGoodsId(), dto.getNum());log.info("扣减库存返回的结果:{}", pair.getRight());responseDto.setResultCode(pair.getLeft() ? "0000" : "9999");responseDto.setMessage(pair.getRight());return ApiResponseDto.success(responseDto);}
}
5.2、service
StockService.java
package cn.alian.mall.stock.service;import io.ebean.DB;
import io.ebean.EbeanServer;
import io.ebean.SqlUpdate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Slf4j
@Service
public class StockService {@Autowiredprivate EbeanServer ebeanServer;public Pair<Boolean, String> deductInventory(int goodsId, int num) {String sql = "update tb_goods_stock set inventory=inventory - " + num + " where goods_id =" + goodsId;SqlUpdate sqlUpdate = DB.sqlUpdate(sql);int execute = sqlUpdate.execute();log.info("商品【{}】库存操作完成", goodsId);if (execute != 0) {return Pair.of(true, "库存扣减成功");}return Pair.of(false, "库存扣减失败");}}
5.3、dto
DeductInventoryRequestDto.java
package cn.alian.mall.stock.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.validation.constraints.NotNull;@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@ApiModel(description = "扣减库存请求信息")
public class DeductInventoryRequestDto {@NotNull@ApiModelProperty("订单id")private Integer orderId;@NotNull@ApiModelProperty("商品id")private Integer goodsId;@NotNull@ApiModelProperty("数量")private Integer num = 1;}
DeductInventoryResponseDto.java
package cn.alian.mall.stock.dto;import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;import javax.validation.constraints.NotNull;@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder(toBuilder = true)
@ApiModel(description = "扣减库存返回信息")
public class DeductInventoryResponseDto {@NotNull@ApiModelProperty("结果码")private String resultCode;@NotNull@ApiModelProperty("结果说明")private String message;}
六、配置
6.1、主类
StockApplication.java
package cn.alian.mall.stock;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@EnableDiscoveryClient
@SpringBootApplication
public class StockApplication {public static void main(String[] args) {SpringApplication.run(StockApplication.class, args);}}
6.2、bootstrap.properties
bootstrap.properties
#应用名
spring.application.name=stock
#开发环境
spring.profiles.active=dev
#配置标签(根据配置中心,本文全是采用master)
spring.cloud.config.label=master
#配置中心地址,多个用逗号分隔
spring.cloud.config.uri=http://10.130.3.222:6666
#设置为true时,如果服务无法连接到配置中心服务器,则服务启动失败
spring.cloud.config.fail-fast=true
#日志配置,通过配置中心获取
logging.config=${spring.cloud.config.uri}/logback/${spring.application.name}.xml
6.3、ebean.properties
ebean.properties
ebean.packages=cn.alian.domain.stock
6.4、build.properties
build.properties
build.groupId=${pom.groupId}
build.artifactId=${pom.artifactId}
build.version=${pom.version}
# 生成的文档说明
build.description=${pom.description}
# spring-boot:run -Ppack时方便生成api客户端
build.pack=cn.alian.mall.stock
6.5、dozerMapping.xml
dozerMapping.xml
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozermapper.github.io/schema/bean-mapping"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://dozermapper.github.io/schema/bean-mapping http://dozermapper.github.io/schema/bean-mapping.xsd">
</mappings>
七、验证
我们公共的API已经完成了swagger的整合,我们启动项目使用swagger进行测试
返回结果:
{"code": "0000","msg": "success","content": {"resultCode": "0000","message": "库存扣减成功"},"timestamp": 1649741434665,"bizCode": null,"bizMsg": null,"success": true
}
数据库结果:
mysql> select * from tb_goods_stock;
+----+----------+-----------+-------------------------+-------------------------+
| id | goods_id | inventory | create_time | update_time |
+----+----------+-----------+-------------------------+-------------------------+
| 1 | 10001 | 99 | 2022-04-06 11:25:51.626 | 2022-04-12 05:30:35.662 |
| 2 | 10002 | 200 | 2022-04-12 01:56:39.974 | 2022-04-12 01:56:39.974 |
+----+----------+-----------+-------------------------+-------------------------+
2 rows in set (0.00 sec)
从结果上来说吗,我们的系统已经通过测试了。后续我们会生成接口调用,供订单系统调用。
(十)Alian 的 Spring Cloud 库存系统相关推荐
- (十八)Alian 的 Spring Cloud Gateway 集群配置
目录 一.简介 二.配置 三.配置文件 3.1.application.properties 四.主类 五.部署及配置 5.1.部署 5.2.Nginx配置 5.3.Spring Cloud Gate ...
- (十五)Alian 的 Spring Cloud 自动生成项目
目录 一.创建 1.1.第一步 二.mvn命令 三.生成项目 3.1.配置 3.1.属性配置 3.2.控制层 3.3.服务层 四.验证 4.1.请求生成项目 4.2.生成项目结果 4.3.项目结构 一 ...
- (十一)Alian 的 Spring Cloud 文档中心(swagger聚合文档)
目录 一.简介 1.1.maven依赖 二.核心配置类 2.1.SwaggerUI配置 2.2.服务定义的上下文 2.3.定时刷下文档定义 2.4.文档接口 三.配置 3.1.主类 3.2.boots ...
- (七)Alian 的 Spring Cloud Config 配置中心(客户端)
目录 一.背景 二.maven依赖 三.配置文件 四.验证 一.背景 通过上一篇文章,我们已经搭建了配置中心了,接下里我们继续改造我们的订单服务了,之前我们的订单服务的数据库配置还是写在配置文件中 ...
- (三)Alian 的 Spring Cloud Eureka Server(服务注册中心)
目录 一.创建Eureka服务工程 1.1.第一步(创建工程) 1.2.第二步(springboot工程) 1.3.第三步(工程设置) 1.4.第四步(依赖选择) 二.配置 2.1.pom文件 2.2 ...
- (十四)Alian 的 Spring Cloud 订单服务调用自动生成的API
目录 一.背景 二.maven依赖 三.主要编码 3.1.控制层 3.2.服务层 3.3.dto 3.4.主类 四.配置 4.1.bootstrap.properties 4.2.build.prop ...
- (十九)Alian 的 Spring Cloud Config 集群配置
目录 一.简介 1.1.第一步 二.maven依赖 三.配置 3.1.application.properties 3.2.主类 四.客户端修改(支付系统) 4.1 maven依赖 4.2 支付系统主 ...
- (十六)Alian 的 Spring Cloud Eureka 集群配置(主机名方式)
目录 一.背景 二.maven依赖 三.主类 四.Eureka服务配置 五.启动服务 5.1 服务1效果图(eureka-server1.com) 5.2 服务2效果图(eureka-server2. ...
- (十二)Alian 的 Spring Cloud 自定义Archetype
目录 一.简介 1.1.archetype目录结构 1.2.Archetype Domain结构图 1.3.Archetype Project结构图 二.Archetype Project 2.1.项 ...
最新文章
- 设有一数据库,包括四个表:学生表(Student)、课程表(Course)、成绩表(Score)以及教师信息表(Teacher)。...
- XP 的共享方案(面对新人)
- The import java.util cannot be resolved The import javax.servlet cannot be resolved
- JVM内存管理机制线上问题排查
- win10上安装opencv详细教程
- 【收藏】Win10:路径长度超过260个字符
- 使用遥控器控制汽车,实现高难度的泊车(发明畅想)
- MapReduce的方式进行HBase向HDFS导入和导出
- 西部数据硬盘支持linux,西部数据开发新的Linux文件系统“Zonefs” 支持在分区块设备上运行...
- 200(强缓存)和304(协商缓存)的区别
- 【原创】C# Sealed、new、virtual、abstract、override的理解
- php中的id怎么传值,uniapp如何跳转页面传值
- Highcharts+Spring饼图使用实例
- 排序算法(一)--桶排序、冒泡、快排(JAVA)
- Oracle 归档开启切换和归档日志删除(单实例和RAC)
- 【转】webkit webApp 开发技术要点总结
- ES6、7学习笔记(尚硅谷)-3-变量的解构赋值
- MPLAB X环境ICD3无法使用
- 精进Spring—Spring常用注解【经典总结】
- intellij idea 无法识别新装字体的问题的两种解决办法