概述
在前几篇文章中我记录了通过Netty基于WebSocket实现的即时通信APP项目,目前做到了个人对个人的聊天和附近的人(通过Redis GeoHash实现)功能。其他的功能设计无非是对数据库的增删改查,但这样的项目并不算是一个有趣的项目。
因此我打算将其拆分为微服务,顺便应用一下好早好早以前学习过的一些知识,巩固一下。
开始
拆分项目与配置依赖
首先,在之前的项目中大概分为三个模块:
- 基于Netty的聊天服务
- 基于FastDFS的文件存储服务
- 基于SpringDataJPA的数据存储服务
很显然,我可以直接将其抽离出来,将其独立起来。步骤是,对我们的项目右键——新建——模块。这样就可以基于本项目创建一个模块。
但值得注意的是,拆出来之后我们需要为其加入独立的启动类与配置类。
其后,我们需要迁移各个模块所需要的pom依赖。然后在主项目pom文件中加入以下依赖。这些依赖中,主要规定了我们本项目对应的SpringCloud环境中所对应的依赖的版本号。因此我们之后子模块的依赖项一般就不用写上版本号了。因为我们本次引入的依赖项已经为我们规定好了。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-alibaba-dependencies</artifactId>
<version>2.2.5.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
注册中心
安装客户端
如标题所示,此次项目使用了Nacos作为注册中心。第一步需要先下载它的客户端。
下载地址: https://gitee.com/myzhhc/nacos/blob/master/nacos-server-1.3.2.zip
解压后进入/bin目录,执行一下命令。目的是将其启动,其后参数 「-m standalone」是以单例形式运行,否则默认为集群式启动。
sh startup.sh -m standalone
其后可以根据终端输出的内容「/logs/start.out」查看运行日志,一般我们直接访问「http://127.0.0.1:8848/nacos/index.htm」就可以登入Nacos的后台了。账号和密码默认都是「nacos」。
注册服务
首先我们需要引入以下依赖。
<!--注册中心-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
然后加入以下配置。「server-addr」中是你的nacos地址。
spring:
cloud:
nacos:
discovery:
server-addr: 127.0.0.1:8848
其后在启动器之上加入「@EnableDiscoveryClient」注解就好了。当项目启动后,我们在Nacos后台的服务列表中就可以看到我们的服务了。
微服务之间的通讯
之前了解过,一般情况下微服务目前有两种通讯的形式,一中是SpringCloud提倡的网络请求式(restful)和dubbo的rpc协议。
简单的来说,restful形式就是通过从注册中心中获取对应的服务列表,然后直接通过它所提供的接口地址发起网络访问请求。但我们并不习惯于这种形式,很是麻烦。
所以我们可以通过OpenFeign这个库来帮助我们实现具体的请求,我们编写一个接口对应一下服务的接口,这样写起来会很舒服。
使用
首先我们需要引入依赖。
<!--服务方法映射-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
然后在启动类之上加入「@EnableFeignClients」注解。
其后我们就可以编写对应的映射类了。代码如下。
首先需要在映射类上加入「@FeignClient」注解,并声明是要请求哪一个服务,一定要确保这个服务是开启状态。
其后编写对应的接口就好了。
@FeignClient(name = "nonsense-file-service")
public interface FileService {
@PostMapping(value = "/file/upload/user-face-image",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
AjaxResult uploadUserFaceImage(@RequestPart(value = "file",required = false) MultipartFile file);
@GetMapping("/file/delete/{path}")
@ApiOperation(value = "删除存储服务器文件")
AjaxResult delete(@PathVariable(value = "path",required = false) String path);
}
值得注意的是,每一个参数注解之后我们都要设置「required」属性为诶false。因为我们当前的服务在启动的时候需要初始化这个接口,但并不能提供参数,因此会产生报错。
其后如果参数是文件流形式的数据,就会出现问题。
拥有文件流参数的接口映射
上述说了,一般情况一个接口中如果拥有文件流类型的参数,那么就会导致我们对应的服务无法解析这个参数,因为openfeign在做映射操作的时候所发送的数据包的content-type并不是「form-data」形式,因此我们需要主动进行更改。
配置类。
public class FeignMultipartSupportConfig {
@Bean
@Primary
@Scope("prototype")
public Encoder multipartFormEncoder() {
return new SpringFormEncoder();
}
@Bean
public feign.Logger.Level multipartLoggerLevel() {
return feign.Logger.Level.FULL;
}
}
接口。在上述的代码中你应该已经看到了,我们在「@PostMapping」的注解添加了「consumes」参数,目的就是声明这个请求的类型是基于「form-data」形式的。
@PostMapping(value = "/file/upload/user-face-image",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
AjaxResult uploadUserFaceImage(@RequestPart(value = "file",required = false) MultipartFile file);
本页的评论功能已关闭