Feign其实就是Ribbon再套了一层,什么意思,Feign是通过Serivce层中写接口的方式, 添加@FeignClient, 实现从service层到controller层的远程调用. 同时保留了原有的Ribbon基于客户端的负载均衡配置.
下面我们通过配置feign的方式, 实现远程的客户端Controller层的Service方法调用
首先在我们的pojo实体类中,定义好一个service层,
在此之前记得导入feign的pom依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
<type>pom</type>
</dependency>
service层如下:
package com.bai.springcloud.service;
import com.bai.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Service
@FeignClient(value = "SPRINGCLOUD-ROVIDER-DEPT")
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
public Dept queryById(@PathVariable("id")Long id);
@GetMapping("/dept/list")
public List<Dept> queryAll();
@PostMapping("/dept/add")
public boolean addDept(Dept dept);
}
@FeignClient注解 value指向我们的服务提供者,以便我们找到具体功能实现的mapper层以及其mapper.xml以提供完整的服务
value和我们的服务提供者微服务名称一样即可
我们通过在service层直接写RestFul风格的注解来进行编写
ok我们去编写基于feign实现的消费者客户端
项目结构如下,我们既要使用Feign的远程调用方式, 还要使用其提供的客户端负载均衡功能. 所以我们也同时开启了自定义的一个ConfigBean
ConfigBean配置很简单,这里使用其默认支持的随机算法作为演示.
package com.bai.springcloud.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {//ApplicationContext.xml---spring @Configuration
@LoadBalanced
@Bean
public IRule myRule(){
return new RandomRule();
}
}
与Ribbon不同的地方在于需要在Service就加入RestFul风格注解,之外, 我们还要对Feign配置的消费者的Controller层进行改造
package com.bai.springcloud.controller;
import com.bai.springcloud.pojo.Dept;
import com.bai.springcloud.service.DeptClientService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DeptConsumerController {
@Autowired
private DeptClientService deptClientService = null;
@RequestMapping("consumer/dept/add")
public boolean add(Dept dept){
return this.deptClientService.addDept(dept);
}
@RequestMapping("consumer/dept/get/{id}")
public Dept get(@PathVariable("id")Long id){
return this.deptClientService.queryById(id);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list(){
return this.deptClientService.queryAll();
}
}
可以看到我们这里自动织入刚刚在实体类微服务中写的Service类,这时候, 我们可以注意到, pojo实体类微服务的sevice中的RequestMapping类注解所指向的是我们的服务提供者的Controller, 而Feign客户端直接指向我们的pojo实体类的Service的Mapping就可以了
具体写法详见以上代码
ok 这时候我们进行测试, 看这样的写法是否能够依旧获取到我们的服务…
我们启动至少两个服务提供者,这样才能够让我们的LoadBalance负载均衡成功运行
我这里开启了两个Eureka注册中心和两个Provider提供者 以及我们刚刚写好的Feign客户端消费者
运行查看结果成功!