SpringCloud整合Feign
1、准备工作
- 新建Maven项目:atm_spring_feign_server(8761端口)
新建Maven项目:atm_spring_feign_provider
- 启动8080与8081端口
- 提供“/person/{personId}”与“/hello”服务
新建Maven项目:atm_spring_feign_invoker(9000端口)
2、服务调用者
2.1、引入依赖
- 为服务提供者(atm_spring_feign_invoker)引入依赖
<!-- SpringCloud 整合 Feign -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
2.2、启动类打开Feign
package com.atm.cloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients//调用者启动时,打开Feign开关
public class MySpringFeignInvoker {
public static void main(String[] args) {
SpringApplication.run(MySpringFeignInvoker.class, args);
}
}
2.3、编写接口
package com.atm.cloud.interf;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* 客户端服务接口
*
* 与单独使用Feign不同:
* 1.接口需要使用@FeignClient注解修饰
* 2.声明需要调用的服务名称
*/
@FeignClient("atm-spring-feign-provider")
public interface PersonClient {
/**
* 之前得知:
* 通过编写"翻译器"(Contract),可以让Feign知道第三方注解的含义
* 同样,SpringCloud也提供了翻译器,会将注解告诉Feign
* 因此,接口可以直接使用该注解
* 默认支持注解:@RequestMapping、@RequestParam、@RequestHeader、@PathVariable
* 【注意】使用了SpringCloud的翻译器后,将不能再使用Feign的默认注解
*/
@GetMapping("/hello")
//@RequestMapping(method=RequestMethod.GET,value="/hello")
String sayHello();
@RequestMapping(method=RequestMethod.GET,value="/hello/{name}")
String hello(@PathVariable("name") String name);
}
2.4、控制器添加调用方法
package com.atm.cloud.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import com.atm.cloud.interf.PersonClient;
@RestController
@Configuration
public class MyInvokerController {
//在控制器中调用接口方法 ---start
@Autowired
private PersonClient personClient;
@RequestMapping(value="/invokeHello",method=RequestMethod.GET)
public String invokeHello(){
return personClient.sayHello();
}
//在控制器中调用接口方法 ---end
}
2.5、运行测试
- 启动atm_spring_feign_server(8761端口)
- 启动atm_spring_feign_provider(8080端口、8081端口)
- 启动atm_spring_feign_invoker(9000端口)
- 浏览器访问http://localhost:9000/invokerHello
- 可以发现:服务提供者的“/hello”被调用
3、Feign负载均衡
3.1、编写接口
package com.atm.cloud;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* 客户端服务接口
*
* 与单独使用Feign不同:
* 1.接口需要使用@FeignClient注解修饰
* 2.声明需要调用的服务名称
*/
@FeignClient("atm-spring-feign-provider")
public interface PersonClient {
@RequestMapping(method = RequestMethod.GET, value = "/person/{personId}")
Person getPerson(@PathVariable("personId") Integer personId);
}
3.2、控制器添加调用方法
package com.atm.cloud;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.atm.cloud.PersonClient;
@RestController
@Configuration
public class MyInvokerController {
@RequestMapping(value = "/router", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public String router() {
// 调用服务提供者的接口
Person p = personClient.getPerson(2);
return p.getName();
}
}
3.3、运行测试
- 浏览器访问http://localhost:9000/router
- 可以发现,调用了提供者接口,轮询访问8080端口与8081端口
3.4、默认配置
- SpringCloud为Feign的使用提供了各种默认属性
- 默认情况下,Spring将会为Feign的属性提供bean
- 解码器(Decoder):bean 名称为 feignDecoder,ResponseEntityDecoder 类
- 编码器(Encoder):bean 名称为 feignEecoder,SpringEncoder 类
- 日志(Logger): bean 名称为 feignLogger,Slf4jLogger 类
- 注解翻译器(Contract): bean 名称为 feignContract,SpringMvcContract 类
package com.atm.cloud;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyUrl {
String url();
String method();
}
package com.atm.cloud;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import org.springframework.cloud.netflix.feign.support.SpringMvcContract;
import feign.Contract.BaseContract;
import feign.MethodMetadata;
//自定义翻译器实现支持两种注解
public class MyContract extends SpringMvcContract {
@Override
protected void processAnnotationOnMethod(MethodMetadata data,
Annotation annotation, Method method) {
super.processAnnotationOnMethod(data, annotation, method);
// 在父类的基础上实现
// 实现自定义的翻译逻辑
}
}
package com.atm.cloud;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import feign.Contract;
@Configuration
public class MyConfig {
@Bean
public Contract feignContract() {
return new MyContract();
}
}
@MyUrl(url="/hello",method="GET")
String hello();
- Feign 实 例 的 创 建 者 ( Feign.Builder ) : bean 名 称 为 feignBuilder ,HystrixFeign.Builder 类
- Feign 客户端(Client):bean 名称为 feignClient,LoadBalancerFeignClient 类
3.5、可选配置
- Logger.level:接口日志的记录级别,相当于调用了Feign.Builder的level方法
- Retryer:重试处理器,相当于调用了Feign.Builder.的retryer方法
- ErrorDecoder:异常解码器,相当于调用了Feign.Builder.的ErrorDecoder方法
- Request.Options:设置请求的配置项
- Collection”<”RequestInterceptor”>”:请求拦截器
3.6、压缩配置
- feign.compression.request.enabled:设置为true开启请求压缩
- feign.compression.response.enabled:设置为true开启响应压缩
- feign.compression.request.mine-types:数据类型列表,默认为text/xml,application/xml,application/json
- feign.compression.request.min-request-size:设置请求内容的最小阀值,默认2048