远程调用
RestTemplate
Spring
提供了RestTemplate
工具,可以方便的实现HTTP
请求的发送。
-
注入
RestTemplate
到Spring
容器 -
通过构造函数注入到
Service
层@RequiredArgsConstructor
:创建包含必须初始化(final
)的属性的构造函数 -
发起远程调用
public <T> ResponseEntity</T> exchange(
String url, // 请求路径
HttpMethod method, // 请求方式
@Nullable HttpEntity<?> requestEntity, // 请求实体,可以为空
Class<T> responseType, // 返回值类型
Map<String, ?> uriVariables // 请求参数,jdk11的写法
)// jdk8的Map写法
String joinedIds = CollUtil.join(itemIds, ",");
// 创建一个临时的可变 Map
Map<String, String> tempMap = new HashMap<>();
tempMap.put("ids", joinedIds);
// 创建一个不可变的 Map
Map<String, String> map = Collections.unmodifiableMap(tempMap);
(OpenFeign)[https://github.com/OpenFeign/feign]
是一个声明式的http客观端,是SpringCloud
在Eureka
公司开源的Feign
基础上改造而来。
基于SpringMVC
的常见注解,实现http
请求的发送
-
引入依赖
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载 均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency> -
启动
OpenFeign
使用
@EnableFeignClients
注解@EnableFeignClients
@SpringBootApplication
public class Application {……} -
在
/client
目录下新建ItemClient
接口,编写FeignClient
@FeignClient(value = "服务名,如item-service")
public interface ItemClient {
@GetMapping("路由,如/items")
List<ItemDTO> queryItemByIds(@RequestParam("ids") Collection<Long> ids);
} -
使用
FeignClient
,实现远程调用List<ItemDTO> items = itemClient.queryItemByIds(List.of(1,2,3));
优化-连接池
Feign底层发起http请求,依赖于其它的框架。其底层支持的http客户端实现包括:
- HttpURLConnection:默认实现,不支持连接池
- Apache HttpClient :支持连接池
- OKHttp:支持连接池
-
引入依赖
<!--OK http 的依赖 -->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-okhttp</artifactId>
</dependency> -
开启连接池功能
feign:
okhttp:
enabled: true # 开启OKHttp功能
最佳实践
方案一:适合项目结构为Maven聚合,用一个统一的api
模块暴露其他微服务需要的dto
、api
、biz
等信息,耦合度比方案一高
方案二:适合项目结构为每个模块是独立的Project,在各自的模块下管理自己的dto
、api
、biz
等
方案一
-
创建
api
模块及需要暴露的信息--api
--src
--main
--java
--com.hmall
--api
--client
--dto
…… -
注入需要的依赖
例子:
<dependencies>
<!--openFeign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--负载均衡器-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.6.6</version>
<scope>compile</scope>
</dependency>
</dependencies> -
让同父模块下的模块可以扫描到
<!--feign模块-->
<dependency>
<groupId>com.heima</groupId>
<artifactId>hm-api</artifactId>
<version>1.0.0</version>
</dependency>在启动类上加声明
-
@EnableFeignClients(basePackages = "com.hmall.api.client")
-
@EnableFeignClients(clients = {ItemClient.class})
-
日志配置
OpenFeign只会在FeignClient所在包的日志级别为DEBUG时,才会输出日志。
logging:
level:
com.hmall: debug
而且其日志级别有4级:
NONE
:不记录任何日志信息,这是默认值。BASIC
:仅记录请求的方法,URL
以及响应状态码和执行时间HEADERS
:在BASIC
的基础上,额外记录了请求和响应的头信息FULL
:记录所有请求和响应的明细,包括头信息、请求体、元数据。
Feign
默认的日志级别就是NONE
,所以默认我们看不到请求日志。
-
在
api
下新建配置类,定义Feign
的日志级别// package com.hmall.api.config;
// DefaultFeignConfig
public class DefaultFeignConfig {
@Bean
public Logger.Level feignLogLevel(){
return Logger.Level.FULL;
}
} -
配置类使日志生效
-
局部生效:在某个
FeignClient
中配置,只对当前FeignClient
生效@FeignClient(value = "item-service", configuration = DefaultFeignConfig.class)
-
全局生效:在
@EnableFeignClients
中配置,针对所有FeignClient
生效。@EnableFeignClients(defaultConfiguration = DefaultFeignConfig.class)
-