RestTemplate虽然比直接用HTTPClient简单的多,但是还是存在着许多的问题,比如url拼接麻烦,容易出错,并且可读性很差
public OrderDetail selectOrderById(Integer orderId){
OrderDetail orderDetail = orderMapper.selectOrderById(orderId);
String url="http://product-service/product/"+orderDetail.getProductId();
ProductDetail productDetail = restTemplate.getForObject(url, ProductDetail.class);
orderDetail.setProductDetail(productDetail);
return orderDetail;
}
OpenFeign
微服务之间的通信,通常有RPC和HTTP,在SpringCloud中默认使用HTTP来进行微服务的通信,最常用的两种形式:RestTemplate和OpenFeign
OpenFeign是⼀个声明式的WebService客⼾端.它让微服务之间的调⽤变得更简单,类似controller 调⽤service, 只需要创建⼀个接⼝,然后添加注解即可使⽤OpenFeign
OpenFeign的使用
引入依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
添加注解@EnableFeignClients
用来开启OpenFeign的功能
@EnableFeignClients
@SpringBootApplication
@MapperScan("org.example1.mapper")
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class,args);
}
}
写一个关于OpenFeign的客⼾端
用SpringMvc的注解进行调用
@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
@RequestMapping("/{productId}")
ProductDetail selectProductById(@RequestParam("productId") Integer productId);
@RequestMapping("/p1")
String p1(@RequestParam("id") Integer id);
@RequestMapping("/p2")
String p2(@RequestParam("id") Integer id,@RequestParam("name") String name);
@RequestMapping("/p3")
String p3(@SpringQueryMap ProductDetail productDetail);
@RequestMapping("/p4")
String p4(@RequestBody ProductDetail productDetail);
}
远程调用
@Service
public class OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private ProductApi productApi;
public OrderDetail selectOrderById(Integer orderId){
OrderDetail orderDetail = orderMapper.selectOrderById(orderId);
ProductDetail.class);
ProductDetail productDetail = productApi.selectProductById(orderDetail.getProductId());
orderDetail.setProductDetail(productDetail);
return orderDetail;
}
}
OpenFeign关于参数的传递
包括一个参数,两个参数,传递对象,传递Json
首先我们在product-service中提供几个接口方法
@RestController
@RequestMapping("/product")
public class ProductController {
@Autowired
private ProductService productService;
@RequestMapping("p1")
private String p1(Integer id){
return "参数传递:"+id;
}
@RequestMapping("p2")
private String p2(Integer id,String name){
return "参数传递,id:"+id+"name"+name;
}
@RequestMapping("p3")
private String p3(ProductDetail productDetail){
return "传递对象"+productDetail;
}
@RequestMapping("p4")
private String p4(@RequestBody ProductDetail productDetail){
return "接受Json对象"+productDetail;
}
}
在Feign客户端
@FeignClient(value = "product-service", path = "/product")
public interface ProductApi {
@RequestMapping("/p1")
String p1(@RequestParam("id") Integer id);
@RequestMapping("/p2")
String p2(@RequestParam("id") Integer id,@RequestParam("name") String name);
@RequestMapping("/p3")
String p3(@SpringQueryMap ProductDetail productDetail);
@RequestMapping("/p4")
String p4(@RequestBody ProductDetail productDetail);
}
最后通过order-service服务调用
@RequestMapping("/feign")
@RestController
public class FeignController {
@Autowired
private ProductApi productApi;
@RequestMapping("/o1")
public String o1(Integer id){
return productApi.p1(id);
}
@RequestMapping("/o2")
public String o2(Integer id,String name){
return productApi.p2(id,name);
}
@RequestMapping("/o3")
public ProductDetail o3(){
ProductDetail productDetail=new ProductDetail();
productApi.p3(productDetail);
productDetail.setId(1);
productDetail.setProductName("zhangsan");
return productDetail;
}
@RequestMapping("/o4")
public ProductDetail o4(){
ProductDetail productDetail=new ProductDetail();
productApi.p3(productDetail);
productDetail.setId(1);
productDetail.setProductName("zhangsan");
return productDetail;
}
}
我们可以来测试一下
传递一个参数的
传递两个参数的
传递对象的
传递Json对象的
Feign 继承⽅式
Feign支持继承的方式,我们可以把一些常见的操作封装到接口中
创建一个新的服务product-api
将Feign客户端写在这个服务中,这样在调用的时候就不用再重写了
将Feign继承product-api
@FeignClient(value = "product-service", path = "/product")
public interface ProductApi extends org.example.ProductApi {
}
注:在product-api服务中记得写入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
在写好product-api服务后,将其install到本地
然后再重新测试一下
Feign 抽取⽅式
就是直接将Feign写成一个独立的模块,将product-service中的product-api接口删除
然后重新启动程序,发现报错了
我们需要再启动类中添加
@EnableFeignClients(clients = {ProductApi.class})
@SpringBootApplication
@MapperScan("org.example1.mapper")
public class OrderServiceApplication {
public static void main(String[] args) {
SpringApplication.run(OrderServiceApplication.class,args);
}
}
标明需要加载的Feign客⼾端
注:在部署服务的时候需要修改pom文件
希望对大家有所帮助!!!!!