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 ...
随机推荐
- [CF1830E] Bully Sort
题目描述 On a permutation $ p $ of length $ n $ , we define a bully swap as follows: Let $ i $ be the in ...
- 技术Leader:像李云龙一样打造学习型团队
今天跟大家分享一下怎么样构建一个学习型的团队. 首先对于计算机行业而言,不明而喻,我们要接受的东西真的太多了.我们接触的信息和变化也太多了.如果只是因循守旧,排斥新东西,那么我们被时代淘汰只是个时间问 ...
- 7、If分支语句
1.程序的流程结构 程序的流程控制结构一共有三种: 顺序结构 选择结构 循环结构. 顺序结构: 从上向下 逐行执行 选择结构:条件满足,某些代码才会执行.0-1次 分支语句: if,switch,se ...
- MySQL运维14-管理及监控工具Mycat-web的安装配置
一.Mycat-web介绍 Mycat-web(现改名为Mycat-eye)是对Mycat-server提供监控服务,通过JDBC连接对Mycat,MySQL监控,监控远程服务器的cpu,内存,网络, ...
- bash shell笔记整理——basename和dirname命令
bashname命令作用 去掉给定name的目录部分,如果指定了 SUFFIX, 就 同时去掉SUFFIX(后缀).具体看示例吧. bashname语法 Usage: basename NAME [S ...
- 可视化大屏与GIS之间如何实现互补?
在当今数字化时代,可视化大屏和地理信息系统(GIS)是两个在不同领域发挥重要作用的技术.可视化大屏以其生动.直观的图表.图像和动画展示方式,为数据可视化和信息展示提供了强大的工具.而GIS则通过地理空 ...
- ElasticSearch之健康状态
参考Cluster health API. 命令样例,如下: curl -X GET "https://localhost:9200/_cluster/health?wait_for_sta ...
- 网安区过年-Log4j2
Log4j2-2021 漏洞原理 Apache Log4j 2 是Java语言的日志处理套件,使用极为广泛.在其2.0到2.14.1版本中存在一处JNDI注入漏洞,攻击者在可以控制日志内容的情况下,通 ...
- MySQL|mysql-索引
1.索引是什么 1.1索引简介 索引是表的目录,是数据库中专门用于帮助用户快速查询数据的一种数据结构.类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,以及快速定位查询数据.对于索引 ...
- BUUCTF Web CyberPunk WriteUp
想直接查看payload的点这里 前言 二次注入(Second-Order Injection)是指攻击者在应用程序中注入恶意数据,然后在稍后的操作或不同的上下文中再次使用该恶意数据,导致安全漏洞.它 ...