SpringCloud学习 系列三、 创建一个没有使用springCloud的服务提供者和消费者
系列导航
SpringCloud学习 系列一、 前言-为什么要学习微服务
SpringCloud学习 系列三、 创建一个没有使用springCloud的服务提供者和消费者
SpringCloud学习 系列四、微服务中心 Eureka介绍及创建一个Eureka中心服务
SpringCloud学习 系列五、创建生产者和消费者验证微服务中心 Eureka的作用
SpringCloud学习 系列七、EurekaServer集群创建
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的服务提供者和消费者的更多相关文章
- SpringCloud学习6-如何创建一个服务消费者consumer
上一节如何创建一个服务提供者provider已经启动了一个provider的server,提供用户信息查询接口.接下来,我们启动另一个provider,由于是同一台机器本地测试,我们换一个端口 --s ...
- SpringCloud学习5-如何创建一个服务提供者provider
前几篇主要集中在注册中心eureka的使用上,接下来可以创建服务提供者provider来注册到eureka. demo源码见: https://github.com/Ryan-Miao/spring- ...
- SpringCloud学习系列之一 ----- 搭建一个高可用的注册中心(Eureka)
前言 本篇主要介绍的是SpringCloud相关知识.微服务架构以及搭建一个高可用的服务注册与发现的服务模块(Eureka). SpringCloud介绍 Spring Cloud是在Spring B ...
- SpringCloud学习系列之三----- 断路器(Hystrix)和断路器监控(Dashboard)
前言 本篇主要介绍的是SpringCloud中的断路器(Hystrix)和断路器指标看板(Dashboard)的相关使用知识. SpringCloud Hystrix Hystrix 介绍 Netfl ...
- SpringCloud学习系列之七 ----- Zuul路由网关的过滤器和异常处理
前言 在上篇中介绍了SpringCloud Zuul路由网关的基本使用版本,本篇则介绍基于SpringCloud(基于SpringBoot2.x,.SpringCloud Finchley版)中的路由 ...
- scrapy爬虫学习系列三:scrapy部署到scrapyhub上
系列文章列表: scrapy爬虫学习系列一:scrapy爬虫环境的准备: http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_python_00 ...
- DocX开源WORD操作组件的学习系列三
DocX学习系列 DocX开源WORD操作组件的学习系列一 : http://www.cnblogs.com/zhaojiedi1992/p/zhaojiedi_sharp_001_docx1.htm ...
- RabbitMQ学习系列三-C#代码接收处理消息
RabbitMQ学习系列三:.net 环境下 C#代码订阅 RabbitMQ 消息并处理 http://www.80iter.com/blog/1438251320680361 http://www. ...
- .net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能
原文:.net reactor 学习系列(三)---.net reactor代码自动操作相关保护功能 接上篇,上篇已经学习了界面的各种功能以及各种配置,这篇准备学习下代码控制许可证. ...
- MyBatis学习系列三——结合Spring
目录 MyBatis学习系列一之环境搭建 MyBatis学习系列二——增删改查 MyBatis学习系列三——结合Spring MyBatis在项目中应用一般都要结合Spring,这一章主要把MyBat ...
随机推荐
- [ABC309G] Ban Permutation
Problem Statement Find the number, modulo $998244353$, of permutations $P=(P_1,P_2,\dots,P_N)$ of $( ...
- Microsoft Edge 分屏 推荐
前言: 很早之前就在 Edge Dev 频道的更新公告中看到过 Edge 的新分屏功能,当时没怎么注意,昨天看文档的时候发现 Edge 的侧边栏可以拖动当作一个"虚假的"分屏页面来 ...
- Python+Selenium+Webdriver+unittest 实现登录126邮箱
第一版:登录 #encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webd ...
- 解密Prompt系列21. LLM Agent之再谈RAG的召回信息密度和质量
话接上文的召回多样性优化,多路索引的召回方案可以提供更多的潜在候选内容.但候选越多,如何对这些内容进行筛选和排序就变得更加重要.这一章我们唠唠召回的信息密度和质量.同样参考经典搜索和推荐框架,这一章对 ...
- 在arm架构的银河麒麟系统部署Nginx
以下是在arm架构的银河麒麟系统上部署Nginx的详细步骤: 1. 创建文件夹 首先,在合适的位置创建必要的文件夹.在本例中,我们将创建/opt/nginx和/usr/src/nginx两个文件夹. ...
- 封装Detours用于Python中x64函数hook
Detours 代码仓库: https://github.com/microsoft/Detours x64写一个任意地址hook要比x86麻烦的多,所以这里直接封装框架来用于x64的hook. De ...
- NetSuite 开发日记:如何管理多环境自定义列表值
在 NetSuite 中可以创建自定义列表,列表可用于为其他(自定义)记录上的下拉选项列表值. var rec = record.create({ type: 'customrecord_xx' }) ...
- cs上线Linux
cs上线Linux 下载和配置crossC2 首先到项目地址:https://github.com/gloxec/CrossC2/releases下载两个文件 后缀为.cna的为cs的插件文件,启动c ...
- 11 个步骤完美排查Linux服务器是否被入侵
文章来源公众号:LemonSec 随着开源产品的越来越盛行,作为一个Linux运维工程师,能够清晰地鉴别异常机器是否已经被入侵了显得至关重要,个人结合自己的工作经历,整理了几种常见的机器被黑情况供参考 ...
- MyBatis—Spring 动态数据源事务的处理
在一般的 Spring 应用中,如果底层数据库访问采用的是 MyBatis,那么在大多数情况下,只使用一个单独的数据源,Spring 的事务管理在大多数情况下都是有效的.然而,在一些复杂的业务场景下, ...