系列导航

SpringCloud学习 系列一、 前言-为什么要学习微服务

SpringCloud学习 系列二、 简介

SpringCloud学习 系列三、 创建一个没有使用springCloud的服务提供者和消费者

SpringCloud学习 系列四、微服务中心 Eureka介绍及创建一个Eureka中心服务

SpringCloud学习 系列五、创建生产者和消费者验证微服务中心 Eureka的作用

SpringCloud学习 系列六、服务平滑离线

SpringCloud学习 系列七、EurekaServer集群创建

SpringCloud学习 系列八、OpenFeign

SpringCloud学习 系列九、Ribbon

SpringCloud学习 系列十、服务熔断与降级(1-简介)

SpringCloud学习 系列十、服务熔断与降级(2-方法级别服务降级)

SpringCloud学习 系列十、服务熔断与降级(3-类级别的服务降级)

SpringCloud学习 系列十、服务熔断与降级(4-Dashboard监控仪表盘)

本系列教程期望达到的效果是,看完之后不仅仅对springCloud能干什么有所了解,更重要的是看完之后就能上手实现这些功能。好多教程写的非常好理论很全面,但是实验部分源码和测试用例不全,或者有跳跃导致读者无法独立完成实验内容,最终只是知道能干什么但是自己却不能实现出来。本系列教程将会逐步将我自己掌握的一些知识点以实验的方式展示给大家,希望大家有所收获,逐步更新中敬请期待。

创建一个没有使用springCloud的服务提供者和消费者

为了阐述为什么要用SpringCloud,本例先创建一个没有使用SpringCloud的消费者和供者的服务,然后分析一下这样的工程有什么不缺点。注:本系列中所有的实例都使用 MySQL 数据库,使用 mybatis-plus 作为持久层技术。

(1)数据库中创建表

CREATE TABLE `block_t` (
`id` int NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8; 插入实验数据:
INSERT INTO `block_t` VALUES ('1', 'oracle');
INSERT INTO `block_t` VALUES ('2', 'mysql');
INSERT INTO `block_t` VALUES ('3', '达梦');
INSERT INTO `block_t` VALUES ('4', '金仓');
INSERT INTO `block_t` VALUES ('5', 'mongo');
INSERT INTO `block_t` VALUES ('6', 'redis');

(2)创建一个空的工程

上图:Jdk选择1.8版本

3)创建一个provider模块(服务提供者)

模块名称:01-provider-8081(该模块非常重要,后面好多工程都要在该基础上进行修改,一定要保证该工程的正确性)

主要提供对表block_t的单条查询和批量查询功能。

上图:创建一个module

上图:随便选一个版本,后面直接修改pom.xml文件改成需要的版本即可。

删除如下这些没有用的文件。

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud</groupId>
<artifactId>01-provider-8081</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>01-provider-8081</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
</properties> <dependencies> <!-- mysql 数据库连接驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.11</version>
<scope>runtime</scope>
</dependency> <!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency> <!-- mybatis-plus-generator 代码自动生成-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.3.1</version>
</dependency> <!-- 省略get/set等方法 日志打印 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</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>
</dependencies> <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>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.17.RELEASE</version>
<configuration>
<mainClass>com.springcloud.ApplicationProvider8081</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </project>

配置文件

package com.springcloud.controller;

import com.springcloud.domain.Block;
import com.springcloud.service.IBlockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import java.util.Map; /**
* <p>
* 前端控制器。
* </p>
*
* @author yc
* @since 2022-07-15
*/ @RestController
@RequestMapping("/provider")
public class BlockController { @Autowired
private IBlockService iBlockService; /**
* 单记录新增。
*
* @param block 参数说明
* @return AjaxResult
*/
@PostMapping(value = "/block/add")
@ResponseBody
public int addSave(@Valid Block block) {
return iBlockService.insert(block);
} /**
* 获取数据列表。
*
* @return map
*/
@GetMapping(value = "/block/list")
@ResponseBody
public Map list( ) {
Map map = iBlockService.selectList(null);
return map;
} /**
* 根据id查询单条数据。
*
* @param blockId 参数说明
* @return Block
*/
@GetMapping(value = "/block/get/{blockId}")
@ResponseBody
public Block get(@PathVariable("blockId") Integer blockId) {
Block block = iBlockService.selectById(blockId);
return block;
} /**
* 修改保存。
* @param block 参数说明
* @return int
*/
@PostMapping(value = "/block/update/{blockId}")
@ResponseBody
public int editSave(@PathVariable("blockId")Integer blockId,@Valid Block block){
block.setId(blockId);
return iBlockService.edit(block) ;
} /**
* 根据id删除单条数据。
*
* @param blockId 参数说明
* @return int
*/
@PostMapping(value = "/block/delete/{blockId}")
@ResponseBody
public int remove(
@NotNull(message = "id不能为空!") @PathVariable("blockId") Integer blockId) {
return iBlockService.delete(blockId);
}
}
package com.springcloud.domain;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; /**
* <p>
* 。
* </p>
*
* @author yc
* @since 2022-07-15
*/
@TableName(value = "BLOCK_T")
public class Block {
private static final long serialVersionUID = 1L; @TableId
private Integer id; private String name; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public void setName(String name) {
this.name = name;
} public String getName() {
return name;
} @Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("name", getName())
.toString();
}
}
package com.springcloud.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.springcloud.domain.Block; /**
* <p>
* Mapper 接口。
* </p>
*
* @author yc
* @since 2022-07-15
*/
public interface BlockMapper extends BaseMapper<Block> { }
package com.springcloud.service;

import com.springcloud.domain.Block;

import java.util.Map;

/**
* <p>
* 服务类。
* </p>
*
* @author yc
* @since 2022-07-15
*/
public interface IBlockService {
/**
* 获取数据列表。
*
* @param block 参数说明
* @return List
*/
Map selectList(Block block); /**
* 获取单条数据。
*
* @param departId 参数说明
* @return Depart
*/
Block selectById(Integer departId); /**
* 单记录新增。
*
* @param block 参数说明
* @return status
*/
int insert(Block block); /**
* 修改保存。
*
* @param block 参数说明
* @return status
*/
int edit(Block block); /**
* 根据id删除单条数据。
*
* @param id 参数说明
* @return status
*/
int delete(Integer id);
}
package com.springcloud.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.springcloud.domain.Block;
import com.springcloud.mapper.BlockMapper;
import com.springcloud.service.IBlockService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import java.util.HashMap;
import java.util.List;
import java.util.Map; /**
* <p>
* 服务实现类。
* </p>
*
* @author yc
* @since 2022-07-15
*/
@Service
public class BlockServiceImpl implements IBlockService {
@Autowired
BlockMapper blockMapper; /**
* 获取数据列表。
*
* @param block 参数说明
* @return List
*/
@Override
public Map selectList(Block block) {
Map<String, List> reusltMap = new HashMap<>();
reusltMap.put("dataList", blockMapper.selectList(new QueryWrapper<>(block)));
return reusltMap;
} /**
* 根据id获取单条数据。
*
* @param departId 参数说明
* @return Depart
*/
@Override
public Block selectById(Integer departId) {
return blockMapper.selectById(departId);
} /**
* 单记录新增。
*
* @param block 参数说明
* @return status
*/
@Override
public int insert(Block block) {
return blockMapper.insert(block);
} /**
* 修改保存。
*
* @param block 参数说明
* @return status
*/
@Override
public int edit(Block block) {
return blockMapper.updateById(block);
} /**
* 根据id删除单条数据。
*
* @param id 参数说明
* @return status
*/
@Override
public int delete(Integer id) {
return blockMapper.deleteById(id);
}
}
package com.springcloud;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
@MapperScan("com.springcloud.mapper") //这里要注意扫描mapper文件
public class ApplicationProvider8081 { public static void main(String[] args) {
SpringApplication.run(ApplicationProvider8081.class, args);
} }

(4)创建一个consumer模块(服务使用者)

模块名称:01-consumer-8080(该模块非常重要,后面好多工程都要在该基础上进行修改,一定要保证该工程的正确性)

主要提供调用provider模块中对表block_t的单条查询和批量查询功能的controller。

方法类似上面的步骤不在重复。

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.springcloud</groupId>
<artifactId>01-consumer-8080</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>01-consumer-8081</name>
<description>Demo project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.1.6.RELEASE</spring-boot.version>
</properties> <dependencies> <!-- 省略get/set等方法 日志打印 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency> <dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</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>
</dependencies> <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>
</dependencies>
</dependencyManagement> <build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.17.RELEASE</version>
<configuration>
<mainClass>com.springcloud.ApplicationConsumer8080</mainClass>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build> </project>

配置文件

package com.springcloud.configure;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;
import org.springframework.web.client.RestTemplate; @Controller
public class BlockCodeConfigure { @Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
package com.springcloud.controller;

import com.springcloud.domain.Block;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Map; /**
* <p>
* 前端控制器。
* </p>
*
* @author yc
* @since 2022-07-15
*/ @RestController
@RequestMapping("/consumer")
public class BlockController { @Autowired
private RestTemplate restTemplate;
private static final String SERVICE_PROVIDER = "http://localhost:8081"; /**
* 获取数据列表。
*
* @param block 参数说明
* @return map
*/
@GetMapping(value = "/block/list")
@ResponseBody
public Map list(Block block) {
String url = SERVICE_PROVIDER + "/provider/block/list";
return restTemplate.getForObject(url, Map.class);
} /**
* 根据id查询单条数据。
*
* @param blockId 参数说明
* @return Block
*/
@GetMapping(value = "/block/get/{blockId}")
@ResponseBody
public Block get(@PathVariable("blockId") Integer blockId) {
String url = SERVICE_PROVIDER + "/provider/block/get/"+blockId;
return restTemplate.getForObject(url, Block.class);
} }
package com.springcloud.domain;

import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle; /**
* <p>
* 。
* </p>
*
* @author yc
* @since 2022-07-15
*/ public class Block {
private static final long serialVersionUID = 1L; private Integer id; private String name; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public void setName(String name) {
this.name = name;
} public String getName() {
return name;
} @Override
public String toString() {
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("name", getName())
.toString();
}
}
package com.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication
public class ApplicationConsumer8080 { public static void main(String[] args) {
SpringApplication.run(ApplicationConsumer8080.class, args);
} }

删除如下这些没用的文件

(5) 效果展示

<1>直接调用01-provider-8081工程中的接口(只看单条查询的接口)

<2>调用01-consumer-8080中的接口,01-consumer-8080中的接口在调用01-provider-8081工程中的接口(只看单条查询的接口)

6、这种服务存在的问题

(1)01-consumer-8080中直接调用服务者的服务,只能写一个服务者的地址,01-provider-8081挂了就没有服务了。

(2)调用服务提供者使用的是ip而不是服务名,如果服务提供者更换了主机,服务调用者也得修改代码。

(3)如果有很多consumer,服务提供者provider的压力无法分担容易出现性能瓶颈。

如何解决这个问题就要进入下一章“微服务中心 Eureka”

SpringCloud学习 系列三、 创建一个没有使用springCloud的服务提供者和消费者的更多相关文章

  1. SpringCloud学习6-如何创建一个服务消费者consumer

    上一节如何创建一个服务提供者provider已经启动了一个provider的server,提供用户信息查询接口.接下来,我们启动另一个provider,由于是同一台机器本地测试,我们换一个端口 --s ...

  2. SpringCloud学习5-如何创建一个服务提供者provider

    前几篇主要集中在注册中心eureka的使用上,接下来可以创建服务提供者provider来注册到eureka. demo源码见: https://github.com/Ryan-Miao/spring- ...

  3. SpringCloud学习系列之一 ----- 搭建一个高可用的注册中心(Eureka)

    前言 本篇主要介绍的是SpringCloud相关知识.微服务架构以及搭建一个高可用的服务注册与发现的服务模块(Eureka). SpringCloud介绍 Spring Cloud是在Spring B ...

  4. SpringCloud学习系列之三----- 断路器(Hystrix)和断路器监控(Dashboard)

    前言 本篇主要介绍的是SpringCloud中的断路器(Hystrix)和断路器指标看板(Dashboard)的相关使用知识. SpringCloud Hystrix Hystrix 介绍 Netfl ...

  5. SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理

    前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...

  6. scrapy爬虫学习系列三:scrapy部署到scrapyhub上

    系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备:      http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...

  7. DocX开源WORD操作组件的学习系列三

    DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...

  8. RabbitMQ学习系列三-C#代码接收处理消息

    RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理 http://www.80iter.com/blog/1438251320680361 http://www. ...

  9. .net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能

    原文:.net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能         接上篇,上篇已经学习了界面的各种功能以及各种配置,这篇准备学习下代码控制许可证. ...

  10. MyBatis学习系列三——结合Spring

    目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...

随机推荐

  1. vertx的学习总结1

    一.  vertx是什么?   答:lib工具包 二.  为什么要使用vertx 答: 异步和非阻塞:Vert.x 采用了事件驱动和非阻塞的编程模型,可以处理大量并发请求而不会阻塞线程,提供更好的响应 ...

  2. C和C++练习

    要点: 1.数组 2.冒泡排序BubbleSort 3.带指针的结构体(malloc,free) 4.字符串操作(拷贝.逆序.比较) 5.格式化输出printf,sprintf 6.格式化输入,sca ...

  3. 使用pip或者手动安装第三方库出现“由于目标计算机积极拒绝,无法连接”错误的解决办法

    网上找了很多地方,都没找到怎么解决,之前用pip安装成功过,但是翻过墙后,pip安装第三方库的时候发现错误,如图:

  4. C++中数字与字符串之间的转换(转载自http://www.cnblogs.com/luxiaoxun/)

    C++中数字与字符串之间的转换   1.字符串数字之间的转换(1)string --> char *   string str("OK");   char * p = str ...

  5. Python代码中的偏函数

    技术背景 在数学中我们都学过偏导数\(\frac{\partial f(x,y)}{\partial x}\),而这里我们提到的偏函数,指的是\(f(y)(x)\).也就是说,在代码实现的过程中,虽然 ...

  6. 为什么许多数字孪生产品开始了GIS融合的尝试?

    随着数字孪生技术的发展,越来越多的产品意识到要实现数字孪生的最大价值,需要考虑多个维度的数据,包括空间信息.地理位置.环境条件等.因此,许多数字孪生产品开始了与GIS系统的融合尝试,以进一步提升其功能 ...

  7. 万界星空科技五金家具企业MES案例介绍

    五金家具行业MES解决方案 MES系统如何与家具企业生产相匹配?相较于其它大多数工业软件,MES系统无疑是受企业欢迎的软件之一.MES系统处于制造生产企业信息化的核心领域,有着承上启下的作用.那MES ...

  8. xml的语法总结

    xml的语法总结

  9. 文心一言 VS 讯飞星火 VS chatgpt (175)-- 算法导论13.3 4题

    四.用go语言,Teach 教授担心 RB-INSERT-FIXUP可能将 T.nil.color 设为 RED,这时,当 z 为根时第1行的测试就不会让循环终止.通过讨论 RB-INSERT-FIX ...

  10. Flutter PageView(轮动图)

    Flutter中的轮动图以及抖音上下滑页切换视频功能等等,这些都可以通过 PageView 轻松实现 PageView常见属性: PageView 的使用 class MyPage extends S ...