1.前言
基于之前的博客中提到的分布式框架实现:
SpringBoot整合分布式Dubbo+Zookeeper
在SpringBoot中整合了分布式微服务组件Dubbo、Zookeeper,使用RPC通信方式实现了服务提供方Provider和服务消费方Consumer之间的远程接口调用。
今天来学习大名鼎鼎的SpringCloud微服务框架,这里要讲到的是SpringCloud采用的是基于HTTP的Rest协议调用方式,使用到的最重要的Bean组件就是
RestTemplate。
RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。虽然在性能上不如RPC远程调用,但是却不存在代码级别的强依赖,基于Restful风格的接口调用显得更为灵活。
这种开发方式,在强调快速演化的微服务环境下,显得更加合适。
下面这里将以简单地方式基于RestTemplate实现一个SpringBoot与Mybatis框架下的模块微服务通信方式,在此基础上再添加SpringCloud框架及其组件。也算是对之前
的Dubbo和Zookeeper知识做了一次回顾对比学习。
2.微服务框架构建
2.1.整体服务框架依赖说明
该项目有一个maven父模块,其中里面有三个子模块:
springcloud_hello:整体父工程。
springcloud-api:公共子模块,放公共实体对象。
springcloud-provider-dept-8001:部门微服务提供者。提供微服务HTTP调用接口。
springcloud-consumer-dept-8002:部门微服务消费者。调用部分微服务提供者接口进行CRUD操作。
2.2.父工程构建
创建简单的Maven项目springcloud_hello,配置主要的pom依赖、添加相应的组件:
<!--打包方式为pom--> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> </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依赖:2.1.4.RELEASE版本对应springcloud为Greenwich.SR1--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>2.1.4.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> <!--springboot启动器--> <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> <!--junit--> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> </dependency> <!--lombok--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <!--数据库:mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency> </dependencies> </dependencyManagement>
2.3.构建公共POJO项目api
这里主要就是将springcloud-api添加至parent父项目的依赖中进行创建:
<!--每添加一个子项目都会在这里面进行增加一个子module,服务 提供者和调用者都是类似操作,不再累述--> <modules> <module>springcloud-api</module> <module>springcloud-provider-dept-8001</module> <module>springcloud-consumer-dept-8002</module> </modules>
添加lombok组件,并创建POJO类:
<!--当前的Module需要的依赖如果在父依赖中已经设置了版本号, 这里就不需要再重复设置了--> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
@Data @NoArgsConstructor @Accessors(chain = true) //链式写法 public class Dept{ private Long deptno; private String dname; private String dbSource; public Dept(String dname) { this.dname = dname; } }
2.4.创建微服务提供方
主要思路:
引入pom依赖(调用api公共module)→ 配置application.yml连接池 → 连接mysql数据库配置 → 创建并向外暴露服务接口(mapper/service/controller)
→ 启动服务检查
①导入依赖配置相关:
<dependencies> <!--需要拿到实体类,引入api module--> <dependency> <groupId>com.fengye</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>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</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> <!--jetty服务器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jetty</artifactId> </dependency> <!--热部署工具--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> </dependency> </dependencies>
②yml配置:
server: port: 8001 #mybatis的配置 mybatis: #config-location: classpath:mybatis/mybatis-config.xml type-aliases-package: com.fengye.springcloud.pojo mapper-locations: classpath:mybatis/mapper/*Mapper.xml #注意config-location: classpath:mybatis/mybatis-config.xml不能与 #驼峰一起使用 configuration: map-underscore-to-camel-case: true #spring的配置 spring: application: name: springcloud-provider-dept datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/springcloud_db01?useUnicode=true&characterEncoding=utf-8 username: root password: admin
③建库、建表、mybatis操作数据库dao/service/controller一套操作CRUD这里就不多说了(有兴趣去看我的源码),主要看一下controller层暴露的服务接口:
@RestController @RequestMapping("/dept") public class DeptController { @Autowired private DeptService service; @PostMapping("/add") public boolean addDept(Dept dept){ return service.addDept(dept); }; @GetMapping("/queryById/{id}") public Dept queryById(@PathVariable("id") Long id){ return service.queryById(id); }; @GetMapping("/queryAll") public List<Dept> queryAll(){ return service.queryAll(); }; }
④测试验证服务:
先做个小测试,看数据库连接是否成功,调用api模块是否成功。
完美访问!
2.5.创建微服务消费者
主要思路:
简单依赖pom配置、开放web消费访问端口 → 基于Config创建RestTemplate Bean → 使用RestTemplate请求访问服务提供方的远程服务端口 → 测试请求访问是否成功
①pom依赖配置、端口开放:
<dependencies> <dependency> <groupId>com.fengye</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>
server:
port: 8002
②创建Config来生成RestTemplate的Bean:
@Configuration public class SpringBeanConfig { @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
③使用RestTemplate访问远端服务接口:
@RestController public class DeptConsumerController { /** * 消费者:不应该有service实现层 * RestTemplate:提供多种便捷的访问远程http服务的方法,提供简单的restful服务模板(使用简单无脑粗暴) * 参数类型:(url, requestMap, ResponseBean.class)分别代表REST请求地址、请求参数、HTTP响应转换被转换成的对象类型 */ @Autowired private RestTemplate restTemplate; //服务端的请求地址,这里是本机localhost,也可以是其他任意的服务机ip地址 private static final String REST_URL_PREFIX = "http://localhost:8001"; @RequestMapping("/consumer/dept/add") public boolean add(Dept dept){ return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add", dept, Boolean.class); } @RequestMapping("/consumer/dept/get/{id}") public Dept get(@PathVariable("id") Long id){ return restTemplate.getForObject(REST_URL_PREFIX + "/dept/queryById/" + id, Dept.class); } @RequestMapping("/consumer/dept/list") public List<Dept> list(){ return restTemplate.getForObject(REST_URL_PREFIX + "/dept/queryAll", List.class); } }
④启动请求并测试验证是否能访问成功:
完成远端服务提供者的接口访问!
3.总结:
整个SpringCloud微服务是一套生态,基于SpringBoot项目的每一个服务组件(父工程管理所有子工程组件依赖及版本信息),组件之间使用HTTP协议(这里案例使用RestTemplate)进行接口调用。
- 服务提供者提供Restful访问接口,启动服务端口,供消费者调用;
- 服务api作为中间者,只提供服务组件(POJO),不与业务接口相耦合;
- 服务消费者使用RestTemplate进行服务接口远程访问,直接访问远端服务接口,无脑操作;
- 服务消费者调用远端接口后,同样使用restful接口暴露出自己的访问地址,以供服务启用显示
最后,罗列一下本博客参考博文博主 【雨点的名字】。
我也是她的粉丝,哈哈!这里借鉴了一下她的文章思路:基于RestTemplate微服务项目案例
博客涉及代码均已上传至github:
https://github.com/devyf/SpringCloud_Study/tree/main/springcloud_hello
写博是一种习惯,习惯坚持下去一定会有收获~ 编码路漫漫,希望初心不改!就酱~