不用feign只用ribbon的请求是什么样子的?
如果仅仅使用Ribbon+RestTemplate来进行服务间调用,每个接口都需要写很多的代码。 实际上可以使用Feign来完成声明式的服务调用
@RestController
@Configuration
public class HelloService {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
@GetMapping("/hello/{name}")
public String hello(@PathVariable String name){
System.out.println("fgdffgfgf");
return this.restTemplate().getForObject("http://serviceA/helloo/yubo",String.class);
}
}
如果没有feign,只用ribbon的话,可以对于ServiceA做一个接口类和实现类。把上述代码挪到实现类中。而HelloService中可以改为如下代码
@RestController
public class HelloService {
@Autowired
private IserviceA serviceA;
@GetMapping("/hello/{name}")
public String hello(@PathVariable String name){
System.out.println("fgdffgfgf");
return serviceA.sayHello(name);
}
}
这样仍然很麻烦。对服务A的每个接口,都需要在本地定义一个接口类和实现类。
2.用了feign之后的请求是什么样子的
理想情况下,ServiceA要提供接口的时候,也要提供一个Jar包出来。服务B不能为调用服务A写任何代码。服务B引入这个jar包即可。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
在服务B的启动类加上注解 @EnableFeignClients
在服务B做一个IServiceA类
@FeignClient("ServiceA")
public interface IServiceA{
@RequestMapping(value = "/user/",method = RequestMethod.POST)
String createUser(@RequestBody User user);
@RequestMapping(value = "/user/{id}",method = RequestMethod.DELETE)
String deleteUser(@PathVariable("id") Long id);
}
这就是Feign+ribbon整合的方式 但是目前还是很麻烦。没有写代码,但是还是写了一些接口。这些接口和服务A的接口定义一模一样。 所以我们希望所有的接口只在serviceA中一遍搞定。
-
先在ServiceA中写一个接口A,controller类实现之
-
也可以见一个模块叫service-a-api,把接口A放进来。然后把这个模块mvn install /deploy
-
serviceB引入这个jar包
<dependency>
<groupId>com.zhss.demo</groupId>
<artifactId>service-a-api</artifactId>
</dependency>
- 然后,IServiceA extends jar包里的接口类,不需要写重复的
@FeignClient("ServiceA")
public interface IServiceA extends ServiceAInterface{
}
3.feign的核心组件和自定义bean、配置
核心组件
-
编码器解码器:如果调用接口的时候,传递的参数是一个对象。feign需要将这个对象进行encoder编码,变成json序列化。收到一个json以后,需要转换为对象。(ResponseEntityDecoder、SpringEncoder)
-
Logger: 打印接口调用请求的日志(Slf4jLogger)
-
Contract: 契约组件,负责解释别人家的注解,比如spring-mvc支持的@PathVariable\
@RequestMapping@RequestParam 等等,让feign可以和别人家的注解结合起来使用。(SpringMvcContract)
-
Feign.Builder: feign客户端的构造器。(HystrixFeign.Builder)
-
FeignClient: 使用feign最核心的入口。(LoadBalancerFeignClient)
自定义Bean
FeignClient(name="ServiceA",configuration = MyConfiguration.class)
public interface ServiceClient{
}
@Configuration
public class MyConfiguration{
@Bean
public RequestInterceptor requestInterceptor(){
return new MyRequestInterceptor();//用来替换核心组件
}
@Bean
public Logger.Level feignLoggerLevel(){
return Logger.Level.FULL;
}
//可以自定义很多bean,比如logger\Decoder...
}
public MyRequestInterceptor implements RequestInterceptor{
@Override
public void apply(RequestTemplate requestTemplate){
requestTemplate.header("Content-Type","application/json");
}
}
配置
举例:
feign:
client:
config:
ServiceA:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
decode404: false
logging.level.com.zhss.service.ServiceAclient:DEBUG