版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_29479041/article/details/83752169
一、Eureka Server
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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.imooc</groupId>
<artifactId>eureka</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
application.yml 配置相关属性
#配置eureka
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
fetch-registry: false
server:
enable-self-preservation: false #关闭自我保护模式 开发环境关闭,生产环境不要这样设置
spring:
application:
name: eureka
server:
port: 8761
Application 注解启用注册中心的功能
@EnableEurekaServer //启用注册中心的功能
@SpringBootApplication
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
二、商品服务
1、Sql 在数据库运行Sql语句
-- 类目
create table `product_category` (
`category_id` int not null auto_increment,
`category_name` varchar(64) not null comment '类目名字',
`category_type` int not null comment '类目编号',
`create_time` timestamp not null default current_timestamp comment '创建时间',
`update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',
primary key (`category_id`),
unique key `uqe_category_type` (`category_type`)
);
INSERT INTO `product_category` (`category_id`, `category_name`, `category_type`, `create_time`, `update_time`)
VALUES
(1,'热榜',11,'2017-03-28 16:40:22','2017-11-26 23:39:36'),
(2,'好吃的',22,'2017-03-14 17:38:46','2017-11-26 23:39:40');
-- 商品
create table `product_info` (
`product_id` varchar(32) not null,
`product_name` varchar(64) not null comment '商品名称',
`product_price` decimal(8,2) not null comment '单价',
`product_stock` int not null comment '库存',
`product_description` varchar(64) comment '描述',
`product_icon` varchar(512) comment '小图',
`product_status` tinyint(3) DEFAULT '0' COMMENT '商品状态,0正常1下架',
`category_type` int not null comment '类目编号',
`create_time` timestamp not null default current_timestamp comment '创建时间',
`update_time` timestamp not null default current_timestamp on update current_timestamp comment '修改时间',
primary key (`product_id`)
);
INSERT INTO `product_info` (`product_id`, `product_name`, `product_price`, `product_stock`, `product_description`, `product_icon`, `product_status`, `category_type`, `create_time`, `update_time`)
VALUES
('157875196366160022','皮蛋粥',0.01,39,'好吃的皮蛋粥','//fuss10.elemecdn.com/0/49/65d10ef215d3c770ebb2b5ea962a7jpeg.jpeg',0,1,'2017-03-28 19:39:15','2017-07-02 11:45:44'),
('157875227953464068','慕斯蛋糕',10.90,200,'美味爽口','//fuss10.elemecdn.com/9/93/91994e8456818dfe7b0bd95f10a50jpeg.jpeg',1,1,'2017-03-28 19:35:54','2017-04-21 10:05:57'),
('164103465734242707','蜜汁鸡翅',0.02,982,'好吃','//fuss10.elemecdn.com/7/4a/f307f56216b03f067155aec8b124ejpeg.jpeg',0,1,'2017-03-30 17:11:56','2017-06-24 19:20:54');
2、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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.micco</groupId>
<artifactId>product</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>product</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.M1</spring-cloud.version>
</properties>
<dependencies>
<!-- 引入eureka-client -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- 引入mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!-- 引入lombok 可以省去get set方法 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
3、application.yml 配置相关环境
spring:
application:
name: product #配置服务名称
#配置数据源
datasource:
driver-class-name: com.mysql.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/SpringCloud_Sell?characterEncoding=utf-8&useSSL=false
jpa:
show-sql: true
#配置Eureka
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka/
#配置端口号
server:
port: 8888
4、Application 注解开启发现服务功能
@EnableDiscoveryClient //开启发现服务功能
@SpringBootApplication
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
}
5、Entity 实体类
//商品
//@Table(name="product_info") //如果表名跟类名不一样,要写表名,一样就不要
@Data //使用lombok省去get set方法
@Entity //数据库与表对应
public class ProductInfo {
@Id //主键
private String productId;//id
private String productName;//名字
private BigDecimal productPrice;//单价
private Integer productStock;//库存
private String productDescription;//描述
private String productIcon;//小图
private Integer productStatus;//状态, 0正常1下架
private Integer categoryType;//类目编号
private Date createTime;//创建时间
private Date updateTime;//修改时间
}
//类目
@Data
@Entity
public class ProductCategory {
@Id //主键
@GeneratedValue //id自增
private Integer categoryId;//类目id
private String categoryName;//类目名字
private Integer categoryType;//类目编号
private Date createTime;//创建时间
private Date updateTime;//修改时间
}
6、DTO 数据传输对象
//数据传输对象
@Data
public class CartDTO {
private String productId;//商品id
private Integer productQuantity;//商品数量
public CartDTO() {
}
public CartDTO(String productId, Integer productQuantity) {
this.productId = productId;
this.productQuantity = productQuantity;
}
}
7、Dao 操作数据库
//商品
public interface ProductInfoRepository extends JpaRepository<ProductInfo,String> {
//根据商品状态查询商品List
List<ProductInfo> findByProductStatus(Integer productStatus);
//根据商品Id查询商品List
List<ProductInfo> findByProductIdIn(List<String> productIdList);
}
//类目
public interface ProductCategoryRepository extends JpaRepository<ProductCategory,Integer> {
//根据类目编号查询类目List
List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);
}
8、Service
//商品
public interface ProductService {
//查询所有在架商品列表
List<ProductInfo> findUpAll();
//根据productIdList查询商品列表
List<ProductInfo> findList(List<String> productIdList);
//扣库存
void decreaseStock(List<CartDTO> cartDTOList);
}
//类目
public interface CategoryService {
//根据类目编号查询List<ProductCategory>
List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList);
}
9、ServiceImpl 业务逻辑层
//商品
@Service
public class ProductServiceImpl implements ProductService {
//引入商品Dao
@Autowired
private ProductInfoRepository productInfoRepository;
//查询所有在架商品列表
@Override
public List<ProductInfo> findUpAll() {
return productInfoRepository.findByProductStatus(ProductStatusEnum.UP.getCode());
}
//根据productIdList查询商品列表
@Override
public List<ProductInfo> findList(List<String> productIdList) {
return productInfoRepository.findByProductIdIn(productIdList);
}
//扣库存
@Override
@Transactional
public void decreaseStock(List<CartDTO> cartDTOList) {
for (CartDTO cartDTO: cartDTOList) {
//根据商品Id查出商品信息
Optional<ProductInfo> productInfoOptional = productInfoRepository.findById(cartDTO.getProductId());
//判断商品是否存在
if(!productInfoOptional.isPresent()){
throw new ProductException(ResultEnum.PRODUCT_NOT_EXIST);
}
ProductInfo productInfo = productInfoOptional.get();
//判断库存是否足够
Integer result = productInfo.getProductStock() - cartDTO.getProductQuantity();
if(result<0){
throw new ProductException(ResultEnum.PRODUCT_STOCK_ERROR);
}
//扣减库存
productInfo.setProductStock(result);
productInfoRepository.save(productInfo);
}
}
//类目
@Service
public class CategoryServiceImpl implements CategoryService {
//引入商品Dao
@Autowired
private ProductCategoryRepository productCategoryRepository;
////根据类目编号查询List<ProductCategory>
@Override
public List<ProductCategory> findByCategoryTypeIn(List<Integer> categoryTypeList) {
return productCategoryRepository.findByCategoryTypeIn(categoryTypeList);
}
}
10、Enums 枚举状态
//商品上下线状态
@Getter //get方法
public enum ProductStatusEnum {
UP(0,"在架"),
DOWN(1,"下架"),
;
private Integer code;
private String message;
ProductStatusEnum(Integer code,String message){
this.code = code;
this.message = message;
}
}
@Getter
public enum ResultEnum {
PRODUCT_NOT_EXIST(1,"商品不存在"),
PRODUCT_STOCK_ERROR(1,"库存有误"),
;
private Integer code;
private String message;
ResultEnum(Integer code,String message){
this.code = code;
this.message = message;
}
}
11、Exception 自定义异常
//自定义异常
public class ProductException extends RuntimeException{
private Integer code;//异常码
public ProductException(Integer code,String message){
super(message);
this.code = code;
}
public ProductException(ResultEnum resultEnum){
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
}
}
12、Utils 工具类
//返回页面josn数据格式
public class ResultVOUtil {
public static ResultVO success(Object object){
ResultVO resultVO = new ResultVO();
resultVO.setData(object);
resultVO.setCode(0);
resultVO.setMsg("成功");
return resultVO;
}
}
13、VO(返回页面的Josn数据)
//http请求返回的最外层对象
@Data
public class ResultVO<T> {
private Integer code;//错误码
private String msg;//提示信息
private T data;//具体内容
}
//http请求返回的中间层对象
@Data
public class ProductVO {
@JsonProperty("name") //返回前端显示的字段
private String categoryName;//内目名字
@JsonProperty("type")
private Integer categoryType;//类目编号
@JsonProperty("foods")
private List<ProductInfoVO> productInfoVOList;//食物
}
//http请求返回的最里层对象
@Data
public class ProductInfoVO {
@JsonProperty("id")
private String productId;//商品id
@JsonProperty("name")
private String productName;//商品名称
@JsonProperty("price")
private String productPrice;//商品价格
@JsonProperty("description")
private String productDescription;//商品描述
@JsonProperty("icon")
private String productIcon;//商品突破
}
14、Controller
//商品
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;//商品Service
@Autowired
private CategoryService categoryService;//类目Service
@GetMapping("/list")
public ResultVO<ProductVO> list(){
//1.查询所有在架的商品
List<ProductInfo> productInfoList = productService.findUpAll();
//2.获取类目type列表
List<Integer> categoryTypeList = productInfoList.stream()
.map(ProductInfo::getCategoryType).collect(Collectors.toList());
//3.从数据库查询类目
List<ProductCategory> categoryList = categoryService.findByCategoryTypeIn(categoryTypeList);
//4.构造数据
List<ProductVO> productVOList = new ArrayList<>();
for (ProductCategory productCategory:categoryList) {
ProductVO productVO = new ProductVO();
productVO.setCategoryName(productCategory.getCategoryName());
productVO.setCategoryType(productCategory.getCategoryType());
List<ProductInfoVO> productInfoVOList = new ArrayList<>();
for (ProductInfo productInfo:productInfoList) {
if(productInfo.getCategoryType().equals(productCategory.getCategoryType())){
ProductInfoVO productInfoVO = new ProductInfoVO();
BeanUtils.copyProperties(productInfo,productInfoVO);//将productInfo里的属性拷贝到productInfoVO里面
productInfoVOList.add(productInfoVO);
}
}
productVO.setProductInfoVOList(productInfoVOList);
productVOList.add(productVO);
}
return ResultVOUtil.success(productVOList);
}
/**
* 获取商品列表(给订单服务用的)
* */
@PostMapping("/listForOrder")
public List<ProductInfo> listForOrder(@RequestBody List<String> productIdList){
return productService.findList(productIdList);
}
/**
* 扣减库存(给订单服务用的)
* */
@PostMapping("/decreaseStock")
public void decreaseStock(@RequestBody List<CartDTO> cartDTOList){
productService.decreaseStock(cartDTOList);
}
}
//给订单调用的测试Controller
@RestController
public class ServerController {
@GetMapping("/msg")
public String msg(){
return "this is product msg";
}
}
15、Test
测试地址:http://localhost:8888/product/list
测试结果: