Spring Cloud(一)入门

本贴最后更新于 1621 天前,其中的信息可能已经物是人非

一、微服务概述

  微服务架构是一种架构模式,或者说是一种架构风格, 它提倡将单一的应用程序划分成一组小的服务,每个服务运行在其独立的自己的进程内,服务之间互相协调,互相配置,为用户提供最终价值。

  服务之间采用轻量级的通信机制互相沟通,每个服务都围绕着具体的业务进行构建,并且能够被独立的部署到生产环境中,另外,应尽量避免统一的,集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言,工具对其进行构建,可以有一个非常轻量级的集中式管理来协调这些服务,可以使用不同的语言来编写服务,也可以使用不同的数据存储。

优点:

  • 开发简单,开发效率提高,一个服务可能就是专一的只干一件事;
  • 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的;
  • 微服务能使用不同的语言开发;
  • 每个微服务都有自己的存储能力,可以有自己的数据库,也可以有统一数据库。

缺点:

  • 开发人员要处理分布式系统的复杂性;
  • 多服务运维难度,随着服务的增加,运维的压力也在增大;
  • 系统部署依赖;
  • 服务间通信成本;
  • 数据一致性等等。

微服务技术栈:

image.png

二、Spring Cloud 概述

  SpringCloud 利用 SpringBoot 的开发便利性,巧妙地简化了分布式系统基础设施的开发,SpringCloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理,服务发现,断路器,路由,微代理,事件总线,全局锁,决策竞选,分布式会话等等,他们都可以用 SpringBoot 的开发风格做到一键启动和部署。

  SpringBoot 可以离开 SpringClooud 独立使用,开发项目,但是 SpringCloud 离不开 SpringBoot,属于依赖关系。

Dubbo 和 SpringCloud 对比

image.png

最大区别:

  SpringCloud 抛弃了 Dubbo 的 RPC 通信,采用的是基于 HTTP 的 REST 方式。严格来说,这两种方式各有优劣。虽然从一定程度上来说,后者牺牲了服务调用的性能,但也避免了原生 RPC 带来的问题。而且 REST 相比 RPC 更为灵活,服务提供方和调用方的依赖只依靠一纸契约,不存在代码级别的强依赖,这在强调快速演化的微服务环境下,显得更加合适。

三、项目构建

总体介绍:

一个父工程带着多个子 Module 子模块

SpringCloud 父工程(Project)下依次带着 3 个子模块(Module)

  • springcloud-api 【封装的整体 entity / 接口 / 公共配置等】
  • springcloud-provider-dept-8001【服务提供者】
  • springcloud-consumer-dept-80【服务消费者】

创建父工程

新建父工程 Maven 项目 springcloud-parent,切记 Packageing 是 pom 模式。

主要是定义 POM 文件,将后续各个子模块公用的 jar 包等统一提取出来,类似一个抽象父类。

image.png

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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.wlgzs</groupId> <artifactId>springcloud</artifactId> <version>1.0-SNAPSHOT</version> <!--打包方式 pom--> <packaging>pom</packaging> <properties> </properties> <dependencyManagement> <dependencies> <!--springCloud的依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR1</version> <type>pom</type> <scope>import</scope> </dependency> <!--SpringBoot--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.4.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.16</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.10</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.12</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> </dependencies> </dependencyManagement> </project>

创建 api 公共模块

image.png

可以观察发现,在父工程中多了一个 Modules

image.png

编写 springcloud-api 的 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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud</artifactId> <groupId>com.wlgzs</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>springcloud-api</artifactId> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>

编写实体类

package com.wlgzs.springcloud.entity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; /** * 部门表(Dept)表实体类 */ @Data @AllArgsConstructor @NoArgsConstructor public class Dept implements Serializable { /** * 部门ID */ private Integer deptId; /** * 部门名称 */ private String deptName; /** * 数据库 */ private String dbSource; public Dept(String deptName){ this.deptName=deptName; } }

创建 provider 模块

新建 springcloud-provider-dept-8001 模块

编辑 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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud</artifactId> <groupId>com.wlgzs</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>springcolud-provider-dept-8001</artifactId> <dependencies> <dependency> <groupId>com.wlgzs</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-test</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> </dependency> </dependencies> </project>

编辑 application.yml

server: port: 8001 mybatis: type-aliases-package: com.wlgzs.springcloud.entity configuration: map-underscore-to-camel-case: true spring: application: name: springcloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC username: root password: root

编写部门的 dao 接口

package com.wlgzs.springcloud.dao; import com.wlgzs.springcloud.entity.Dept; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import java.util.List; @Mapper public interface DeptDao { @Insert("insert into dept (dept_name,db_source)\n" + "values (#{deptName},DATABASE())") boolean addDept(Dept dept); @Select("select * from dept where dept_id = #{deptId}") Dept queryById(int deptId); @Select("select * from dept") List<Dept> queryAll(); }

创建 Service 服务层接口

package com.wlgzs.springcloud.service; import com.wlgzs.springcloud.entity.Dept; import java.util.List; public interface DeptService { boolean addDept(Dept dept); Dept queryById(int id); List<Dept> queryAll(); }

ServiceImpl 实现类

package com.wlgzs.springcloud.service; import com.wlgzs.springcloud.dao.DeptDao; import com.wlgzs.springcloud.entity.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.util.List; @Service public class DeptServiceImpl implements DeptService{ @Resource private DeptDao deptDao; public boolean addDept(Dept dept) { return deptDao.addDept(dept); } public Dept queryById(int id) { Dept dept=deptDao.queryById(id); return dept; } public List<Dept> queryAll() { List<Dept> depts=deptDao.queryAll(); return depts; } }

DeptController 提供 REST 服务

package com.wlgzs.springcloud.controller; import com.wlgzs.springcloud.entity.Dept; import com.wlgzs.springcloud.service.DeptService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController public class DeptController { @Autowired DeptService deptService; @PostMapping("/") public boolean addDept(@RequestBody Dept dept){ return deptService.addDept(dept); } @GetMapping("/{id}") public Dept getDeptById(@PathVariable int id){ return deptService.queryById(id); } @GetMapping("/") public List getAll(){ return deptService.queryAll(); } }

编写 DeptProvider 的主启动类

package com.wlgzs.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.netflix.eureka.EnableEurekaClient; @SpringBootApplication public class DeptProvider_8001 { public static void main(String[] args) { SpringApplication.run(DeptProvider_8001.class,args); } }

启动测试

image.png

创建 consumer 模块

新建 springcloud-consumer-dept-80 模块

编辑 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 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>springcloud</artifactId> <groupId>com.wlgzs</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>springcloud-consumer-dept-80</artifactId> <dependencies> <dependency> <groupId>com.wlgzs</groupId> <artifactId>springcloud-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies> </project>

application.yml 配置文件

server: port: 80

新建一个 ConfifigBean 包注入 RestTemplate

package com.wlgzs.springcloud.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class ConfigBean { @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }

创建 Controller 包,编写 DeptConsumerController 类

package com.wlgzs.springcloud.controller; import com.wlgzs.springcloud.entity.Dept; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import java.util.List; /** * @author wlgzs-sjl * @date 2020/11/21 22:17 */ @RestController public class DeptConsumerController { //理解:消费者,不应该有service层 // 使用RestTemplate访问restful接口非常的简单粗暴且无脑 // (url,requestMap,ResponseBean.class) 这三个参数分别代表 // REST请求地址,请求参数,Http响应转换 被 转换成的对象类型 @Autowired private RestTemplate restTemplate; private static final String REST_URL_PREFIX = "http://localhost:8001"; @GetMapping("/{id}") public Dept get(@PathVariable("id") int id){ return restTemplate.getForObject(REST_URL_PREFIX+"/"+id,Dept.class); } @GetMapping("/") public List getAll(){ return restTemplate.getForObject(REST_URL_PREFIX,List.class); } @PostMapping("/") public boolean add(Dept dept){ return restTemplate.postForObject(REST_URL_PREFIX,dept,Boolean.class); } }

了解 RestTemplate

  RestTemplate 提供了多种便捷访问远程 Http 服务的方法,是一种简单便捷的访问 restful 服务模板类,是 Spring 提供的用于访问 Rest 服务的客户端模板工具集

  使用 RestTemplate 访问 restful 接口非常的简单粗暴且无脑(url,requsetMap,ResponseBean.class) 这三个参数分别代表 REST 请求地址,请求参数,Http 响应转换 被 转换成的对象类型。

主启动类

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

参考 B 站教程狂神说 Java

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    949 引用 • 1460 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...