【SpringCloud】Re03 Feign
Feign是一个声明式的HttpClient?更简洁的实现Http请求发送
安装Feign组件:
配置Feign的依赖坐标:
<?xml version="1.0" encoding="UTF-8"?> <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>cloud-demo</artifactId> <groupId>cn.itcast.demo</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--eureka客户端依赖--> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>--> <!-- nacos客户端依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--feign客户端依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--引入HttpClient依赖--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> <!--引入feign的统一api--> <dependency> <groupId>cn.itcast.demo</groupId> <artifactId>feign-api</artifactId> <version>1.0</version> </dependency> </dependencies> <build> <finalName>app</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
启动类注册Feign
package cn.itcast.order; import cn.itcast.feign.clients.UserClient; import cn.itcast.feign.config.DefaultFeignConfiguration; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @MapperScan("cn.itcast.order.mapper") @SpringBootApplication @EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class) public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } /** * 创建RestTemplate并注入Spring容器 */ @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } /* @Bean public IRule randomRule() { return new RandomRule(); }*/ }
编写Feign客户端接口?
package cn.itcast.feign.clients; import cn.itcast.feign.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "userservice") public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
Feign的内部已经集成了Ribbon,使用方法不变
全局配置方式
server: port: 8088 spring: datasource: url: jdbc:mysql://mysql:3308/cloud_order?useSSL=false username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver application: name: orderservice cloud: nacos: server-addr: nacos:8848 # nacos服务地址 # discovery: # namespace: 4d6ce343-9e1b-44df-a90f-2cf2b6b3d177 # dev环境 # ephemeral: false # 是否是临时实例 mybatis: type-aliases-package: cn.itcast.user.pojo configuration: map-underscore-to-camel-case: true logging: level: cn.itcast: debug pattern: dateformat: MM-dd HH:mm:ss:SSS #eureka: # client: # service-url: # eureka的地址信息 # defaultZone: http://127.0.0.1:10086/eureka userservice: ribbon: NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 ribbon: eager-load: enabled: true # 开启饥饿加载 clients: # 指定饥饿加载的服务名称 - userservice feign: httpclient: enabled: true # 支持HttpClient的开关 max-connections: 200 # 最大连接数 max-connections-per-route: 50 # 单个路径的最大连接数 client: config: default: # default 表示全局生效 | 局部生效 指定服务名称 userservice 针对某一个服务进行配置 loggerLevel: FULL
局部配置方式
client:
config:
服务名: # default 表示全局生效 | 局部生效 指定服务名称 userservice 针对某一个服务进行配置
loggerLevel: FULL
Java代码配置方式:
package cn.itcast.feign.config; import feign.Logger; import org.springframework.context.annotation.Bean; public class DefaultFeignConfiguration { @Bean public Logger.Level logLevel(){ return Logger.Level.BASIC; } }
全局配置位置在启动类上注解:
package cn.itcast.order; import cn.itcast.feign.clients.UserClient; import cn.itcast.feign.config.DefaultFeignConfiguration; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.loadbalancer.LoadBalanced; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Bean; import org.springframework.web.client.RestTemplate; @MapperScan("cn.itcast.order.mapper") @SpringBootApplication @EnableFeignClients(clients = UserClient.class,defaultConfiguration = DefaultFeignConfiguration.class) public class OrderApplication { public static void main(String[] args) { SpringApplication.run(OrderApplication.class, args); } /** * 创建RestTemplate并注入Spring容器 */ @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } /* @Bean public IRule randomRule() { return new RandomRule(); }*/ }
局部单个服务在Feign定义的服务接口上配置:
package cn.itcast.feign.clients; import cn.itcast.feign.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClientProperties; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "userservice", configuration = FeignClientProperties.FeignClientConfiguration.class) public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
Feign性能调整:
引入Feign的HttpClient依赖:
<?xml version="1.0" encoding="UTF-8"?> <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>cloud-demo</artifactId> <groupId>cn.itcast.demo</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--eureka客户端依赖--> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>--> <!-- nacos客户端依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--feign客户端依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--引入HttpClient依赖--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> <!--引入feign的统一api--> <dependency> <groupId>cn.itcast.demo</groupId> <artifactId>feign-api</artifactId> <version>1.0</version> </dependency> </dependencies> <build> <finalName>app</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Feign的连接池配置:
server: port: 8088 spring: datasource: url: jdbc:mysql://mysql:3308/cloud_order?useSSL=false username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver application: name: orderservice cloud: nacos: server-addr: nacos:8848 # nacos服务地址 # discovery: # namespace: 4d6ce343-9e1b-44df-a90f-2cf2b6b3d177 # dev环境 # ephemeral: false # 是否是临时实例 mybatis: type-aliases-package: cn.itcast.user.pojo configuration: map-underscore-to-camel-case: true logging: level: cn.itcast: debug pattern: dateformat: MM-dd HH:mm:ss:SSS #eureka: # client: # service-url: # eureka的地址信息 # defaultZone: http://127.0.0.1:10086/eureka userservice: ribbon: NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则 ribbon: eager-load: enabled: true # 开启饥饿加载 clients: # 指定饥饿加载的服务名称 - userservice feign: httpclient: enabled: true # 支持HttpClient的开关 max-connections: 200 # 最大连接数 max-connections-per-route: 50 # 单个路径的最大连接数 # client: # config: # default: # default 表示全局生效 | 局部生效 指定服务名称 userservice 针对某一个服务进行配置 # loggerLevel: FULL
Feign的最佳使用方式
使用接口来共同约束编写规范
官方不推荐这种方式,紧耦合,约束过强,SpringMVC支持其他Http对象入参,被约束后将不适用
好处就是没有规范争议,闭着眼睛只管实现就完了
方式二:直接放在Common模块中,统一声明一系列配置,实体类,API接口
不管是哪个服务都统一从这里面进行资源调取
这个Feign-API POM信息:
<?xml version="1.0" encoding="UTF-8"?> <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>cloud-demo</artifactId> <groupId>cn.itcast.demo</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>feign-api</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> </dependencies> </project>
User实体类:
package cn.itcast.feign.pojo; import lombok.Data; @Data public class User { private Long id; private String username; private String address; }
Feign的日志配置:
package cn.itcast.feign.config; import feign.Logger; import org.springframework.context.annotation.Bean; public class DefaultFeignConfiguration { @Bean public Logger.Level logLevel(){ return Logger.Level.BASIC; } }
Feign接口:
package cn.itcast.feign.clients; import cn.itcast.feign.pojo.User; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClientProperties; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @FeignClient(value = "userservice", configuration = FeignClientProperties.FeignClientConfiguration.class) public interface UserClient { @GetMapping("/user/{id}") User findById(@PathVariable("id") Long id); }
其他服务安装Feign-API,从Feign-API里面获取即可:
<?xml version="1.0" encoding="UTF-8"?> <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>cloud-demo</artifactId> <groupId>cn.itcast.demo</groupId> <version>1.0</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!--eureka客户端依赖--> <!--<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>--> <!-- nacos客户端依赖包 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!--feign客户端依赖--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-openfeign</artifactId> </dependency> <!--引入HttpClient依赖--> <dependency> <groupId>io.github.openfeign</groupId> <artifactId>feign-httpclient</artifactId> </dependency> <!--引入feign的统一api--> <dependency> <groupId>cn.itcast.demo</groupId> <artifactId>feign-api</artifactId> <version>1.0</version> </dependency> </dependencies> <build> <finalName>app</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>