说明

我看了一些教程要么写的太入门、要么就是写的太抽象。真正好的文章应该是快速使人受益的而不是浪费时间。本文通过一个包括组织、部门、员工等服务交互的案例让刚接触spring cloud微服务的朋友快速上手。内容收集改造自网络,希望对大家有所帮助:)

本文涵盖以下知识点:

  • 使用Spring Boot 2.6.x开发各个微服务模块。
  • Spring Cloud Config提供配置中心
  • Spring Cloud Eureka提供服务注册和发现服务
  • Spring Cloud Gateway提供API网关
  • Spring Cloud Sleuth提供服务日志(可选)
  • Spring Cloud openfeign提供服务接口调用
  • springdoc-openapi提供接口API文档

有关各个组件的,不在过多介绍。

系统架构

有三个独立的Spring Boot微服务,它们在服务发现中注册自己,从配置服务中获取属性,并相互通信。整个系统隐藏在API网关后面。服务调用采用

项目源码

https://gitee.com/indexman/spring_cloud_sample

开发步骤

只展示部分关键代码,详细请看源码。

1.搭建父工程

创建一个父工程:spring_cloud_sample,添加pom.xml:

<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/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.laoxu.java</groupId><artifactId>spring_cloud_sample</artifactId><version>0.0.1-SNAPSHOT</version><name>spring_cloud_sample</name><packaging>pom</packaging><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.1</version><relativePath /></parent><properties><java.version>1.8</java.version><spring-cloud.version>2021.0.0</spring-cloud.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>${spring-cloud.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><modules><module>config-service</module><module>discovery-service</module><module>employee-service</module><module>department-service</module><module>organization-service</module><module>gateway-service</module></modules>
</project>

2.创建配置中心config-service

2.1 添加依赖

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-config-server</artifactId>
</dependency>

2.2 添加配置

启用读取本地配置文件需要设置:spring.profiles.active=native

server:port: 8088
spring:profiles:active: native

2.3 添加启动类

@SpringBootApplication
@EnableConfigServer
public class ConfigApplication {public static void main(String[] args) {new SpringApplicationBuilder(ConfigApplication.class).run(args);}
}
  • 本地配置文件
    各服务的配置都放在这个config文件夹下,启动后会自动读取。

3.创建服务发现discovery-service

3.1 添加依赖

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency></dependencies>

3.2 添加配置文件

注意:启动配置文件都在配置中心config-service resources目录下,此处都是去读取配置中心的各个配置,name一定不要配错!

spring:application:name: discovery-serviceconfig:import: "optional:configserver:http://localhost:8088"

3.3 添加启动类

@SpringBootApplication
@EnableEurekaServer
public class DiscoveryApplication {public static void main(String[] args) {new SpringApplicationBuilder(DiscoveryApplication.class).run(args);}}

4.创建员工服务employee-service

注意每个微服务必须在启动期间执行一些操作。

  • 从 config-service 获取配置,
  • 在 discovery-service 中注册自己
  • 暴露 HTTP API 并自动生成 API 文档。

为了实现以上操作,我们需要在 pom.xml 中包含一些依赖项。 要读取配置中心,需要依赖starter spring-cloud-starter-config。 依赖spring-cloud-starter-netflix-eureka-client并使用 @EnableDiscoveryClient 注释主类后,微服务就能注册到发现服务。 此外 Spring Boot 应用程序生成 API 文档,此处我们使用Spring REST Docs

4.1 添加依赖

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId></dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-webmvc-core</artifactId><version>1.5.13</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies>

4.2 添加启动类

注意启动类主要做了2件事:

  1. 启用api文档配置
  2. 初始化employee数据

后续的部门和组织模块与此类似。

@SpringBootApplication
@OpenAPIDefinition(info =@Info(title = "Employee API", version = "1.0", description = "Documentation Employee API v1.0")
)
public class EmployeeApplication {public static void main(String[] args) {SpringApplication.run(EmployeeApplication.class, args);}@BeanEmployeeRepository repository() {EmployeeRepository repository = new EmployeeRepository();repository.add(new Employee(1L, 1L, "John Smith", 34, "Analyst"));repository.add(new Employee(1L, 1L, "Darren Hamilton", 37, "Manager"));repository.add(new Employee(1L, 1L, "Tom Scott", 26, "Developer"));repository.add(new Employee(1L, 2L, "Anna London", 39, "Analyst"));      repository.add(new Employee(1L, 2L, "Patrick Dempsey", 27, "Developer"));repository.add(new Employee(2L, 3L, "Kevin Price", 38, "Developer"));      repository.add(new Employee(2L, 3L, "Ian Scott", 34, "Developer"));repository.add(new Employee(2L, 3L, "Andrew Campton", 30, "Manager"));repository.add(new Employee(2L, 4L, "Steve Franklin", 25, "Developer"));repository.add(new Employee(2L, 4L, "Elisabeth Smith", 30, "Developer"));return repository;}}

4.3 添加接口

@RestController
public class EmployeeController {private static final Logger LOGGER = LoggerFactory.getLogger(EmployeeController.class);@AutowiredEmployeeRepository repository;@PostMapping("/")public Employee add(@RequestBody Employee employee) {LOGGER.info("Employee add: {}", employee);return repository.add(employee);}@GetMapping("/{id}")public Employee findById(@PathVariable("id") Long id) {LOGGER.info("Employee find: id={}", id);return repository.findById(id);}@GetMapping("/")public List<Employee> findAll() {LOGGER.info("Employee find");return repository.findAll();}@GetMapping("/department/{departmentId}")public List<Employee> findByDepartment(@PathVariable("departmentId") Long departmentId) {LOGGER.info("Employee find: departmentId={}", departmentId);return repository.findByDepartment(departmentId);}@GetMapping("/organization/{organizationId}")public List<Employee> findByOrganization(@PathVariable("organizationId") Long organizationId) {LOGGER.info("Employee find: organizationId={}", organizationId);return repository.findByOrganization(organizationId);}}

5.创建部门服务department-service

5.1 添加依赖

同4.1,略

5.2 添加启动类

@SpringBootApplication
@EnableFeignClients
@OpenAPIDefinition(info =@Info(title = "Department API", version = "1.0", description = "Documentation Department API v1.0")
)
public class DepartmentApplication {public static void main(String[] args) {SpringApplication.run(DepartmentApplication.class, args);}@BeanDepartmentRepository repository() {DepartmentRepository repository = new DepartmentRepository();repository.add(new Department(1L, "Development"));repository.add(new Department(1L, "Operations"));repository.add(new Department(2L, "Development"));repository.add(new Department(2L, "Operations"));     return repository;}}

5.3 添加接口

@RestController
public class DepartmentController {private static final Logger LOGGER = LoggerFactory.getLogger(DepartmentController.class);DepartmentRepository repository;EmployeeClient employeeClient;public DepartmentController(DepartmentRepository repository, EmployeeClient employeeClient) {this.repository = repository;this.employeeClient = employeeClient;}@PostMapping("/")public Department add(@RequestBody Department department) {LOGGER.info("Department add: {}", department);return repository.add(department);}@GetMapping("/{id}")public Department findById(@PathVariable("id") Long id) {LOGGER.info("Department find: id={}", id);return repository.findById(id);}@GetMapping("/")public List<Department> findAll() {LOGGER.info("Department find");return repository.findAll();}@GetMapping("/organization/{organizationId}")public List<Department> findByOrganization(@PathVariable("organizationId") Long organizationId) {LOGGER.info("Department find: organizationId={}", organizationId);return repository.findByOrganization(organizationId);}@GetMapping("/organization/{organizationId}/with-employees")public List<Department> findByOrganizationWithEmployees(@PathVariable("organizationId") Long organizationId) {LOGGER.info("Department find: organizationId={}", organizationId);List<Department> departments = repository.findByOrganization(organizationId);departments.forEach(d -> d.setEmployees(employeeClient.findByDepartment(d.getId())));return departments;}}

6.创建组织服务organization-service

6.1 添加依赖

同4.1,略

6.2 添加启动类

@SpringBootApplication
@EnableFeignClients
@OpenAPIDefinition(info =@Info(title = "Organization API", version = "1.0", description = "Documentation Organization API v1.0")
)
public class OrganizationApplication {public static void main(String[] args) {SpringApplication.run(OrganizationApplication.class, args);}@BeanOrganizationRepository repository() {OrganizationRepository repository = new OrganizationRepository();repository.add(new Organization("Microsoft", "Redmond, Washington, USA"));repository.add(new Organization("Oracle", "Redwood City, California, USA"));   return repository;}}

6.3 添加接口

@RestController
public class OrganizationController {private static final Logger LOGGER = LoggerFactory.getLogger(OrganizationController.class);@AutowiredOrganizationRepository repository;@AutowiredDepartmentClient departmentClient;@AutowiredEmployeeClient employeeClient;@PostMappingpublic Organization add(@RequestBody Organization organization) {LOGGER.info("Organization add: {}", organization);return repository.add(organization);}@GetMappingpublic List<Organization> findAll() {LOGGER.info("Organization find");return repository.findAll();}@GetMapping("/{id}")public Organization findById(@PathVariable("id") Long id) {LOGGER.info("Organization find: id={}", id);return repository.findById(id);}@GetMapping("/{id}/with-departments")public Organization findByIdWithDepartments(@PathVariable("id") Long id) {LOGGER.info("Organization find: id={}", id);Organization organization = repository.findById(id);organization.setDepartments(departmentClient.findByOrganization(organization.getId()));return organization;}@GetMapping("/{id}/with-departments-and-employees")public Organization findByIdWithDepartmentsAndEmployees(@PathVariable("id") Long id) {LOGGER.info("Organization find: id={}", id);Organization organization = repository.findById(id);organization.setDepartments(departmentClient.findByOrganizationWithEmployees(organization.getId()));return organization;}@GetMapping("/{id}/with-employees")public Organization findByIdWithEmployees(@PathVariable("id") Long id) {LOGGER.info("Organization find: id={}", id);Organization organization = repository.findById(id);organization.setEmployees(employeeClient.findByOrganization(organization.getId()));return organization;}}

7.创建网关服务gateway-service

  • 关于网关gateway
    Spring Cloud Gateway 提供了三个用于配置的基本组件:路由(routes)、谓词(predicates )和过滤器(filters)。 路由是网关的基本构建块。 它包含一个目标 URI 和定义的谓词和过滤器列表。 Predicate 负责匹配来自传入 HTTP 请求的任何内容,例如请求头或参数。 过滤器可以在发送到下游服务之前和之后修改请求和响应。 所有这些组件都可以使用配置属性进行设置。 我们为示例微服务定义的路由创建并放置在配置服务器文件 gateway-service.yml。

7.1 添加依赖

<dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-sleuth</artifactId></dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-webflux-core</artifactId><version>1.5.13</version></dependency><dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-webflux-ui</artifactId><version>1.5.13</version></dependency></dependencies>

7.2 添加启动类

@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApplication {private static final Logger LOGGER = LoggerFactory.getLogger(GatewayApplication.class);public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}@AutowiredRouteDefinitionLocator locator;@Beanpublic List<GroupedOpenApi> apis() {List<GroupedOpenApi> groups = new ArrayList<>();List<RouteDefinition> definitions = locator.getRouteDefinitions().collectList().block();assert definitions != null;definitions.stream().filter(routeDefinition -> routeDefinition.getId().matches(".*-service")).forEach(routeDefinition -> {String name = routeDefinition.getId().replaceAll("-service", "");groups.add(GroupedOpenApi.builder().pathsToMatch("/" + name + "/**").group(name).build());});return groups;}}

7.3 添加中心化配置

server:port: 8060eureka:client:serviceUrl:defaultZone: http://localhost:8061/eureka/logging:pattern: console: "%d{yyyy-MM-dd HH:mm:ss} ${LOG_LEVEL_PATTERN:-%5p} %m%n"spring:cloud:gateway:discovery:locator:enabled: trueroutes:- id: employee-serviceuri: lb://employee-servicepredicates:- Path=/employee/**filters:- RewritePath=/employee/(?<path>.*), /$\{path}- id: department-serviceuri: lb://department-servicepredicates:- Path=/department/**filters:- RewritePath=/department/(?<path>.*), /$\{path}- id: organization-serviceuri: lb://organization-servicepredicates:- Path=/organization/**filters:- RewritePath=/organization/(?<path>.*), /$\{path}- id: openapiuri: http://localhost:${server.port}predicates:- Path=/v3/api-docs/**filters:- RewritePath=/v3/api-docs/(?<path>.*), /$\{path}/v3/api-docsspringdoc:swagger-ui:urls:- name: employeeurl: /v3/api-docs/employee- name: departmenturl: /v3/api-docs/department- name: organizationurl: /v3/api-docs/organization

8.运行测试

8.1 启动服务

  • 依次启动:
    config-servicediscovery-service
    剩下的服务顺序无限制。
  • 程序的运行逻辑参考下图:

8.1 访问api doc

访问:http://localhost:8060/swagger-ui.html

8.2 访问接口

注意:由于数据在启动时初始化到内存,所以多次查询后会发生填充,重启后才会重置。当然你也可以去修改Repository中的方法去重置,此处对于整个项目无关紧要。

  • 查询单个组织
    http://localhost:8060/organization/1
  • 查询组织下的部门列表
    http://localhost:8060/organization/1/with-departments

Spring Boot+Eureka+Spring Cloud微服务快速上手项目实战相关推荐

  1. 使用spring boot+kubernetes构建完整微服务平台

    微服务架构被认为是构建大型复杂系统的最佳理论指导,其采用了分而治之.单一职责.关注点分离等方法论来设计系统架构.微服务的实现方式和思路有很多种,本文简述基于kubernetes的微服务平台建设思路及技 ...

  2. 使用Spring Boot和Kubernetes构建微服务架构

    "我喜欢编写身份验证和授权代码." 〜从来没有Java开发人员. 厌倦了一次又一次地建立相同的登录屏幕? 尝试使用Okta API进行托管身份验证,授权和多因素身份验证. 在本教程 ...

  3. 如何使用消息队列,Spring Boot和Kubernetes扩展微服务

    by Daniele Polencic 由Daniele Polencic 如何使用消息队列,Spring Boot和Kubernetes扩展微服务 (How to scale Microservic ...

  4. 基于Spring Boot 2.5.1 微服务框架发布(Eurynome Cloud )

    企业级技术中台微服务架构与服务能力开发平台(Eurynome Cloud ) Eurynome Cloud是一款企业级技术中台微服务架构与服务能力开发平台.基于Spring Boot 2.5.1.Sp ...

  5. Spring Cloud + Spring Boot + Mybatis + shiro + RestFul + 微服务

    摘要: Commonservice-system是一个大型分布式.微服务.面向企业的JavaEE体系快速研发平台,基于模块化.服务化.原子化.热插拔的设计思想,使用成熟领先的无商业限制的主流开源技术构 ...

  6. 基于Vue+SpringCloudAlibaba微服务电商项目实战-技术选型-004:快速整合微信公众号开发

    004:快速整合微信公众号开发 1 微信公众号开发项目演示 2 微信公众号开发设计原理 3 基于natapp将本地项目发布到外网 4 对接微信公众号测试平台 5 第三方微信框架快速实现微信开发 6 微 ...

  7. 基于Vue+SpringCloudAlibaba微服务电商项目实战-构建会员服务-011:基于Vue快速整合会员服务接口

    011:基于Vue快速整合会员服务接口 1 构建前端Vue项目调用后端接口实现联合登录效果演示 2 什么是微服务前后端分离开发的模式 3 联合登录接口接口简单回顾 4 前后端分离解决跨域的问题 5 V ...

  8. 基于Vue+SpringCloudAlibaba微服务电商项目实战-商品服务-015:亿万级别商品详情页面实现动态优化

    015:亿万级别商品详情页面实现动态优化 1 亿万级别商品详情页面如何设计 2 使用Nginx缓存商品详情页面 3 使用FreeMarker生成静态化模板页面 4 openresty+lua实现亿级别 ...

  9. 基于Spring Boot和Spring Cloud实现微服务架构学习--转

    原文地址:http://blog.csdn.net/enweitech/article/details/52582918 看了几周spring相关框架的书籍和官方demo,是时候开始总结下这中间的学习 ...

最新文章

  1. 关系型数据库-三范式
  2. 20131003国庆作业例4-4,4-5,4-6.
  3. .classpath 和.project文件含义
  4. laravel里面使用event
  5. 旧电脑从win7更换成Ubuntu系统(U盘安装)
  6. Unity编辑器扩展之EditorWindow
  7. 无锡金秋购物节 淘菜菜提供社区消费全景式服务
  8. elm的 java包_README.md
  9. Windows程序开发——指挥官夏尔对于Windows程序开发框架的选择
  10. sqlu8多阶级层次bom_心理学:有这二种“长相”的男人,往往层次很高,女人可多留意...
  11. 贪心算法无重叠区间c语言,贪心算法之区间问题.md
  12. [渝粤教育] 西南科技大学 交通运输经济 在线考试复习资料
  13. 我的凸优化学习之路(转)
  14. 微运行库2015_vc++2015运行库下载_vc++2015运行库64位官方下载「vc2015」-太平洋下载中心...
  15. 浙江大学PAT考证,计算机专业的可别错过了,轻松就业+高薪
  16. 数学之美番外篇:进化论中的概率论
  17. CH0805 防线 二分
  18. matlab用方程的解赋值,Matlab隐式符号方程求解和赋值
  19. USB Type-C数据线美国新标准UL9990报告检测项目
  20. java 例外_【JAVA基础】浅析JAVA例外处理(转)

热门文章

  1. AD转换中参考电压的作用
  2. HTML哪些百度收录,四招让网站内容快速被百度收录
  3. 【产品经理】002-梁宁·产品思维30讲-同理心
  4. 小巧的Lingoes翻译家
  5. 百度有钱联盟邀请码有效期48小时
  6. Whale 帷幄技术周大咖分享:AI 迎来大洗牌
  7. Leetcode题库(数据库合集)
  8. 什么是PE? 什么是VC?
  9. Java8和Java1.8
  10. 在线转换mobi文件的软件哪个好?分享3个mobi转换软件