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

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 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


相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1月前
|
搜索推荐 NoSQL Java
微服务架构设计与实践:用Spring Cloud实现抖音的推荐系统
本文基于Spring Cloud实现了一个简化的抖音推荐系统,涵盖用户行为管理、视频资源管理、个性化推荐和实时数据处理四大核心功能。通过Eureka进行服务注册与发现,使用Feign实现服务间调用,并借助Redis缓存用户画像,Kafka传递用户行为数据。文章详细介绍了项目搭建、服务创建及配置过程,包括用户服务、视频服务、推荐服务和数据处理服务的开发步骤。最后,通过业务测试验证了系统的功能,并引入Resilience4j实现服务降级,确保系统在部分服务故障时仍能正常运行。此示例旨在帮助读者理解微服务架构的设计思路与实践方法。
103 17
|
10天前
|
传感器 监控 安全
智慧工地云平台的技术架构解析:微服务+Spring Cloud如何支撑海量数据?
慧工地解决方案依托AI、物联网和BIM技术,实现对施工现场的全方位、立体化管理。通过规范施工、减少安全隐患、节省人力、降低运营成本,提升工地管理的安全性、效率和精益度。该方案适用于大型建筑、基础设施、房地产开发等场景,具备微服务架构、大数据与AI分析、物联网设备联网、多端协同等创新点,推动建筑行业向数字化、智能化转型。未来将融合5G、区块链等技术,助力智慧城市建设。
|
1月前
|
监控 JavaScript 数据可视化
建筑施工一体化信息管理平台源码,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
智慧工地云平台是专为建筑施工领域打造的一体化信息管理平台,利用大数据、云计算、物联网等技术,实现施工区域各系统数据汇总与可视化管理。平台涵盖人员、设备、物料、环境等关键因素的实时监控与数据分析,提供远程指挥、决策支持等功能,提升工作效率,促进产业信息化发展。系统由PC端、APP移动端及项目、监管、数据屏三大平台组成,支持微服务架构,采用Java、Spring Cloud、Vue等技术开发。
|
1月前
|
Java 关系型数据库 数据库
微服务SpringCloud分布式事务之Seata
SpringCloud+SpringCloudAlibaba的Seata实现分布式事务,步骤超详细,附带视频教程
77 1
|
5月前
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
1月前
|
人工智能 安全 Java
AI 时代:从 Spring Cloud Alibaba 到 Spring AI Alibaba
本次分享由阿里云智能集团云原生微服务技术负责人李艳林主讲,主题为“AI时代:从Spring Cloud Alibaba到Spring AI Alibaba”。内容涵盖应用架构演进、AI agent框架发展趋势及Spring AI Alibaba的重磅发布。分享介绍了AI原生架构与传统架构的融合,强调了API优先、事件驱动和AI运维的重要性。同时,详细解析了Spring AI Alibaba的三层抽象设计,包括模型支持、工作流智能体编排及生产可用性构建能力,确保安全合规、高效部署与可观测性。最后,结合实际案例展示了如何利用私域数据优化AI应用,提升业务价值。
141 4
|
2月前
|
SpringCloudAlibaba 负载均衡 Dubbo
【SpringCloud Alibaba系列】Dubbo高级特性篇
本章我们介绍Dubbo的常用高级特性,包括序列化、地址缓存、超时与重试机制、多版本、负载均衡。集群容错、服务降级等。
【SpringCloud Alibaba系列】Dubbo高级特性篇
|
2月前
|
存储 SpringCloudAlibaba Java
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论。
【SpringCloud Alibaba系列】一文全面解析Zookeeper安装、常用命令、JavaAPI操作、Watch事件监听、分布式锁、集群搭建、核心理论
|
2月前
|
SpringCloudAlibaba JavaScript Dubbo
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
本文介绍了 Dubbo-Admin 的安装和使用步骤。Dubbo-Admin 是一个前后端分离的项目,前端基于 Vue,后端基于 Spring Boot。安装前需确保开发环境(Windows 10)已安装 JDK、Maven 和 Node.js,并在 Linux CentOS 7 上部署 Zookeeper 作为注册中心。
【SpringCloud Alibaba系列】Dubbo dubbo-admin安装教程篇
|
2月前
|
SpringCloudAlibaba Dubbo Java
【SpringCloud Alibaba系列】Dubbo基础入门篇
Dubbo是一款高性能、轻量级的开源Java RPC框架,提供面向接口代理的高性能RPC调用、智能负载均衡、服务自动注册和发现、运行期流量调度、可视化服务治理和运维等功能。
【SpringCloud Alibaba系列】Dubbo基础入门篇