1.环境搭建
增加feign依赖,网上搜索到的都是如下配置:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
</dependency>
其实这个配置不对,spring boot根本无法启动feign注解,正确的方式如下:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
上一节中,使用类似
restTemplate.getForEntity("http://COMPUTE-SERVICE/add?a=10&b=20", String.class).getBody()
这样的语句进行服务间调用并非不可以,只是我们在服务化的过程中,希望跨服务调用能够看起来像本地调用,这也是我理解的Feign的使用场景
*启用
@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class EurekaClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
}
*定义服务,声明feignclient,使得远程调用如同调用本地服务一样,并且可以和eureka完美集成
package hello;
import hello.depends.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
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.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* Created by hanruikai on 2018/7/3.
*/
@RestController
@RequestMapping("/api/v1/")
class TestController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private TestService testService;
@GetMapping("testinvoke")
public List<ServiceInstance> serviceInstancesByApplicationName() {
restTemplate.exchange("http://SERVICE-PROVIDER/test",HttpMethod.GET,null,String.class);
return null;
}
@GetMapping("invokedByFeign")
public List<ServiceInstance> invokeByFeign() {
testService.helloTest();
return null;
}
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
package hello.depends;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Created by hanruikai on 2018/7/3.
*/
@FeignClient("SERVICE-PROVIDER")
public interface TestService {
@GetMapping(value="test")
String helloTest();
}
其中
@FeignClient("SERVICE-PROVIDER")
参数值为调用的服务的名称,此处为eureka中的application name,也就是服务名称
@GetMapping中的value是需要调用的服务的接口,服务提供方代码如下:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
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.RestController;
import java.util.List;
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
@RestController
class ServiceInstanceRestController {
@GetMapping("/test")
public void test() {
System.out.print("invoked successfully");
}
}
2 如何传递参数
feign client代码修改如下:
package hello.depends;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Created by hanruikai on 2018/7/3.
*/
@FeignClient("SERVICE-PROVIDER")
public interface TestService {
@PostMapping(value="test")
String helloTest(@RequestBody String name);
}
@GetMapping("invokedByFeign")
public List<ServiceInstance> invokeByFeign() {
testService.helloTest("kerry");
return null;
}
provider:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@EnableDiscoveryClient
@SpringBootApplication
public class EurekaProviderApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaProviderApplication.class, args);
}
}
@RestController
class ServiceInstanceRestController {
@PostMapping("/test")
public void test(@RequestBody String name) {
System.out.print("invoked successfully"+name);
}
}
3 如果没有Eureka,服务名称不存在怎么办
package hello.depends;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
/**
* Created by hanruikai on 2018/7/3.
*/
@FeignClient(value = "test",url = "http://localhost:8090")
public interface TestService {
@PostMapping(value="test")
String helloTest(@RequestBody String name);
}
feignclient注解除了name,还有url,可以指定url进行调用。这样可以把重复的rest调用封装到service里面,用feign进行声明式rest client。