测试时: 报错 'xxxxx' that could not be found 解决方式
一、Feign替代RestTemplate
首先我们要先知道RestTemplate方式调用时存在的问题:
因此我们就用Feign解决RestTemplate方式调用时存在的问题:
总结一句话:我们使用Feign技术的目的就是解决上面RestTemplate向服务提供者发送url请求的格式,并且我们使用 RestTemplate向服务提供者发送url请求的时候,当服务提供者userservice服务器名对应有多个服务器的时候,我们服务消费者请求访问的时候,访问到服务提供者的服务器是负载均衡的(也就是说服务提供者的服务器都有可能会接收到服务消费者发送的请求)
1.1、使用Feign的步骤
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
注:order-service是服务消费者,也就是说在服务消费者启动类上加注解,并且引入依赖。
补充:restTemplate技术发送的url是以Get请求方式发送的,因此我们现在使用Feign技术代替的时候就用GetMapping注解形式。
操作之前:首先我们先把服务提供者(也就是我们上面restTemplate发送的url,就是想向服务消费者发送的url路径请求)
我们保证服务提供者(也就是说前面说过的用户模块功能)的服务器是开启状态的时候,然后我们就可以向这个服务提供者发送url请求了:
java代码操作如下所示(Feign代替restTemplate发送的url代码):
二、自定义Feign的配置
配置Feign日志有两种方式:
第一种:配置文件形式
feign:
client:
config:
default: # 全局配置方式
loggerLevel: FULL # 四个等级中的FULL等级(FULL:也就是说打印所有的日志信息)
首先我们没有添加日志配置的时候,我们服务消费者访问调用服务提供者的资源数据时:
会发现服务消费者控制台只打印输入了SQL方面的信息:
现在我们服务消费者配置文件中加上了输入日志的配置后:
再访问调用时,会发现我们服务消费者控制台就会输出了很多的日志信息了(包括响应头、响应体、等日志信息):
第二种:java代码方式
可以导一下这个依赖坐标:
<dependency>
<!--新坐标,SpringCloud Finchley及之后的版本必须使用该坐标-->
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
最终会发现问题解决:
第二步: 如果我们想把日志配成全局配置,那么就把第一步声明的实体类放到@EnableFeignClients这个注解中即可:
最终访问发现控制台确实输入了全部的日志信息:
如果想配置成局部配置的话,只需要放到@FeignClient注解中即可:
注:前面的value="#" 就代表当服务消费者访问#服务名对应的服务器访问地址的时候,才会输出打印日志信息。
三、Feign性能优化
因此我们上面的总结中可以知道,想提高Feign的性能,我们就可以使用连接池的方式代替Feign底层默认采用的不支持连接池的实现方式,具体步骤如下所示:
我们就使用Apache HttpClient 支持连接池的实现方式优化Feign性能:
注:我们知道Feign的作用就是让向微服务(其他模块发送url路径的)变得更加优雅的,因此我们要知道我们操作的这些Feign其实都是针对服务消费者而言的(个人理解)。
<dependency>
<!-- httpclient的依赖-->
<groupId>io.github.openfeign</groupId>
<artifactId>feign-httpclient</artifactId>
</dependency>
这两步操作完之后,那么我们的Feign性能就优化成功了。
四、Feign最佳企业使用方案
首先我们要先知道,上面说过了Feign的作用就是让服务消费者向服务提供者发送的url路径变得更加优雅的:
然后其实上面这个UserClient接口的目的就是服务消费者向服务名为userservice的服务提供者发送url请求的,我们知道上面发送的url路径资源请求其实是发送到服务提供者的下面的功能方法当中的,最终获取到服务提供者中该方法(下面的queryById方法)中的资源数据的:
现在比如说我们有这样一个场景,就是说我们现在有几十个服务消费者(支付模块、商品模块、地址模块等)都想发送url请求获取上面那个user-service服务提供者queryById功能方法中的资源,难不成我们这几十个服务消费者模块当中都要写一个下面这个发送url的Feign接口才能获取到服务提供者该url对应的资源数据 ?(为什么都要写这个url的Feign接口呢:因为下面的Feign接口发送的url就是到服务提供者的queryById功能方法中的) 那岂不是说相同的代码接口写了几十次那这样也太冗余了。
因此我们怎么解决上面所面临的重复写Feign发送url请求的接口代码呢:
我们就可以使用抽取的方式,就是说把那个要写几十次Feign接口的代码独立抽取出来:
最终通过上面的抽取方式,我们就知道了当有几十个服务消费者想要向服务提供者发送获取那一个功能资源的时候,本来要写几十次发送url请求的Feign接口,但是通过上面的抽取方式后,就只写一次就可以了。
具体的java代码实现上面抽取方式的步骤如下所示:
第一步:
第二步:
注:这个feign配置就是feign打印输出日志的那个配置,上面笔记有。
假设现在这个order-service服务消费者模块就想通过用抽取到feign-api模块中的那套通过发送url的Feign接口,然后向服务提供者发送url获取到相对应的资源数据,那么这个order-service服务消费者就要通过下面的操作才能够使用到feign-api模块中的功能:
第一步:在order-service这个服务消费者中引入feign-api模块中的依赖
第二步: 修改服务消费者中的import部分,改成导入feign-api中的包
第三步:导入好之后,重启服务器进行访问测试
然后会发现好家伙,报错啊:
为什么会报这个错误呢:
测试时: 报错 'xxxxx' that could not be found 解决方式
两种解决方式:
演示方式一:
最终会发现服务器启动成功: