Spring Cloud【Finchley】实战-02订单微服务(上)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Spring Cloud【Finchley】实战-02订单微服务

Spring Cloud【Finchley】专栏


如果还没有系统的学过Spring Cloud ,先到我的专栏去逛逛吧

Spring Cloud 【Finchley】手札


概述

这里我们简单的说下业务相关的需求,重点是体会微服务这种理念是如何落地的。


数据模型-订单微服务

通常来讲,微服务都是分数据库的。这里我们新建个数据库给订单微服务 ,数据库实例名 o2o-order


-- ----------------------------
-- Table structure for order
-- ----------------------------
-- 订单
create table `artisan_order` (
    `order_id` varchar(32) not null,
    `buyer_name` varchar(32) not null comment '买家名字',
    `buyer_phone` varchar(32) not null comment '买家电话',
    `buyer_address` varchar(128) not null comment '买家地址',
    `buyer_openid` varchar(64) not null comment '买家微信openid',
    `order_amount` decimal(8,2) not null comment '订单总金额',
    `order_status` tinyint(3) not null default '0' comment '订单状态, 默认为新下单',
    `pay_status` tinyint(3) not null default '0' 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 (`order_id`),
    key `idx_buyer_openid` (`buyer_openid`)
);
-- ----------------------------
-- Table structure for order_detail
-- ----------------------------
-- 订单详情
create table `order_detail` (
    `detail_id` varchar(32) not null,
    `order_id` varchar(32) not null,
    `product_id` varchar(32) not null,
    `product_name` varchar(64) not null comment '商品名称',
    `product_price` decimal(8,2) not null comment '当前价格,单位分',
    `product_quantity` int not null comment '数量',
    `product_icon` varchar(512) 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 (`detail_id`),
    key `idx_order_id` (`order_id`)
);

订单与订单详情是一对多的关系,一个订单中可能包含多个订单详情,比如我下一个订单,这个订单中买了1杯奶茶、2杯可乐等。


order_detail中不仅设计了product_id,同时也冗余了 product_name product_price product_icon等,主要是考虑到有些促销活动这些字段会经常更改这些因素。


API

请求:

POST方式 /order/create

内容:

    "name": "xxx",
    "phone": "xxxx",
    "address": "xxxx",
    "openid": "xxxx", //用户的微信openid
    "items": [
        {
            "productId": "xxxxxx",
            "productQuantity": 2   //购买数量
        }
    ]


后端尽量少依赖前端传递的数据,为了安全起见,产品相关的数据,只传递了一个productId和productQuantity,而没有将价格、描述等等一并传递,不传递就不会被篡改,也减少了交互数据的大小。

返回:

{
  "code": 0,
  "msg": "成功",
  "data": {
      "orderId": "123456" 
  }
}


业务逻辑分析

  1. 校验前台入参
  2. 查询商品信息(调用商品微服务
  3. 计算订单总价
  4. 扣减库存(调用商品微服务
  5. 订单入库


搭建订单微服务

依赖及配置文件

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>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.artisan</groupId>
    <artifactId>artisan_order</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>artisan_order</name>
    <description>Order</description>
    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.RELEASE</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>
</project>


application.yml

这里我们连接到 order微服务的数据库。 我这里本地环境,就新建了个数据库实例。

server:
  port: 8081
spring:
  application:
    name: artisan-order
  # datasource
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/o2o-order?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&useSSL=false
    username: root
    password: root
  #jpa
  jpa:
    show-sql: true
# Eureka
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/


将微服务注册到注册中心

application.yml中配置了Eureka的信息后,我们在启动类增加@EnableEurekaClient即可


20190323162938165.png

启动注册中心微服务,启动该服务

访问 http://localhost:8761/


20190323163019195.png


注册成功


实体类

Order

package com.artisan.order.domain;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;
import java.util.Date;
@Data
// 必不可少
@Entity
@Table(name = "artisan_order")
public class Order {
    /**
     * 订单id.
     */
    @Id
    private String orderId;
    /**
     * 买家名字.
     */
    private String buyerName;
    /**
     * 买家手机号.
     */
    private String buyerPhone;
    /**
     * 买家地址.
     */
    private String buyerAddress;
    /**
     * 买家微信Openid.
     */
    private String buyerOpenid;
    /**
     * 订单总金额.
     */
    private BigDecimal orderAmount;
    /**
     * 订单状态, 默认为0新下单.
     */
    private Integer orderStatus;
    /**
     * 支付状态, 默认为0未支付.
     */
    private Integer payStatus;
    /**
     * 创建时间.
     */
    private Date createTime;
    /**
     * 更新时间.
     */
    private Date updateTime;
}


OrderDetail

package com.artisan.order.domain;
import lombok.Data;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import java.math.BigDecimal;
@Data
// 必不可少
@Entity
// 如果实体类是OrderDetail,表名是order_detail,则这个注解可省略
@Table(name = "order_detail")
public class OrderDetail {
    // 必不可少
    @Id
    private String detailId;
    /**
     * 订单id.
     */
    private String orderId;
    /**
     * 商品id.
     */
    private String productId;
    /**
     * 商品名称.
     */
    private String productName;
    /**
     * 商品单价.
     */
    private BigDecimal productPrice;
    /**
     * 商品数量.
     */
    private Integer productQuantity;
    /**
     * 商品小图.
     */
    private String productIcon;
}


Dao层

创建订单无非就是往这两个表里写入数据。直接利用jpa提供的save方法即可。

OrderRepository

空实现 ,利用jpa本身提供的save方法

package com.artisan.order.repository;
import com.artisan.order.domain.Order;
import org.springframework.data.jpa.repository.JpaRepository;
// JpaRepository<Order,String>  第一个是要操作的对象,第二个是实体类中标注的@Id的字段的类型 (主键类型)
public interface OrderRepository extends JpaRepository<Order,String> {
}

OrderDetailRepository

空实现 ,利用jpa本身提供的save方法

package com.artisan.order.repository;
import com.artisan.order.domain.OrderDetail;
import org.springframework.data.jpa.repository.JpaRepository;
public interface OrderDetailRepository extends JpaRepository<OrderDetail ,String> {
}


单元测试

OrderRepositoryTest

package com.artisan.order.repository;
import com.artisan.order.ArtisanOrderApplicationTests;
import com.artisan.order.domain.Order;
import com.artisan.order.enums.OrderStatusEnum;
import com.artisan.order.enums.PayStatusEnum;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
@Component
public class OrderRepositoryTest  extends ArtisanOrderApplicationTests {
    @Autowired
    private OrderRepository orderRepository;
    @Test
    public void testSave(){
        Order order = new Order();
        order.setOrderId("1222");
        order.setBuyerName("artisan");
        order.setBuyerPhone("123445664");
        order.setBuyerAddress("Artisan Tech");
        order.setBuyerOpenid("11112233");
        order.setOrderAmount(new BigDecimal(3.9));
        order.setOrderStatus(OrderStatusEnum.NEW.getCode());
        order.setPayStatus(PayStatusEnum.WAIT.getCode());
        Order result = orderRepository.save(order);
        Assert.assertNotNull(result);
    }
}


2019032319590524.png


数据库记录


20190323195938869.png


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
12天前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
44 3
|
20天前
|
运维 NoSQL Java
后端架构演进:微服务架构的优缺点与实战案例分析
【10月更文挑战第28天】本文探讨了微服务架构与单体架构的优缺点,并通过实战案例分析了微服务架构在实际应用中的表现。微服务架构具有高内聚、低耦合、独立部署等优势,但也面临分布式系统的复杂性和较高的运维成本。通过某电商平台的实际案例,展示了微服务架构在提升系统性能和团队协作效率方面的显著效果,同时也指出了其带来的挑战。
58 4
|
30天前
|
自然语言处理 Java API
Spring Boot 接入大模型实战:通义千问赋能智能应用快速构建
【10月更文挑战第23天】在人工智能(AI)技术飞速发展的今天,大模型如通义千问(阿里云推出的生成式对话引擎)等已成为推动智能应用创新的重要力量。然而,对于许多开发者而言,如何高效、便捷地接入这些大模型并构建出功能丰富的智能应用仍是一个挑战。
115 6
|
1月前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
80 2
|
1月前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
26 1
|
2月前
|
负载均衡 Java 网络架构
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
实现微服务网关:Zuul与Spring Cloud Gateway的比较分析
110 5
|
1月前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
70 0
|
2月前
|
运维 持续交付 API
深入理解并实践微服务架构:从理论到实战
深入理解并实践微服务架构:从理论到实战
137 3
|
2月前
|
Java API 对象存储
微服务魔法启动!Spring Cloud与Netflix OSS联手,零基础也能创造服务奇迹!
这段内容介绍了如何使用Spring Cloud和Netflix OSS构建微服务架构。首先,基于Spring Boot创建项目并添加Spring Cloud依赖项。接着配置Eureka服务器实现服务发现,然后创建REST控制器作为API入口。为提高服务稳定性,利用Hystrix实现断路器模式。最后,在启动类中启用Eureka客户端功能。此外,还可集成其他Netflix OSS组件以增强系统功能。通过这些步骤,开发者可以更高效地构建稳定且可扩展的微服务系统。
58 1
|
1月前
|
XML Java 数据库连接
【2020Spring编程实战笔记】Spring开发分享~(上)
【2020Spring编程实战笔记】Spring开发分享~
53 0