Spring Cloud【Finchley】实战-01注册中心及商品微服务(上)

本文涉及的产品
RDS MySQL DuckDB 分析主实例,基础系列 4核8GB
RDS MySQL DuckDB 分析主实例,集群系列 4核8GB
RDS AI 助手,专业版
简介: Spring Cloud【Finchley】实战-01注册中心及商品微服务(上)

Spring Cloud【Finchley】专栏


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

Spring Cloud 【Finchley】手札


概述


点餐系统,重点体会使用Spring Cloud微服务组件如何拆分系统

优秀的系统都是演进而来的,不要害怕出错,大胆折腾吧。

我们先来针对商品微服务进行设计和构建


版本说明


  • spring boot : 2.0.3.RELEASE
  • spring cloud: Finchley.RELEASE

搭建Eureka Server注册中心

如果没有了解过Eureka ,建议先学习下


Spring Cloud【Finchley】-02服务发现与服务注册Eureka + Eureka Server的搭建

Spring Cloud【Finchley】-13 Eureka Server HA高可用 2个/3个节点的搭建及服务注册调用

工程结构


20190321232800582.png

Step1. pom添加依赖

<?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.artisan</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>eureka server</description>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.3.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>
   </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</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>


Step2.application.yml 配置Eureka的信息

# app name
spring:
  application:
    name: eureka-server
# 启动端口
server:
  port: 8761
# 单节点的eureka (后续会改成集群模式)
eureka:
  client:
    # 是否将自己注册到Eureka Server ,默认为true.因为当前应用是作为Eureka Server用,因此设置为false
    register-with-eureka: false
    # eureka.client.fetch-registry:是否从Eureka Server获取注册信息,默认为true.
    # 因为我们这里目前是个单节点的Eureka Server ,不需要与其他的Eureka Server节点的数据,因此设为false
    fetch-registry: false
    # 置与Eureka Server交互的地址,查询服务和注册服务都依赖这个地址。
    # 默认为 http://localhost:8761/eureka ,多个地址可使用 , 分隔
    service-url:
      defaultZone: http://localhost:8761/eureka

Step3. 启动类增加@EnableEurekaServer

package com.artisan.eurekaserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}


Step4 启动测试

启动application,访问 http://localhost:8761/


20190321233339118.png


Github地址

https://github.com/yangshangwei/springcloud-o2o/tree/master/eureka-server


数据模型-商品微服务


我们先来整理商品微服务模块的库表设计。

  • 商品目录
  • 商品

商品要归属于某个商品目录,我们通过在category_type字段来将产品product和产品目录product_category关联起来。


20190321232645628.png

-- ----------------------------
-- Table structure for product_category
-- ----------------------------
DROP TABLE IF EXISTS `product_category`;
CREATE TABLE `product_category` (
  `category_id` int(11) NOT NULL AUTO_INCREMENT,
  `category_name` varchar(255) DEFAULT NULL COMMENT '产品目录名称',
  `category_type` int(11) NOT NULL COMMENT '产品目录类型,用于存储特定类型的商品',
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`category_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of product_category
-- ----------------------------
INSERT INTO `product_category` VALUES ('1', '热饮', '99', '2019-03-20 22:47:41', '2019-03-20 22:47:41');
INSERT INTO `product_category` VALUES ('2', '酒水', '98', '2019-03-20 22:48:13', '2019-03-20 22:48:13');
INSERT INTO `product_category` VALUES ('3', '甜品', '97', '2019-03-20 22:47:51', '2019-03-20 22:47:51');

20190321232704434.png

-- ----------------------------
-- Table structure for product
-- ----------------------------
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
  `product_id` int(11) NOT NULL AUTO_INCREMENT,
  `product_name` varchar(255) NOT NULL,
  `product_stock` int(11) NOT NULL COMMENT '库存',
  `product_price` decimal(8,2) DEFAULT NULL,
  `product_description` varchar(255) DEFAULT NULL,
  `product_icon` varchar(255) DEFAULT NULL,
  `product_status` tinyint(3) DEFAULT '0' COMMENT '商品状态, 0正常  1下架',
  `category_type` int(11) DEFAULT NULL COMMENT '产品目录',
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`product_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES ('1', '拿铁咖啡', '99', '20.99', '咖啡,提神醒脑', null, '0', '99', '2019-03-20 22:49:47', '2019-03-20 22:49:50');
INSERT INTO `product` VALUES ('2', '青岛纯生', '200', '7.50', '啤酒', null, '0', '98', '2019-03-20 22:50:48', '2019-03-20 22:50:55');
INSERT INTO `product` VALUES ('3', '卡布奇诺', '87', '15.00', '卡布奇诺的香味', null, '0', '99', '2019-03-20 22:51:53', '2019-03-20 22:51:56');

Product 微服务构建


20190323013322819.png

新建工程作为 Eureka Client,注册到Eureka Server上

Step1. pom.xml 添加依赖

    <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>


Step2 启动类增加@EnableEurekaClient注解

package com.artisan.product;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ArtisanProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ArtisanProductApplication.class, args);
    }
}


Step3 .启动 验证


先启动eureka-server这个服务,然后启动 artisan-product这个服务。访问eureka的地址 http://localhost:8761/


20190322220549193.png

说明成功注册到了Eureka Server上


API-约定前后台数据交互格式

请求Get方式 - /product/list


返回:

{
  "code":0,
  "msg":"成功",
  "data":[
    {
      "name":"商品目录名称",
      "type":"商品目录类型",
      "product":[
        {
          "id":"商品id",
            "name":"商品名称",
          "price": 100,
          "description":"商品描述",
          "icon":"商品图片地址"
        }
      ]
    }
  ]
}


[] 表示数组,可以返回多条


20190322222722642.png


约定查询 只查询上架的商品。

分析上述格式,结合我们的数据模型,可知会涉及到商品目录及商品两个表。


pom.xml引入依赖


  • 持久层使用 spring-data-jpa
  • 数据库使用mysql
  • 为了简化代码,引入了lombok (IDEA记得安装lombok插件
  <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>


配置文件增加数据库配置

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


实体类 Product

库表建好了,那接下来就要建立和库表对应的实体类了

package com.artisan.product.domain;
import lombok.Data;
import javax.persistence.*;
import java.math.BigDecimal;
import java.util.Date;
// lombok
@Data
// @Table指定这个实体对应数据库的表名 
// product_info ProductInfo这种格式的可以省略不写 ,如果 实体类叫product , 表名叫t_product 那么就要显式指定了
@Table(name = "product")
// @Entity表示这个类是一个实体类
@Entity
public class Product {
    // @Id标识主键 及主键生成策略 
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private String productId;
    private String productName;
    private Integer productStock;
    private BigDecimal productPrice;
    private String productDescription;
    private String productIcon;
    private Integer productStatus;
    private Integer categoryType;
    private Date createTime;
    private Date updateTime;
}


Dao层 ProductRepository

接口, 继承 JpaRepository<T, ID>

package com.artisan.product.repository;
import com.artisan.product.domain.Product;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
/**
 * JpaRepository<Product, String>  第一个参数为具体的domain对象,第二个参数为主键类型
 */
public interface ProductRepository  extends JpaRepository<Product, String> {
    // 根据产品状态查询产品
    List<Product>  findByProductStatus(Integer productStatus);
}


单元测试


在ProductRepository 中 右键 – Go To --Test --Create New Test 新建个单元测试

Spring Boot的单元测试别忘了这俩注解

@RunWith(SpringRunner.class)

@SpringBootTest

或者继承ArtisanProductApplicationTests ,加上@Component注解

@Component
public class ProductCategoryServiceImplTest extends ArtisanProductApplicationTests 
package com.artisan.product.repository;
import com.artisan.product.domain.Product;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.junit.Assert.*;
@RunWith(SpringRunner.class)
@SpringBootTest
public class ProductRepositoryTest {
    @Autowired
    ProductRepository productRepository;
    @Test
    public void findByProductStatus() {
       List<Product> list =  productRepository.findByProductStatus(0);
        Assert.assertEquals(3,list.size());
    }
}


结合数据库中的数据

20190322231226243.png

20190322231343810.png

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
相关文章
|
4月前
|
算法 Java 微服务
【SpringCloud(1)】初识微服务架构:创建一个简单的微服务;java与Spring与微服务;初入RestTemplate
微服务架构是What?? 微服务架构是一种架构模式,它提出将单一应用程序划分为一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。 每个服务允许在其独立的进程中,服务于服务间采用轻量级的通信机制互相协作(通常是Http协议的RESTful API或RPC协议)。 每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据上下文,选择合适的语言、工具对其进行构建
563 126
|
4月前
|
负载均衡 算法 Java
【SpringCloud(2)】微服务注册中心:Eureka、Zookeeper;CAP分析;服务注册与服务发现;单机/集群部署Eureka;连接注册中心
1. 什么是服务治理? SpringCloud封装了Netfix开发的Eureka模块来实现服务治理 在传统pc的远程调用框架中,管理每个服务与服务之间依赖关系比较复杂,管理比较复杂,所以需要使用服务治理,管理服务于服务之间依赖关系,可以实现服务调用、负载均衡、容错等,实现服务发现与注册
358 0
|
4月前
|
负载均衡 Java API
《深入理解Spring》Spring Cloud 构建分布式系统的微服务全家桶
Spring Cloud为微服务架构提供一站式解决方案,涵盖服务注册、配置管理、负载均衡、熔断限流等核心功能,助力开发者构建高可用、易扩展的分布式系统,并持续向云原生演进。
|
5月前
|
监控 安全 Java
Spring Cloud 微服务治理技术详解与实践指南
本文档全面介绍 Spring Cloud 微服务治理框架的核心组件、架构设计和实践应用。作为 Spring 生态系统中构建分布式系统的标准工具箱,Spring Cloud 提供了一套完整的微服务解决方案,涵盖服务发现、配置管理、负载均衡、熔断器等关键功能。本文将深入探讨其核心组件的工作原理、集成方式以及在实际项目中的最佳实践,帮助开发者构建高可用、可扩展的分布式系统。
361 1
|
SpringCloudAlibaba API 开发者
新版-SpringCloud+SpringCloud Alibaba
新版-SpringCloud+SpringCloud Alibaba
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
定时任务在企业应用中至关重要,常用于异步数据处理、自动化运维等场景。在单体应用中,利用Java的`java.util.Timer`或Spring的`@Scheduled`即可轻松实现。然而,进入微服务架构后,任务可能因多节点并发执行而重复。Spring Cloud Alibaba为此发布了Scheduling模块,提供轻量级、高可用的分布式定时任务解决方案,支持防重复执行、分片运行等功能,并可通过`spring-cloud-starter-alibaba-schedulerx`快速集成。用户可选择基于阿里云SchedulerX托管服务或采用本地开源方案(如ShedLock)
460 1
|
11月前
|
负载均衡 Dubbo Java
Spring Cloud Alibaba与Spring Cloud区别和联系?
Spring Cloud Alibaba与Spring Cloud区别和联系?
|
12月前
|
人工智能 SpringCloudAlibaba 自然语言处理
SpringCloud Alibaba AI整合DeepSeek落地AI项目实战
在现代软件开发领域,微服务架构因其灵活性、可扩展性和模块化特性而受到广泛欢迎。微服务架构通过将大型应用程序拆分为多个小型、独立的服务,每个服务运行在其独立的进程中,服务与服务间通过轻量级通信机制(通常是HTTP API)进行通信。这种架构模式有助于提升系统的可维护性、可扩展性和开发效率。
4401 2
|
Java Nacos Sentinel
Spring Cloud Alibaba:一站式微服务解决方案
Spring Cloud Alibaba(简称SCA) 是一个基于 Spring Cloud 构建的开源微服务框架,专为解决分布式系统中的服务治理、配置管理、服务发现、消息总线等问题而设计。
2812 14
Spring Cloud Alibaba:一站式微服务解决方案
|
SpringCloudAlibaba 负载均衡 Dubbo
【SpringCloud Alibaba系列】Dubbo高级特性篇
本章我们介绍Dubbo的常用高级特性,包括序列化、地址缓存、超时与重试机制、多版本、负载均衡。集群容错、服务降级等。
1913 6
【SpringCloud Alibaba系列】Dubbo高级特性篇

热门文章

最新文章