在 Spring Boot 中,可以使用 Feign 来创建 HTTP 客户端,通过简单的注解方式即可实现服务间的远程调用。Feign是一种声明式、模板化的HTTP客户端,在往常的 HTTP 调用中,一直都是使用的官方提供的 RestTemplate 来进行远程调用,该调用方式将组装代码冗余到正常业务代码中,不够优雅,因此,可以考虑用Feign来替代。
1.引入Feign依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
<version>3.1.4</version>
</dependency>
注意,我这里使用的版本是3.1.4的,适配spring 2.7.5版本,如果使用其他版本,建议去官网看下适配版本,以免依赖冲突了
2.配置Feign客户端
配置 Feign 客户端,告诉它需要调用哪个远程服务。你可以通过 @FeignClient
注解来指定远程服务的名称和地址,这样 Feign 就会在调用时自动将请求发送到指定的服务。
@FeignClient(url = "${user.service.url}", name = "user-service")
public interface UserServiceClient {
@GetMapping("/user/{id}")
User getUser(@PathVariable String id);
@PostMapping("/user")
User createUser(@RequestBody User user);
}
@FeignClient
注解的url属性,可以根据实际业务配置到配置文件里面,不配置到配置文件的话直接赋值就行,url = "localhost:6666" ,不过还是建议配置到配置文件里
# 用户服务URL
user:
service:
url: localhost:6666
如果请求的接口需要带一些请求头信息的话,例如携带token等,就要配置configuration属性,自定义一个FeignTokenConfig,添加接口的请求头信息
@FeignClient(url = "${user.service.url}", name = "user-service", configuration = FeignTokenConfig.class)
public interface UserServiceClient {
@GetMapping("/user/{id}")
User getUser(@PathVariable String id);
@PostMapping("/user")
User createUser(@RequestBody User user);
}
FeignTokenConfig:
/**
* 给Feign请求设置请求头
*/
@Slf4j
@Configuration
public class FeignTokenConfig implements RequestInterceptor {
@Autowired
private UserService userService;
@Override
public void apply(RequestTemplate requestTemplate) {
requestTemplate.header("Accept", "application/json");
String token = null;
// 从当前线程的http实例获取token,可以根据实际情况获取token
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes != null) {
HttpServletRequest request = attributes.getRequest();
token = request.getHeader("Authorization");
}
} catch (Exception e) {
log.error("通过request获取token失败", e);
}
// 通过向认证中心获取token
if (StrUtil.isBlank(token)){
try {
token = userService.getToken();
} catch (Exception e) {
log.error("向认证中心获取token失败",e);
}
}
if (StrUtil.isNotBlank(token)) {
// 我这里只加了token请求头,需要其他的可以按需求添加
requestTemplate.header("Authorization", token);
log.info("feign客户端设置请求头>>> Authorization:{}", token);
} else {
log.error("token获取失败");
}
}
以上只定义了GET和POST请求,如果你需要发送其他类型的请求,只需使用 @PostMapping
、@PutMapping
、@DeleteMapping
等注解,与使用 Spring MVC 一样。同时,你可以使用 @RequestParam
、@PathVariable
、@RequestBody
等注解来传递请求参数,与使用 Spring MVC 一样。
最后,在启动类添加@EnableFeignClients注解
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableFeignClients
public class App
{
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
3.使用Feign客户端
使用 Feign 客户端非常简单,注入客户端,直接调用客户端定义的方法,像使用本地接口一样调用即可,
@RestController
@RequestMapping("/user")
public class UserServiceController {
@Autowired
UserServiceClient userServiceClient;
@GetMapping("/{id}")
public User getUser(@PathVariable String id) {
return userServiceClient.getUser(id);
}
@PostMapping
public User createUser(@RequestBody User user) {
return userServiceClient.createUser(user);
}
}