SpringCloud基础知识:Feign
- 1. Feign 概述
- 2. Feign快速入门
* - 2.1 前期准备(
初始默认代码
)
– - 2.2 Feign应用(
代码修改
)
– - 3. Feign 其他功能
* - 3.1 超时设置
-
Feign 概述
-
Feign是一个声明式的REST客户端,它用了
基于接口的注解方式
,很方便实现客户端配置。 - Feign
最初
由Netflix公司提供,但不支持
SpringMC注解,后
由SprinaCloud.对其封装,支持了
SpringMMC注解,让使用者更易于接受。 - Feign是用于简化
RestTemplate
和Ribbon
的调用方式的。
; 2. Feign快速入门
2.1 前期准备( 初始默认代码
)
; 2.1.1 feign-parent模块
在父模块中,我们只需要在父模块的pom.xml中引入 spring-cloud依赖
即可
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.itheimagroupId>
<artifactId>feign-parentartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>eureka-servermodule>
<module>feign-providermodule>
<module>feign-consumermodule>
modules>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.1.0.RELEASEversion>
<relativePath/>
parent>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8project.reporting.outputEncoding>
<java.version>1.8java.version>
<spring-cloud.version>Greenwich.RELEASEspring-cloud.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>${spring-cloud.version}version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
project>
2.1.2 eureka-server模块
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>feign-parentartifactId>
<groupId>com.itheimagroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>eureka-serverartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
dependencies>
project>
application.yml
server:
port: 8761
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka
register-with-eureka: false
fetch-registry: false
server:
enable-self-preservation: false
eviction-interval-timer-in-ms: 3000
启动类
package com.itheima.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApp {
public static void main(String[] args) {
SpringApplication.run(EurekaApp.class,args);
}
}
2.1.3 feign-consumer模块
- pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>feign-parentartifactId>
<groupId>com.itheimagroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>feign-consumerartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
project>
- applicaion.yml
server:
port: 9000
eureka:
instance:
hostname: localhost
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: feign-consumer
- 启动类
package com.itheima.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableDiscoveryClient
@EnableEurekaClient
@SpringBootApplication
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}
- config配置类
package com.itheima.consumer.config;
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 RestTemplateConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
- controller控制类
package com.itheima.consumer.controller;
import com.itheima.consumer.domain.Goods;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/goods/{id}")
public Goods findGoodsById(@PathVariable("id") int id){
String url = "http://FEIGN-PROVIDER/goods/findOne/"+id;
Goods goods = restTemplate.getForObject(url, Goods.class);
return goods;
}
}
- domain实体类
package com.itheima.consumer.domain;
public class Goods {
private int id;
private String title;
private double price;
private int count;
public Goods() {
}
public Goods(int id, String title, double price, int count) {
this.id = id;
this.title = title;
this.price = price;
this.count = count;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
2.1.4 feign-provider模块
- pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>feign-parentartifactId>
<groupId>com.itheimagroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>feign-providerartifactId>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
dependencies>
project>
- application.yml
server:
port: 8001
eureka:
instance:
hostname: localhost
prefer-ip-address: true
ip-address: 127.0.0.1
instance-id: ${eureka.instance.ip-address}:${spring.application.name}:${server.port}
client:
service-url:
defaultZone: http://localhost:8761/eureka
spring:
application:
name: feign-provider
- 启动类(
无修改
)
package com.itheima.provider;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@EnableEurekaClient
@SpringBootApplication
public class ProviderApp {
public static void main(String[] args) {
SpringApplication.run(ProviderApp.class,args);
}
}
- domain实体类(
提供方和消费方的实体类一致
)
package com.itheima.provider.domain;
public class Goods {
private int id;
private String title;
private double price;
private int count;
public Goods() {
}
public Goods(int id, String title, double price, int count) {
this.id = id;
this.title = title;
this.price = price;
this.count = count;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
- dao层接口
package com.itheima.provider.dao;
import com.itheima.provider.domain.Goods;
import org.springframework.stereotype.Repository;
import javax.validation.ReportAsSingleViolation;
@Repository
public class GoodsDao {
public Goods findOne(int id){
return new Goods(1,"华为手机",3999,10000);
}
}
- service层接口
package com.itheima.provider.service;
import com.itheima.provider.dao.GoodsDao;
import com.itheima.provider.domain.Goods;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class GoodsService {
@Autowired
private GoodsDao goodsDao;
public Goods findOne(int id){
return goodsDao.findOne(id);
}
}
- controller控制类
package com.itheima.provider.controller;
import com.itheima.provider.domain.Goods;
import com.itheima.provider.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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;
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private GoodsService goodsService;
@Value("${server.port}")
private int port;
@GetMapping("/findOne/{id}")
public Goods findOne(@PathVariable("id") int id){
Goods goods = goodsService.findOne(id);
goods.setTitle(goods.getTitle() + ":" + port);
return goods;
}
}
2.2 Feign应用( 代码修改
)
- 在消费端引入 open-feign 依赖
- 编写Feign调用接口
- 在启动类添加EnableEeianClients注解,开启Feign功能
- 测试调用
2.2.1 feign-consumer模块
- 消费端引入 open-feign 依赖
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
- 编写Feign调用接口(包名:feign)
package com.itheima.consumer.feign;
import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "FEIGN-PROVIDER")
public interface GoodsFeignClient {
@GetMapping("/goods/findOne/{id}")
public Goods findOne(@PathVariable("id") int id);
}
别忘记
在消费方启动类开启Feign功能
package com.itheima.consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableDiscoveryClient
@EnableEurekaClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerApp {
public static void main(String[] args) {
SpringApplication.run(ConsumerApp.class,args);
}
}
修改config中 OrderController 代码
package com.itheima.consumer.controller;
import com.itheima.consumer.domain.Goods;
import com.itheima.consumer.feign.GoodsFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
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;
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private GoodsFeignClient goodsFeignClient;
@GetMapping("/goods/{id}")
public Goods findGoodsById(@PathVariable("id") int id){
Goods goods = goodsFeignClient.findOne(id);
return goods;
}
}
- 测试调用
- Feign 其他功能
3.1 超时设置
- Feign 底层依赖于Ribbon实现负载均衡和远程调用。
- Ribbon默认1秒超时
- 超时配置:
ribbon:
connectTimeout: 1000
ReadTimeout: 1000
即:
- 采用超时配置后,如果1秒后,
provider 没有向 consumer 反馈结果
。就会报一些错误。
浏览器报错
控制台报错
3.2 日志记录
Feign只能记录 debug 级别的日志信息。
- 在consumer模块中的applicaton.yml中设置下面信息
logging:
level:
com.itheima: debug
- 定义Feign日志级别Bean
package com.itheima.consumer.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignLogConfig {
@Bean
public Logger.Level level(){
return Logger.Level.FULL;
}
}
- 在GoodsFeignClient 启动该Bean
package com.itheima.consumer.feign;
import com.itheima.consumer.config.FeignLogConfig;
import com.itheima.consumer.domain.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "FEIGN-PROVIDER",configuration = FeignLogConfig.class)
public interface GoodsFeignClient {
@GetMapping("/goods/findOne/{id}")
public Goods findGoodsById(@PathVariable("id") int id);
}
- 重启oonsumer启动类,查看控制台信息
Original: https://blog.csdn.net/qq_40926887/article/details/127796500
Author: 捌椒
Title: SpringCloud基础知识【Feign声明式系统调用】
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/659282/
转载文章受原作者版权保护。转载请注明原作者出处!