一、前言
各位热爱知识的小伙伴们大家好呀!很高兴大家能点开这个博客,这是我个人的第一篇博客,之后也会持续的更新java以及spring项目的相关代码,希望大家持续关注。如果对本篇博客有什么不懂的地方或者思路不清晰的地方,大家可以在评论区交流,如果我看到了会在第一时间回复。现在开始我们的实例练习!
因为我给这篇文章的定位是基础级别,所以文章我会尽量详细一点,可能有点长,但主要是掌握中间件,而不是功能点,如果大家想逻辑在复杂一点,可以自己完善。
我在运行项目的时候不知道为什么总是报Lombok有问题,所以,该项目没有添加lombok,setter和getter方法,我都是用idea生成的,这个可能是我个人电脑运行环境的问题,所以大家可以自己去加一下(该项目没有lombok依赖),不必完全复制我的。
二、读前须知
因为这个项目不是java基础,所以要阅读下面代码可能需要一点点知识积累:
1、Spring MVC(请求驱动Web框架、MCV设计模式)
2、SpringBoot(SpringCloud更好)
3、Maven(项目管理)
4、Mybatis(数据库映射框架)
5、Zookeeper(注册中心) 下文会有简单的介绍
6、Feign(远程服务调用) 下文会有简单的介绍
(这边文章的接口测试使用的Apifox,不会用的小伙伴直接用浏览器也是一样的,当然,项目里引用了Swagger,也可以用Swagger测试接口,相应的配置已经写好了,直接用就可以了)
三、运行环境及配置
集成开发环境:IntelliJ IDEA 2022.2
数据库:Mysql 8.0.30 Mysql安装教程
Maven:apache-maven-3.8.4 maven安装教程
注册中心:apache-zookeeper-3.7.1-bin zookeeper安装教程
(zookeeper下载的时候一定要注意下载文件名要下加bin的文件,不然会出错,出错请看后面问题解决)
四、项目理解以及代码实现
项目理解:
(1)什么是单服务架构?
单服务架构就是把所有的业务代码,集中在单个服务器上,各种业务的调用不复杂,想要调用某个类,使用import语句直接用就好了,开箱即用,所以这种架构的优点就显而易见。
优点:
1、数据处理快:它不需要去和自己写的其他服务进行通讯,每个操作亲历亲为。
2、项目设计成本低,开发速度较快:它不需要去考虑与其他服务的引用问题、以及多台服务器之间的代码逻辑问题。
3、部署快,测试快。
当然有点这么多,但是当我们用户数达到一定数量级、功能点越加越多的时候,这种架构的缺点就慢慢开始显现。
缺点:
1、代码冗余度和耦合度都异常的高:一个需求改变可能涉及到多个地方同步修改(迁一发能动全身),业务逻辑冗余复杂。
2、单体代码量变大,维护成本极高:想象一下在一个上百的文件里,每个文件还有数十个方法,在这一千个方法里去找到自己想要修改的方法,本来改bug就挺痛苦,还去花很多时间去定位它,这比“佛耶戈”都痛苦。
3、访问量巨大,服务器容易崩溃,人更容易崩溃。
所以为了解决以上问题,微服务架构由此诞生,2014年,Martin Fowler 与 James Lewis 共同提出了微服务的概念,定义了微服务是由以单一应用程序构成的小服务,自己拥有自己的行程与轻量化处理,服务依业务功能设计,以全自动的方式部署,与其他服务使用 HTTP API 通讯。同时服务会使用最小的规模的集中管理 (例如 Docker) 能力,服务可以用不同的编程语言与数据库等元件实作。
(2)什么是微服务架构
微服务是一种以业务功能为主的服务设计概念,每一个服务都具有自主运行的业务功能,对外开放不受语言限制的 API (最常用的是 HTTP),应用程序则是由一个或多个微服务组成。
微服务架构,它提倡将单一的应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程内,服务之间相互协调,相互配置,为用户提供最终价值。服务之间采用轻量级的通讯机制相互沟通,每个服务都围绕着具体的业务进行构建,并且能够独立的部署到生产环境中,另外,应尽量避免同意的,统一的集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同语言来编写服务,也可以使用不同的数据存储。
用通俗的话来讲就是将以前单服务中的各功能点进行拆分,让单个服务处理单一功能,加大在大访问量,多功能点的情况下加快处理时间以及保证服务器的安全。,就像以前织布,我们一人织一件衣服需要几周,但是随着人口的发展,这种效率肯定是不适合社会效率的进步,所以开始出现工厂,多个人同时织一件衣服,几天就可以织出这几个人单独织几个月的量。
优点:
关键点:复杂度可控,独立按需扩展,技术选型灵活,容错,可用性高。
1、它解决了复杂性的问题。它会将一种怪异的整体应用程序分解成一组服务。虽然功能总量不变,但应用程序已分解为可管理的块或服务。每个服务都以RPC或消息驱动的API的形式定义了一个明确的边界;Microservice架构模式实现了一个模块化水平。
2、这种架构使每个服务都能够由专注于该服务的团队独立开发。开发人员可以自由选择任何有用的技术,只要该服务符合API合同。当然,大多数组织都希望避免完全无政府状态并限制技术选择。然而,这种自由意味着开发人员不再有义务使用在新项目开始时存在的可能过时的技术。在编写新服务时,他们可以选择使用当前的技术。此外,由于服务相对较小,因此使用当前技术重写旧服务变得可行。
3、Microservice架构模式使每个微服务都能独立部署。开发人员不需要协调部署本地服务的变更。这些变化可以在测试后尽快部署。例如,UI团队可以执行A|B测试,并快速迭代UI更改。Microservice架构模式使连续部署成为可能。
4、Microservice架构模式使每个服务都可以独立调整。您可以仅部署满足其容量和可用性限制的每个服务的实例数。此外,您可以使用最符合服务资源要求的硬件。
缺点:
1、额外引入的复杂性:当复杂性提高的时候,为了保证系统的稳定,就需要整体技术团队的靠谱,就需要技术人员的靠谱,就需要整体技术设施搭建的靠谱。
2、微服务需要的成本高:微服务需要一整套完整的技术体系和设施去支撑整体分布式的建设。
4、微服务本身所需要的经验:微服务本身是很复杂的,从设计划分模块开始,就需要架构师必须对架构设计和微服务本身对应的功能划分。
5、各服务之间无法直接通讯以及调用,因此注册中心中间件zookeeper、远程调用中间件Feign应运而生。
Zookeeper注册中心
注册中心概念
注册中心涉及三大角色
1、服务提供者
2、服务消费者
3、注册中心
他们之间的关系主要是
1、各个服务启动的时候,将自己网络地址等信息记录到注册中心
2、服务消费者从注册中心查询服务提供者提供的服务,并通过对应的地址调用服务提供者的 api
3、微服务与注册中心使用心跳机制通信,如果注册中心与微服务长时间无法通信,就会注销该服务实例
注册中心架构图:
zookeeper 做注册中心详细介绍_注册中心
注册中心的主要作用
在微服务架构中,注册中心主要起到了协调者的作用,主要有以下功能
1、服务发现
服务注册/反注册:保存服务提供者和服务调用者的信息
服务订阅/取消订阅:服务调用者订阅服务提供者的信息,最好有实时推送的功能
服务路由(可选):具有筛选整合服务提供者的能力。
2、服务配置
配置订阅:服务提供者和服务调用者订阅微服务相关的配置
配置下发:主动将配置推送给服务提供者和服务调用者
3、服务健康检测
检测服务提供者的健康情况
Zookeeper 概述
ZooKeeper 主要为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。曾经是 Hadoop 项目中的一个子项目,用来控制集群中的数据,目前已升级为独立的顶级项目。很多场景下也用它作为 Service 发现服务解决方案。
ZooKeeper 是基于 CP 来设计的,即任何时刻对 ZooKeeper 的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性,但是它不能保证每次服务请求的可用性。从实际情况来分析,在使用 ZooKeeper 获取服务列表时,如果 zookeeper 正在选主,或者 ZooKeeper 集群中半数以上机器不可用,那么将无法获得数据。所以说,ZooKeeper 不能保证服务可用性。
Zookeeper(数据一致性)数据同步分析
我们知道 Zookeeper 集群在选举结束之后,leader 节点将进入 LEADING 状态,follower 节点将进入 FOLLOWING 状态;此时集群中节点将进行数据同步操作,以保证数据一致。 只有数据同步完成之后 Zookeeper 集群才具备对外提供服务的能力。
当节点在选举后角色确认为 leader 后将会进入 LEADING 状态,节点状态变更为 LEADING 之后会创建 leader 实例,并触发 lead 过程。
leader 与 follower 在数据同步过程中会执行如下过程:
1、接收 follower 连接
2、计算新的 epoch 值
3、通知统一 epoch 值
4、数据同步
5、启动 zk server 对外提供服务
follower 节点进入 FOLLOWING 状态后,follower 与 leader 在数据同步过程中会执行如下过程:
1、请求连接 leader
2、提交节点信息计算新的 epoch 值
3、数据同步
4、以上就是 zookeeper 的同步逻辑
总结:
因为每个服务相对来说都是较为独立的,因此我们多方达成协议,把自己的调用信息同时放在一个地方,这个地方就是注册中心,每个服务当需要调用其他服务时,都会到这个注册中心寻找服务,完成他想要的功能,如果找不到服务则直接向控制台输出错误信息。
Feign远程调用
介绍:
Feign是Netflix开发的一个轻量级RESTful的HTTP服务客户端(用它来发起请求, 远程调用的),是以Java接口注解的方式调用Http请求,而不用像Java中通过封装 HTTP请求报文的方式直接调用,Feign被广泛应用在Spring Cloud 的解决方案中。类似于Dubbo,服务消费者拿到服务提供者的接口,然后像调用本地接口方法一样 去调用,实际发出的是远程的请求。
使用Feign的原因:
- Feign可帮助我们更加便捷,优雅的调用HTTP API:不需要我们去拼接url然后 呢调用restTemplate的api,在SpringCloud中,使用Feign非常简单,创建一个 接口(在消费者--服务调用方这一端),并在接口上添加一些注解,代码就完成了。
- SpringCloud对Feign进行了增强,使Feign支持了SpringMVC注解 (OpenFeign)。
- 本质:封装了Http调用流程,更符合面向接口化的编程习惯,类似于Dubbo的服务 调用。
总结:Feign的作用就是发现在注册中心里的生产者服务,写一个类来代理生产者的接口,然后controller层对这个代理层进行调用。
用法:
1.引入依赖
我们在zookeeper-consumer服务的pom文件中引入feign的依赖:
2.添加注解
在zookeeper-consumer的启动类添加注解(@EnableFeignClients)开启Feign的功能:
3.编写Feign的客户端
4.调用代理类
5.调用接口方法
好戏开始!
之后都是代码讲解了,当然,如果觉得自己对这个比较熟悉,可以跳过这个部分,直接去Gitee仓库拉代码!!!
网址请点击---------------->hm-zookeeper-demo代码仓库
首先创建数据库
数据库建表
/*
Navicat Premium Data Transfer
Source Server : Practice
Source Server Type : MySQL
Source Server Version : 80030
Source Host : localhost:3306
Source Schema : product
Target Server Type : MySQL
Target Server Version : 80030
File Encoding : 65001
Date: 18/08/2022 13:16:36
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for order
-- ----------------------------
DROP TABLE IF EXISTS `order`;
CREATE TABLE `order` (
`order_id` char(40) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL,
`user_name` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`product_id` char(40) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`product_name` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`order_date` char(30) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`product_number` int(0) NULL DEFAULT NULL,
`product_price` decimal(10, 2) NULL DEFAULT NULL,
`total_price` decimal(10, 2) NULL DEFAULT NULL,
PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of order
-- ----------------------------
INSERT INTO `order` VALUES ('11ad9a565c6b4d088b92b508f8aa1c22', '闵宸霆', '156425', '黄桃', '2022-08-18 02:05:41.394', 45, 12.00, 540.00);
INSERT INTO `order` VALUES ('17a8eae1ea2b4ba2aa0fa7e20724040d', '100', '4', '42', '2022-08-16 08:52:39.438', 5, 80.00, 400.00);
INSERT INTO `order` VALUES ('19db492fe4ea41dba7040176fce9ef6e', '罗承庭', '1585245626', '生煎饼', '2022-08-18 02:20:52.487', 45, 50.00, 2250.00);
INSERT INTO `order` VALUES ('2f9c3e1b11274db28322a8aeaa5d412b', '100', '4', '42', '2022-08-16 08:52:37.024', 5, 80.00, 400.00);
INSERT INTO `order` VALUES ('489c515874534d42a8531ee49f7c5233', '12', '13', '42', '2022-08-16 08:34:26.457', 45, 2.00, 90.00);
INSERT INTO `order` VALUES ('92373c3cb62c4f5696547a54496054d1', '100', '4', '42', '2022-08-16 08:51:46.48', 5, 80.00, 400.00);
INSERT INTO `order` VALUES ('a766304222b54f56be1fa9329d9e8f47', '478', '45', '56', '2022-08-16 08:51:24.818', 5, 40.00, 200.00);
INSERT INTO `order` VALUES ('b289668fd14d4dcb8cd9f227e58cf533', '54', '4', '45645', '2022-08-16 08:50:11.041', 4, 80.00, 320.00);
INSERT INTO `order` VALUES ('c194465b0ed042089ed79516c9b153e5', 'chenrui', '1101', 'fawawfwa', '2022-08-17 09:13:55.981', 2, 8.00, 16.00);
INSERT INTO `order` VALUES ('c809a41498ff4437903f2b06ab42dbef', '4554', '45', '56', '2022-08-16 08:50:34.528', 5, 40.00, 200.00);
INSERT INTO `order` VALUES ('e0f4695f92974555b69bc8c9d8c16f4f', '45', '452', '45', '2022-08-16 08:41:01.416', 4, 50.00, 200.00);
-- ----------------------------
-- Table structure for product
-- ----------------------------
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
`product_id` char(40) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL,
`product_name` varchar(20) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NOT NULL,
`product_price` decimal(10, 2) NULL DEFAULT NULL,
`warehousing_number` int(0) NULL DEFAULT NULL,
`sold_number` int(0) NULL DEFAULT NULL,
`warehousing_date` char(40) CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci NULL DEFAULT NULL,
`discount` decimal(10, 2) NOT NULL,
PRIMARY KEY (`product_id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb3 COLLATE = utf8mb3_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of product
-- ----------------------------
INSERT INTO `product` VALUES ('1', '1', 1.00, 1, 0, '2022-08-03 15:51:52', 0.00);
INSERT INTO `product` VALUES ('10', 'sa', 12.00, 12, 0, '123', 0.00);
INSERT INTO `product` VALUES ('408a9f6f538b4a568a8f1e4bf85fb4b0', '44', 46.00, 12, 0, '2022-08-08 16:07:33', 0.00);
INSERT INTO `product` VALUES ('dc66e02e07ee4598b68846029a601d56', '42', 45.00, 56, 0, '2022-08-16 14:35:51', 1.00);
SET FOREIGN_KEY_CHECKS = 1;
父工程
首先创建父工程
命名好直接下一步,创建完父模块,删除src目录,只留pom文件和idea设置文件夹(新建工作台的时候记得修改maven仓库设置)
然后编写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>org.ming</groupId>
<artifactId>Spring_Cloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>zookeeper-producer</module>
<module>zookeeper-consumer</module>
</modules>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<spring.boot.version>2.6.6</spring.boot.version>
<spring.cloud.version>2021.0.1</spring.cloud.version>
<spring.cloud.alibaba.version>2021.0.1.0</spring.cloud.alibaba.version>
<zookeeper.version>3.7.1</zookeeper.version>
<swagger.version>2.6.1</swagger.version>
<mysql.version>8.0.22</mysql.version>
<mybatis.version>2.0.1</mybatis.version>
<druid.version>1.2.1</druid.version>
</properties>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring.boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring.cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>${spring.cloud.alibaba.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${spring.boot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<!-- 原型外所加依赖-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-jdbc</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${swagger.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
1. 生产者
启动类代码
package com.ming;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient -----一定要记得加上
public class ZookeeperProducerApplication {
public static void main(String[] args) {
SpringApplication.run(ZookeeperProducerApplication.class, args);
}
}
1.1 依赖包代码
生产者服务依赖:
<?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">
<parent>
<artifactId>Spring_Cloud</artifactId>
<groupId>org.ming</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zookeeper-producer</artifactId>
<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-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<exclusions>
<exclusion>
<artifactId>commons-io</artifactId>
<groupId>commons-io</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
<exclusion>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<!-- 原型外所加依赖-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-jdbc</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
1.2 配置包代码
application.properties配置文件:
type=com.alibaba.druid.pool.DruidDataSource
mybatis.mapper-locations=classpath:mapper/*.xmlspring.application.name=zookeeper-producer-ming
server.port=8089
spring.cloud.zookeeper.connect-string=192.168.8.45:2181(填写自己的ip地址的zookeeper端口号)
application.yml配置文件:
server: port: 8088 spring.mvc.pathmatch.matching-strategy: ANT_PATH_MATCHER spring: #数据库配置 datasource: url: jdbc:mysql://localhost:3306/product?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true username: root password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver
mybatis-config.xml配置:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true" />
<setting name="logImpl" value="STDOUT_LOGGING" />
</settings>
</configuration>
1.3 业务代码
1.3.1 实体类
Product实体类:
package com.ming.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Objects;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/8 14:48
*/
@ApiModel("商品类")
public class Product {
@ApiModelProperty(value = "商品id")
private String productId;
@ApiModelProperty(value = "商品名称")
private String productName;
@ApiModelProperty(value = "商品价格")
private BigDecimal productPrice;
@ApiModelProperty(value = "仓库库存数量")
private Integer warehousingNumber;
@ApiModelProperty(value = "售出数量")
private String soldNumber;
@ApiModelProperty(value = "入库时间")
private String warehousingDate;
@ApiModelProperty(value = "商品优惠")
private BigDecimal discount;
public Product() {
}
public Product(String productId, String productName, BigDecimal productPrice, Integer warehousingNumber, String soldNumber, String warehousingDate, BigDecimal discount) {
this.productId = productId;
this.productName = productName;
this.productPrice = productPrice;
this.warehousingNumber = warehousingNumber;
this.soldNumber = soldNumber;
this.warehousingDate = warehousingDate;
this.discount = discount;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public BigDecimal getProductPrice() {
return productPrice;
}
public void setProductPrice(BigDecimal productPrice) {
this.productPrice = productPrice;
}
public Integer getWarehousingNumber() {
return warehousingNumber;
}
public void setWarehousingNumber(Integer warehousingNumber) {
this.warehousingNumber = warehousingNumber;
}
public String getSoldNumber() {
return soldNumber;
}
public void setSoldNumber(String soldNumber) {
this.soldNumber = soldNumber;
}
public String getWarehousingDate() {
return warehousingDate;
}
public void setWarehousingDate(String warehousingDate) {
this.warehousingDate = warehousingDate;
}
public BigDecimal getDiscount() {
return discount;
}
public void setDiscount(BigDecimal discount) {
this.discount = discount;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Product product = (Product) o;
if (!Objects.equals(productId, product.productId)) {
return false;
}
if (!Objects.equals(productName, product.productName)) {
return false;
}
if (!Objects.equals(productPrice, product.productPrice)) {
return false;
}
if (!Objects.equals(warehousingNumber, product.warehousingNumber)) {
return false;
}
if (!Objects.equals(soldNumber, product.soldNumber)) {
return false;
}
if (!Objects.equals(warehousingDate, product.warehousingDate)) {
return false;
}
return Objects.equals(discount, product.discount);
}
@Override
public int hashCode() {
int result = productId != null ? productId.hashCode() : 0;
result = 31 * result + (productName != null ? productName.hashCode() : 0);
result = 31 * result + (productPrice != null ? productPrice.hashCode() : 0);
result = 31 * result + (warehousingNumber != null ? warehousingNumber.hashCode() : 0);
result = 31 * result + (soldNumber != null ? soldNumber.hashCode() : 0);
result = 31 * result + (warehousingDate != null ? warehousingDate.hashCode() : 0);
result = 31 * result + (discount != null ? discount.hashCode() : 0);
return result;
}
}
order实体类
package com.ming.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/8 14:57
*/
@ApiModel("商品类")
public class Order {
@ApiModelProperty(value = "订单id")
private String orderId;
@ApiModelProperty(value = "用户名称")
private String userName;
@ApiModelProperty(value = "商品id")
private String productId;
@ApiModelProperty(value = "商品名称")
private String productName;
@ApiModelProperty(value = "订单开始时间")
private Date orderDate;
@ApiModelProperty(value = "商品订单数量")
private Integer productNumber;
@ApiModelProperty(value = "商品价格")
private BigDecimal productPrice;
@ApiModelProperty(value = "订单总价")
private BigDecimal totalPrice;
public Order() {
}
public Order(String orderId, String userName, String productId, String productName, Date orderDate, Integer productNumber, BigDecimal productPrice, BigDecimal totalPrice) {
this.orderId = orderId;
this.userName = userName;
this.productId = productId;
this.productName = productName;
this.orderDate = orderDate;
this.productNumber = productNumber;
this.productPrice = productPrice;
this.totalPrice = totalPrice;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
public Integer getProductNumber() {
return productNumber;
}
public void setProductNumber(Integer productNumber) {
this.productNumber = productNumber;
}
public BigDecimal getProductPrice() {
return productPrice;
}
public void setProductPrice(BigDecimal productPrice) {
this.productPrice = productPrice;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Order order = (Order) o;
if (!Objects.equals(orderId, order.orderId)) {
return false;
}
if (!Objects.equals(userName, order.userName)) {
return false;
}
if (!Objects.equals(productId, order.productId)) {
return false;
}
if (!Objects.equals(productName, order.productName)) {
return false;
}
if (!Objects.equals(orderDate, order.orderDate)) {
return false;
}
if (!Objects.equals(productNumber, order.productNumber)) {
return false;
}
if (!Objects.equals(productPrice, order.productPrice)) {
return false;
}
return Objects.equals(totalPrice, order.totalPrice);
}
@Override
public int hashCode() {
int result = orderId != null ? orderId.hashCode() : 0;
result = 31 * result + (userName != null ? userName.hashCode() : 0);
result = 31 * result + (productId != null ? productId.hashCode() : 0);
result = 31 * result + (productName != null ? productName.hashCode() : 0);
result = 31 * result + (orderDate != null ? orderDate.hashCode() : 0);
result = 31 * result + (productNumber != null ? productNumber.hashCode() : 0);
result = 31 * result + (productPrice != null ? productPrice.hashCode() : 0);
result = 31 * result + (totalPrice != null ? totalPrice.hashCode() : 0);
return result;
}
}
QueryResult实体类
package com.ming.pojo;
import java.util.Objects;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/3 08:45
*/
public class QueryResult {
boolean success;
int code;
String message;
public QueryResult() {
}
public QueryResult(boolean success, int code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
QueryResult that = (QueryResult) o;
if (success != that.success) {
return false;
}
if (code != that.code) {
return false;
}
return Objects.equals(message, that.message);
}
@Override
public int hashCode() {
int result = (success ? 1 : 0);
result = 31 * result + code;
result = 31 * result + (message != null ? message.hashCode() : 0);
return result;
}
}
1.3.2 swagger配置类
package com.ming.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/2 19:37
*/
@Configuration // 标明是配置类
@EnableSwagger2 //开启swagger功能
public class SwaggerConfig {
/**
* @description: 无
* @param:
* @return:
* @return: springfox.documentation.spring.web.plugins.Docket
* @author Yiming_Chato
* @date: 2022/8/18 11:37
*/
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2) // DocumentationType.SWAGGER_2 固定的,代表swagger2
// .groupName("分布式任务系统") // 如果配置多个文档的时候,那么需要配置groupName来分组标识
.apiInfo(apiInfo()) // 用于生成API信息
.select() // select()函数返回一个ApiSelectorBuilder实例,用来控制接口被swagger做成文档
.apis(RequestHandlerSelectors.basePackage("com.ming.controller")) // 用于指定扫描哪个包下的接口
.paths(PathSelectors.any())// 选择所有的API,如果你想只为部分API生成文档,可以配置这里
.build();
}
/**
* 用于定义API主界面的信息,比如可以声明所有的API的总标题、描述、版本
* @return
*/
/**
* @description: 无
* @param:
* @return:
* @return: springfox.documentation.service.ApiInfo
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("商品API") // 可以用来自定义API的主标题
.description("商品SwaggerAPI管理") // 可以用来描述整体的API
.termsOfServiceUrl("") // 用于定义服务的域名
.version("1.0") // 可以用来定义版本。
.build(); //
}
}
1.3.3 Mapper层
OrderMapper接口:
package com.ming.mapper;
import com.ming.pojo.Order;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
@Mapper
@Repository
public interface OrderMapper {
/**
* @description: 无
* @param:
* @param orderId
* @param userName
* @param productId
* @param productName
* @param orderDate
* @param productNumber
* @param productPrice
* @param totalPrice
* @return:
* @author Yiming_Chato
* @date: 2022/8/18 11:39
*/
void addOrder(String orderId, String userName,
String productId, String productName,
Date orderDate, Integer productNumber,
BigDecimal productPrice,BigDecimal totalPrice);
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:39
*/
List<Order> findAllOrder();
/**
* @description: 无
* @param:
* @param orderId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
List<Order> findOrederByOrederId(String orderId);
}
OrderMapper XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ming.mapper.OrderMapper">
<resultMap id="OrederMapResult" type="com.ming.pojo.Order">
<id column="order_id" property="orderId" jdbcType="CHAR"/>
<result column="user_name" property="userName" jdbcType="VARCHAR"/>
<result column="product_id" property="productId" jdbcType="CHAR"/>
<result column="product_name" property="productName" jdbcType="VARCHAR"/>
<result column="order_date" property="orderDate" jdbcType="CHAR"/>
<result column="product_number" property="productNumber" jdbcType="INTEGER"/>
<result column="product_price" property="productPrice" jdbcType="DECIMAL"/>
<result column="total_price" property="totalPrice" jdbcType="DECIMAL"/>
</resultMap>
<select id="findAllOrder" resultMap="OrederMapResult">
select *
from `order`
</select>
<select id="findOrederByOrederId" resultMap="OrederMapResult" parameterType="string">
select *
from `order`
where order_id = #{param1}
</select>
<insert id="addOrder" parameterType="com.ming.pojo.Order">
insert into `order`
(order_id,user_name, product_id, product_name, order_date,product_number,product_price,total_price)
values (#{param1}, #{param2}, #{param3}, #{param4}, #{param5}, #{param6},#{param7},#{param8})
</insert>
</mapper>
ProductMapper接口:
package com.ming.mapper;
import com.ming.pojo.Product;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.math.BigDecimal;
import java.util.List;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/8 15:07
*/
@Mapper
@Repository
public interface ProductMapper {
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:39
*/
List<Product> findAllProduct();
/**
* @description: 无
* @param:
* @param productId
* @param productName
* @param productPrice
* @param warehousingNumber
* @param soldNumber
* @param warehousingDate
* @param discount
* @return:
* @author Yiming_Chato
* @date: 2022/8/18 11:39
*/
void addProduct(String productId, String productName,
BigDecimal productPrice,Integer warehousingNumber,
String soldNumber,String warehousingDate,
BigDecimal discount);
/**
* @description: 无
* @param:
* @param productId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
List<Product> findProductByProductId(String productId);
}
ProductMapper XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ming.mapper.ProductMapper">
<resultMap id="productMapResult" type="com.ming.pojo.Product">
<id column="product_id" property="productId" jdbcType="CHAR"></id>
<result column="product_name" property="productName" jdbcType="VARCHAR"></result>
<result column="product_price" property="productPrice" jdbcType="DECIMAL"></result>
<result column="warehousing_number" property="warehousingNumber" jdbcType="INTEGER"></result>
<result column="sold_number" property="soldNumber" jdbcType="INTEGER"></result>
<result column="warehousing_date" property="warehousingDate" jdbcType="CHAR"></result>
<result column="discount" property="discount" jdbcType="DECIMAL"></result>
</resultMap>
<select id="findAllProduct" resultMap="productMapResult">
select *
from product
</select>
<select id="findProductByProductId" resultMap="productMapResult" parameterType="string">
select *
from product
where product_id = #{param1}
</select>
<insert id="addProduct" parameterType="com.ming.pojo.Product">
insert into product
(product_id, product_name, product_price, warehousing_number, sold_number, warehousing_date, discount)
values (#{param1}, #{param2}, #{param3}, #{param4}, #{param5}, #{param6},#{param7})
</insert>
</mapper>
OrderService 接口
package com.ming.service;
import com.ming.pojo.Order;
import com.ming.pojo.QueryResult;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface OrderService {
/**
* @description: 无
* @param:
* @param order
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:40
*/
QueryResult addOrder(Order order);
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:40
*/
List<Order> findAllOrder();
/**
* @description: 无
* @param:
* @param orderId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
List<Order> findOrederByOrederId(String orderId);
}
OrederServiceImpl 接口实现类
package com.ming.service.Impl;
import com.ming.mapper.OrderMapper;
import com.ming.pojo.Order;
import com.ming.pojo.QueryResult;
import com.ming.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
/**
* @description: 无
* @param:
* @param order
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:40
*/
@Override
public QueryResult addOrder(Order order) {
orderMapper.addOrder(order.getOrderId(),order.getUserName(),
order.getProductId(),order.getProductName(),
order.getOrderDate(),order.getProductNumber(),
order.getProductPrice(),order.getTotalPrice());
if (orderMapper.findOrederByOrederId(order.getOrderId())!=null) {
return new QueryResult(true, 100, "添加成功");
}
return new QueryResult(false, 000, "添加失败");
}
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
@Override
public List<Order> findAllOrder() {
return orderMapper.findAllOrder();
}
/**
* @description: 无
* @param:
* @param orderId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@Override
public List<Order> findOrederByOrederId(String orderId) {
return orderMapper.findOrederByOrederId(orderId);
}
}
ProductService 接口
package com.ming.service;
import com.ming.pojo.Product;
import com.ming.pojo.QueryResult;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/3 11:09
*/
@Service
public interface ProductService {
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:40
*/
List<Product> findAllProduct();
/**
* @description: 无
* @param:
* @param product
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:40
*/
QueryResult addProduct(Product product);
/**
* @description: 无
* @param:
* @param productId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
List<Product> findProductByProductId(String productId);
}
ProductServiceImpl 接口实现类
package com.ming.service.Impl;
import com.ming.mapper.ProductMapper;
import com.ming.pojo.Product;
import com.ming.pojo.QueryResult;
import com.ming.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/3 10:56
*/
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
@Override
public List<Product> findAllProduct() {
return productMapper.findAllProduct();
}
/**
* @param product
* @description: 无
* @param:
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
@Override
public QueryResult addProduct(Product product) {
productMapper.addProduct(product.getProductId(), product.getProductName(),
product.getProductPrice(), product.getWarehousingNumber(),
product.getSoldNumber(), product.getWarehousingDate(),
product.getDiscount());
if (productMapper.findProductByProductId(product.getProductId()).get(0) != null) {
return new QueryResult(true, 100, "添加成功");
}
return new QueryResult(false, 000, "添加失败");
}
/**
* @param productId
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
@Override
public List<Product> findProductByProductId(String productId) {
return productMapper.findProductByProductId(productId);
}
}
TestController 控制类
package com.ming.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.UUID;
@RestController
@RequestMapping("/test")
public class TestController {
/**
* @description: 无
* @param:
* @return:
* @return: java.lang.String
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@GetMapping("/uuid")
public String getUuid(){
return UUID.randomUUID().toString()+"闵宸霆";
}
}
OrderController 控制类
package com.ming.controller;
import com.ming.pojo.Order;
import com.ming.pojo.QueryResult;
import com.ming.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("/o")
public class OrderConroller {
@Autowired
private OrderService orderService;
/**
* @param userName
* @param productId
* @param productName
* @param productNumber
* @param productPrice
* @description: 添加订单
* @param:
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:37
*/
@PostMapping("/add/{userName}/{productId}/{productName}/{productNumber}/{productPrice}")
public QueryResult addOrder(@PathVariable("userName") String userName,
@PathVariable("productId") String productId,
@PathVariable("productName") String productName,
@PathVariable("productNumber") Integer productNumber,
@PathVariable("productPrice") Double productPrice
) {
String orderUuid = UUID.randomUUID().toString().replace("-", "");
Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式(年-月-日-时-分-秒)
String createTime = dateFormat.format(now);
Double total = new Double(productNumber * productPrice);
Order order = new Order(orderUuid, userName,
productId, productName,
now, productNumber,
BigDecimal.valueOf(productPrice), BigDecimal.valueOf(total));
return orderService.addOrder(order);
}
/**
* @description: 查询所有订单
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:37
*/
@GetMapping("/all")
public List<Order> findAllOrder() {
return orderService.findAllOrder();
}
/**
* @param orderId
* @description: 根据订单ID查询订单
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:38
*/
@GetMapping("/find_order_by_orderid/{orderId}")
public List<Order> findOrderByOrderId(@PathVariable("orderId") String orderId) {
return orderService.findOrederByOrederId(orderId);
}
}
ProductController 控制类
package com.ming.controller;
import com.ming.pojo.Product;
import com.ming.pojo.QueryResult;
import com.ming.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/3 10:56
*/
@RestController
@RequestMapping("/p")
public class ProductController {
@Autowired
private ProductService productService;
/**
* @description: 查询所有产品
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:38
*/
@GetMapping("/all")
public List<Product> findAll() {
return productService.findAllProduct();
}
/***
* @description: 根据产品ID查询产品
* @param:
* @param productId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Product>
* @author Yiming_Chato
* @date: 2022/8/18 11:38
*/
@GetMapping("/find_product_by_productid")
public List<Product> findProductByProductId(String productId) {
return productService.findProductByProductId(productId);
}
/**
* @param productName
* @param productPrice
* @param warehousingNumber
* @param soldNumber
* @param discount
* @description: 添加产品
* @param:
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:38
*/
@PostMapping("/add")
public QueryResult addProduct(String productName,
BigDecimal productPrice, Integer warehousingNumber,
String soldNumber, BigDecimal discount) {
String productUuid = UUID.randomUUID().toString().replace("-", "");
Date now = new Date();
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//设置日期格式(年-月-日-时-分-秒)
String createTime = dateFormat.format(now);
Product product = new Product(productUuid, productName, productPrice, warehousingNumber, soldNumber, createTime, discount);
return productService.addProduct(product);
}
}
做到这里,生产者所有的代码就已经完成了,大家在练习的时候尽量是写完一个功能点就去测试,不然等到代码量一多,出错往往需要花费大量时间去找Bug,真的会得不偿失!!!!
2. 消费者
启动类代码
package com.ming;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableFeignClients -----一定要记得加上
public class ZookeeperConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ZookeeperConsumerApplication.class, args);
}
}
2.1 依赖包代码
<?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">
<parent>
<artifactId>Spring_Cloud</artifactId>
<groupId>org.ming</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>zookeeper-consumer</artifactId>
<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-bootstrap</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>${zookeeper.version}</version>
</dependency>
<!-- 原型外所加依赖-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-data-jdbc</artifactId>-->
<!-- </dependency>-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.6.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.6.6</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.2 配置包代码
application.properties配置文件
# 应用名称
spring.application.name=zookeeper-consumer-ming
server.port=8091
spring.cloud.zookeeper.connect-string=192.168.8.45:2181
type=com.alibaba.druid.pool.DruidDataSource
mybatis.mapper-locations=classpath:mapper/*.xml
spring.main.allow-bean-definition-overriding=true
application.yaml配置文件
server:
port: 8088
spring.mvc.pathmatch.matching-strategy: ANT_PATH_MATCHER
spring:
#数据库配置
datasource:
url: jdbc:mysql://localhost:3306/product?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
2.3 业务代码
Order 实体类
package com.ming.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/8 14:57
*/
@ApiModel("商品类")
public class Order {
@ApiModelProperty(value = "订单id")
private String orderId;
@ApiModelProperty(value = "用户名称")
private String userName;
@ApiModelProperty(value = "商品id")
private String productId;
@ApiModelProperty(value = "商品名称")
private String productName;
@ApiModelProperty(value = "订单开始时间")
private Date orderDate;
@ApiModelProperty(value = "商品订单数量")
private Integer productNumber;
@ApiModelProperty(value = "商品价格")
private BigDecimal productPrice;
@ApiModelProperty(value = "订单总价")
private BigDecimal totalPrice;
public Order() {
}
public Order(String orderId, String userName, String productId, String productName, Date orderDate, Integer productNumber, BigDecimal productPrice, BigDecimal totalPrice) {
this.orderId = orderId;
this.userName = userName;
this.productId = productId;
this.productName = productName;
this.orderDate = orderDate;
this.productNumber = productNumber;
this.productPrice = productPrice;
this.totalPrice = totalPrice;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public Date getOrderDate() {
return orderDate;
}
public void setOrderDate(Date orderDate) {
this.orderDate = orderDate;
}
public Integer getProductNumber() {
return productNumber;
}
public void setProductNumber(Integer productNumber) {
this.productNumber = productNumber;
}
public BigDecimal getProductPrice() {
return productPrice;
}
public void setProductPrice(BigDecimal productPrice) {
this.productPrice = productPrice;
}
public BigDecimal getTotalPrice() {
return totalPrice;
}
public void setTotalPrice(BigDecimal totalPrice) {
this.totalPrice = totalPrice;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Order order = (Order) o;
if (!Objects.equals(orderId, order.orderId)) {
return false;
}
if (!Objects.equals(userName, order.userName)) {
return false;
}
if (!Objects.equals(productId, order.productId)) {
return false;
}
if (!Objects.equals(productName, order.productName)) {
return false;
}
if (!Objects.equals(orderDate, order.orderDate)) {
return false;
}
if (!Objects.equals(productNumber, order.productNumber)) {
return false;
}
if (!Objects.equals(productPrice, order.productPrice)) {
return false;
}
return Objects.equals(totalPrice, order.totalPrice);
}
@Override
public int hashCode() {
int result = orderId != null ? orderId.hashCode() : 0;
result = 31 * result + (userName != null ? userName.hashCode() : 0);
result = 31 * result + (productId != null ? productId.hashCode() : 0);
result = 31 * result + (productName != null ? productName.hashCode() : 0);
result = 31 * result + (orderDate != null ? orderDate.hashCode() : 0);
result = 31 * result + (productNumber != null ? productNumber.hashCode() : 0);
result = 31 * result + (productPrice != null ? productPrice.hashCode() : 0);
result = 31 * result + (totalPrice != null ? totalPrice.hashCode() : 0);
return result;
}
}
Product 实体类
package com.ming.pojo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.util.Objects;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/8 14:48
*/
@ApiModel("商品类")
public class Product {
@ApiModelProperty(value = "商品id")
private String productId;
@ApiModelProperty(value = "商品名称")
private String productName;
@ApiModelProperty(value = "商品价格")
private BigDecimal productPrice;
@ApiModelProperty(value = "仓库库存数量")
private Integer warehousingNumber;
@ApiModelProperty(value = "售出数量")
private String soldNumber;
@ApiModelProperty(value = "入库时间")
private String warehousingDate;
@ApiModelProperty(value = "商品优惠")
private BigDecimal discount;
public Product() {
}
public Product(String productId, String productName, BigDecimal productPrice, Integer warehousingNumber, String soldNumber, String warehousingDate, BigDecimal discount) {
this.productId = productId;
this.productName = productName;
this.productPrice = productPrice;
this.warehousingNumber = warehousingNumber;
this.soldNumber = soldNumber;
this.warehousingDate = warehousingDate;
this.discount = discount;
}
public String getProductId() {
return productId;
}
public void setProductId(String productId) {
this.productId = productId;
}
public String getProductName() {
return productName;
}
public void setProductName(String productName) {
this.productName = productName;
}
public BigDecimal getProductPrice() {
return productPrice;
}
public void setProductPrice(BigDecimal productPrice) {
this.productPrice = productPrice;
}
public Integer getWarehousingNumber() {
return warehousingNumber;
}
public void setWarehousingNumber(Integer warehousingNumber) {
this.warehousingNumber = warehousingNumber;
}
public String getSoldNumber() {
return soldNumber;
}
public void setSoldNumber(String soldNumber) {
this.soldNumber = soldNumber;
}
public String getWarehousingDate() {
return warehousingDate;
}
public void setWarehousingDate(String warehousingDate) {
this.warehousingDate = warehousingDate;
}
public BigDecimal getDiscount() {
return discount;
}
public void setDiscount(BigDecimal discount) {
this.discount = discount;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Product product = (Product) o;
if (!Objects.equals(productId, product.productId)) {
return false;
}
if (!Objects.equals(productName, product.productName)) {
return false;
}
if (!Objects.equals(productPrice, product.productPrice)) {
return false;
}
if (!Objects.equals(warehousingNumber, product.warehousingNumber)) {
return false;
}
if (!Objects.equals(soldNumber, product.soldNumber)) {
return false;
}
if (!Objects.equals(warehousingDate, product.warehousingDate)) {
return false;
}
return Objects.equals(discount, product.discount);
}
@Override
public int hashCode() {
int result = productId != null ? productId.hashCode() : 0;
result = 31 * result + (productName != null ? productName.hashCode() : 0);
result = 31 * result + (productPrice != null ? productPrice.hashCode() : 0);
result = 31 * result + (warehousingNumber != null ? warehousingNumber.hashCode() : 0);
result = 31 * result + (soldNumber != null ? soldNumber.hashCode() : 0);
result = 31 * result + (warehousingDate != null ? warehousingDate.hashCode() : 0);
result = 31 * result + (discount != null ? discount.hashCode() : 0);
return result;
}
}
QueryResult实体类
package com.ming.pojo;
import java.util.Objects;
/**
* @author Tony_Constantine
* @version 1.0
* @date 2022/8/3 08:45
*/
public class QueryResult {
boolean success;
int code;
String message;
public QueryResult() {
}
public QueryResult(boolean success, int code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
QueryResult that = (QueryResult) o;
if (success != that.success) {
return false;
}
if (code != that.code) {
return false;
}
return Objects.equals(message, that.message);
}
@Override
public int hashCode() {
int result = (success ? 1 : 0);
result = 31 * result + code;
result = 31 * result + (message != null ? message.hashCode() : 0);
return result;
}
}
Feign层
TestFeignService类
package com.ming.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(value = "zookeeper-producer-ming",path = "/test")
//value值表示要调用服务的名字!!!!
//这个path一定要和代理对象的映射路径一致!!!!!
public interface TestFeignService {
/**
* @description: 无
* @param:
* @return:
* @return: java.lang.String
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@GetMapping("/uuid")
public String getUuid();
}
OrderFeignService类
package com.ming.feign;
import com.ming.pojo.Order;
import com.ming.pojo.QueryResult;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@FeignClient(value = "zookeeper-producer-ming",path = "/o")
//value值表示要调用服务的名字!!!!
//这个path一定要和代理对象的映射路径一致!!!!!
public interface OrderFeignService {
/**
* @description: 无
* @param:
* @param orderId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@GetMapping("/find_order_by_orderid/{orderId}")
List<Order> findOrderByOrderId(@PathVariable("orderId") String orderId);
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@GetMapping("/all")
List<Order> findAllOrder();
/**
* @description: 无
* @param:
* @param userName
* @param productId
* @param productName
* @param productNumber
* @param productPrice
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@PostMapping("/add/{userName}/{productId}/{productName}/{productNumber}/{productPrice}")
QueryResult addOrder(@PathVariable("userName") String userName,
@PathVariable("productId") String productId,
@PathVariable("productName") String productName,
@PathVariable("productNumber") Integer productNumber,
@PathVariable("productPrice") Double productPrice
);
}
Congtroller层
TestController类
package com.ming.cotroller;
import com.ming.feign.TestFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RequestMapping("/test")
@RestController
public class Testcontroller {
@Autowired
TestFeignService testFeignService;
/**
* @description: 无
* @param:
* @return:
* @return: java.lang.String
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@GetMapping("/uuid")
public String getUuid(){
return testFeignService.getUuid();
};
}
OrderController类
package com.ming.cotroller;
import com.ming.feign.OrderFeignService;
import com.ming.pojo.Order;
import com.ming.pojo.QueryResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.websocket.server.PathParam;
import java.util.List;
@RequestMapping("/o")
@RestController
public class Ordercontroller {
@Autowired
OrderFeignService orderFeign;
// @GetMapping("/test")
// public String getUUID(){
// return testFeign.getUUID();
// }
/**
* @description: 无
* @param:
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
@GetMapping("/all")
public List<Order> orderList(){
List<Order> allOrder = orderFeign.findAllOrder();
return allOrder;
}
/**
* @description: 无
* @param:
* @param userName
* @param productId
* @param productName
* @param productNumber
* @param productPrice
* @return:
* @return: com.aseit.elec.pojo.QueryResult
* @author Yiming_Chato
* @date: 2022/8/18 11:41
*/
@PostMapping("/add")
public QueryResult addOrder(@PathParam("userName") String userName,
@PathParam("productId") String productId,
@PathParam("productName") String productName,
@PathParam("productNumber") Integer productNumber,
@PathParam("productPrice") Double productPrice){
QueryResult queryResult = orderFeign.addOrder(userName, productId, productName, productNumber, productPrice);
return queryResult;
}
/**
* @description: 无
* @param:
* @param orderId
* @return:
* @return: java.util.List<com.aseit.elec.pojo.Order>
* @author Yiming_Chato
* @date: 2022/8/18 11:42
*/
@GetMapping("/find_order_by_orderid/{orderId}")
List<Order> findOrderByOrderId(@PathVariable("orderId") String orderId){
return orderFeign.findOrderByOrderId(orderId);
}
}
五、运行效果
文件架构
整体项目的文件结构是:
生产者服务端:
消费者服务端:
运行效果:
首先我们先不查数据库,行用TestFeignService测试,查看Feign是否能正常运行,如果消费者能调用到生产者,这说明没有问题,可以继续测数据库里的数据,如果不能,在控制台查看错误信息,一定要重新审查一遍代码。
TestFeignService 生产者运行结果:
Apifox:
Chrome浏览器
如果生产者查询都无法出现结果,就一定是接口出问题,重新在过一遍后端Mapper------->Service--------->Controller----------->浏览器,这个流程。如果没问题在继续下面的流程。
TestFeignService 消费者运行结果:
Apifox:
Chrome浏览器
如果这一步不能运行,说明Feign或者Zookeeper在项目中配置有问题,具体要根据控制台提示的错误,百度查询一下。
如果能够运行,就可接着文章进行下一步测试。
1、(生产者端)查询全部订单信息:
Apifox:
Chrome浏览器:
2、(消费者端)查询全部订单信息:
Apifox:
Chrome浏览器:
3、(生产者端)添加一个订单
Apifox:
4、(消费者端)添加一个订单
Apifox:
5、(生产者端)根据orderID查询订单
Apifox:
Chrome:
6、(消费者端)根据orderID查询订单
Apifox:
Chrome浏览器:
到这里这个项目就运行结束了,当然肯定有小伙伴觉得跟着做,对自己作用不大,还得自己理解,按照自己思路去吧整个流程过一遍,因此我留了一个小作业,大家伙可以选择完成,就是可以自己根据OrderFeignService去实现ProductFeignService。
加油!!小伙子!
你和架构师又近了一步!!!!!
代码仓库:https://gitee.com/Chato/hm-zookeeper-demo
六、遇到的问题以及解决方法
1、Zookeeper闪退问题
首先在zkServer.cmd末尾加pause
(1)提示:
‘java’ 不是内部或外部命令,也不是可运行的程序或批处理文件。
可以去这个网站
(2)提示:
找不到或无法加载主类org.apache.zookeeper.server.quorum.QuorumPeerMain
可以去这个网站
2、一定要严格按照上面的dom添加依赖,否则出错会很难查找!!!,如果依赖一直爆红,就把maven仓库里的文件全部先删了,然后再重新打开自己写的项目。
3、Pom文件中各依赖的版本千万搭配好(上面的依赖已经搭配好了,切莫随意修改),我就是因为依赖的问题花费了许多时间,在依赖不匹配上,当然这个感觉是每个人在学习Spring boot 和 Spring cloud的一个“必经过程”,只有出错,你又希望去解决它,这才会有新的收获,程序员总是在Bug中成长的。
七、收获
1、这个demo虽然功能不是那么难,但是这个项目,算是我从“学习”到“工作”的过渡,不论是Feign中间件和是代码规范都是比较规范的(个人感jio),以前在学习向训练项目的时候,代码写的随心所欲,什么规范,什么逻辑,不说别人看我的代码,就算我自己在看一遍也不是能一眼看出,我写的是个什么玩意,可读性和可维护性就很差。这个项目虽然看上去代码量多,但是有很大一部分是注释,方便再次阅读以及他人阅读。
2、这个项目对于我自身来说,学到最深的一点就是,规范自己依赖包的书写以及依赖包版本一致性问题,在这个上面我花的时间比写功能的时间多得多,但是有收获总是最好的结果。
3、因为害怕大家根据上面代码,还是运行不了,所以建了一个仓库,直接用给git的clone命令就能拉取代码,或者简单粗暴直接下ZIP文件,就可以了,所以我又把git命令熟悉了一遍。
八、致谢
本文微服务部分,部分引用CSDN博主「kaikeba」的原创文章。
原文链接:https://blog.csdn.net/kaikeba/article/details/119896337
本文注册中心部分,部分引用来自51CTO博客作者sqtce的原创作品
zookeeper 做注册中心详细介绍
https://blog.51cto.com/u_536410/4197625