1 介绍
Feign 是一个声明式的 REST 客户端,它能让 REST 调用更加简单。Feign 提供了 Http 请求的模板,通过编写简单的忌口和插入注解,就可以定义好 Http 请求的参数、格式、地址等信息。
之前使用的是 RestTemplate 访问 Rest 服务,RestTemplate 提供了多种便捷访问远程 Http 服务的方法,能够大大提高客户端的编写效率。
而 Feign 会完全代理 Http 请求,我们只需要湘调用方法一样调用它就可以完成服务请求及相关处理。Feign 可以与 Eureka 和 Ribbon 组合使用以支持负载均衡。
2 集成 Feign
声明式的 REST 客户端,即注解式的接口调用,类似于 Mapper 接口一样。在服务消费者模块添加如下信息(之前项目)。
2.1 pom.xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2.2 Service
创建 UserInfo Service 接口
@FeignClient(value = "springcloud-provider", path = "/users")
public interface UserInfoService {
@RequestMapping(value = "/{username}")
UserInfo getByName(@PathVariable(value = "username") String username);
}
使用 @PathVariable 时,value 需要显式声明,否则报错。
2.3 Controller
@RestController
@RequestMapping(value = "users")
public class UserInfoController {
@Autowired
UserInfoService userInfoService;
/**
* 通过用户名获取用户
* @param username
* @return
*/
@GetMapping(value = "/feign/{username}")
public UserInfo getByFeign(@PathVariable String username) {
UserInfo userInfo = userInfoService.getByName(username);
return userInfo;
}
}
2.4 启动类
@SpringBootApplication
@EnableEurekaClient // 表明自己是个 eureka 客户端,会自动注册到 eureka 服务端中
@EnableFeignClients(basePackages = {"com.pky.springcloud"}) // 指定扫描 Feign 相关注解。
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
}
}
如果 Feign 接口定义跟启动类不在一个包名下,则需要指定扫描的包名 @EnableFeignClients(basePackages = “指定扫描路径”)
2.5 启动测试
浏览器输入对应地址。
多次请求之后观察 9001、9002 控制台,轮询输出对应信息,达到了负载均衡的效果。
2.6 自定义认证
Feign 有提供一个接口 RequestInterceptor,即请求拦截器。在请求之前做认证操作,然后往请求头中设置认证之后的信息。通过实现 RequestInterceptor 接口来自定义认证方式。
/**
* Feign 认证拦截器
*/
@Configuration
public class FeignBasicAuthRequestInterceptor implements RequestInterceptor {
public FeignBasicAuthRequestInterceptor() {
}
@Override
public void apply(RequestTemplate requestTemplate) {
// 业务逻辑
requestTemplate.header("token", "FeignToken");
}
}
创建 Feign 配置类:
/**
* Feign 配置类
*/
@Configuration
public class FeignConfig {
/**
* 认证拦截器
* @return
*/
@Bean
public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new FeignBasicAuthRequestInterceptor();
}
/**
* 日志级别
* @return
*/
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
还需要在 Feign 接口中引用该配置:
@FeignClient(value = "springcloud-provider", path = "/users", configuration = FeignConfig.class)
public interface UserInfoService {
@RequestMapping(value = "/{username}")
UserInfo getByName(@PathVariable(value = "username") String username);
}
服务提供者模块中的 Controller 接口:
@RestController
@RequestMapping(value = "users")
public class UserInfoController {
@Autowired
UserInfoService userInfoService;
/**
* 通过用户名获取用户
* @param username
* @return
*/
@GetMapping(value = "/{username}")
public UserInfo getByName(@PathVariable String username, HttpServletRequest request) {
String token = request.getHeader("token");
UserInfo userInfo = userInfoService.getByUsername(username);
return userInfo;
}
}
以上完成自定义认证。
2.7 日志
若接口调用失败、参数没收到等问题,就需要配置 Feign 的日志。
* Feign 配置类
*/
@Configuration
public class FeignConfig {
/**
* 认证拦截器
* @return
*/
@Bean
public FeignBasicAuthRequestInterceptor basicAuthRequestInterceptor(){
return new FeignBasicAuthRequestInterceptor();
}
/**
* 日志级别
* @return
*/
@Bean
Logger.Level feignLoggerLevel() {
return Logger.Level.FULL;
}
}
日志类别:
- NONE: 不输出日志
- BASIC:只输出请求方法的 URL 和响应的状态码以及接口执行的时间
- HEADERS:将 BASIC 信息和请求头信息输出
- FULL: 输出完整的请求信息
在 application.yml 中配置日志信息
# 日志
logging:
level:
com:
pky:
springcloud: DEBUG
level 后面为指定包路径。
调用接口时,控制台会打印相应信息: