openfeign概念
feign和openfeign的区别:
feign | openfeign |
---|---|
Feign是一个spring cloud组件中一个轻量级RESTFul的HTTP服务客户端,feign内置了Ribbon,用于客户端的负载均衡。 | openfeign是springcloud在feign的基础上支持了springMVC的注解,如@RequestMapping,openfeign的@FeignClient可以解析SpringMVC的RequestMapping下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。 |
基本上不会再使用该方法了 | org.springframework.cloud spring-cloud-starter-openfeign 3.1.1 |
openfeign的日志打印:
FULL显示示例:
注意这里是的的注册中心为eureka,且为了很好的进行包的管理,这里创建一个父工程
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.6.5version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>2021.0.1version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2021.0.1.0version>
<type>pomtype>
<scope>importscope>
dependency>
dependencies>
dependencyManagement>
<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.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
dependency>
<dependency>
<groupId>com.qiugroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-serverartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #注册中心地址
package com.qiumin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //开启eureka服务
public class eurekaServer7001 {
public static void main(String[] args) {
SpringApplication.run(eurekaServer7001.class,args);
}
}
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>com.qiugroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
<version>2.6.5version>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.2.2version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>8.0.28version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
<version>2.2.2.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<version>2.6.5version>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
server:
port: 8001
spring:
application:
name: cloud-provide-payment #服务名称
datasource: #数据源
username: root
password: 123456
url: jdbc:mysql://localhost:3306/cloud?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
filters: stat,wall,log4j
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
mybatis: #mybatis相关配置
mapper-locations: classpath:mybatis/mapper/*.xml
type-aliases-package: com.qiumin.pojo
eureka:
client:
register-with-eureka: true #注册到注册中心
service-url:
defaultZone: http://localhost:7001/eureka #注册中心地址
instance:
instance-id: payment8001 #处理在eureka中的显示
prefer-ip-address: true
lease-renewal-interval-in-seconds: 2 #
lease-expiration-duration-in-seconds: 4
package com.qiumin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient //开启服务发现客户端
public class paymentApplication {
public static void main(String[] args) {
SpringApplication.run(paymentApplication.class, args);
}
}
package com.qiumin.service;
import com.qiumin.mapper.PaymentDao;
import com.qiumin.pojo.Payment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PaymentServiceImpl implements PaymentService{
@Autowired
PaymentDao paymentDao;
@Override
public Payment query(int id) {
return paymentDao.query(id);
}
@Override
public int insert(Payment payment) {
return paymentDao.insert(payment);
}
}
package com.qiumin.controller;
import com.qiumin.pojo.CommonResult;
import com.qiumin.pojo.Payment;
import com.qiumin.service.PaymentServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Slf4j
public class PaymentController {
@Autowired
PaymentServiceImpl paymentService;
@Value("${server.port}")
String serverPort;
@RequestMapping("/payment/query/{id}")
@ResponseBody
public CommonResult<Payment> query(@PathVariable("id") int id){
Payment query = paymentService.query(id);
// int age=10/0; 用于监测是否服务降级而设置
log.info("======查询结果"+query+"=====");
if (query!=null){
return new CommonResult(200,"查询数据库成功=== serverPort为 "+serverPort,query);
}else {
return new CommonResult(444,"查询数据库失败=== serverPort为 "+serverPort,null);
}
}
@RequestMapping("/payment/create")
@ResponseBody
public CommonResult<Payment> create(Payment payment){
int result = paymentService.insert(payment);
log.info("======插入结果"+payment+"=====");
if (result>0){
return new CommonResult(200,"插入数据库成功=== serverPort为 "+serverPort,payment);
}else {
return new CommonResult(444,"插入数据库失败=== serverPort为 "+serverPort,null);
}
}
}
其他的mapper、pojo、mapper.xml自动补全这里只是演示openfeign远程调用
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>com.qiugroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
<version>2.6.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<version>2.6.5version>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
server:
port: 8888
spring:
application:
name: cloud-consumer-order #服务名
eureka:
client:
register-with-eureka: true #注册到注册中心
service-url:
defaultZone: http://localhost:7001/eureka #注册中心地址
ribbon:
#建立连接所用时间
ReadTimeout: 5000
#服务读取数据可用时间
ConnectTimeout: 5000 #负载均衡超时配置
logging:
level:
com.qiumin.client.paymentClient: debug #eureka日志打印
package com.qiumin.client;
import com.qiumin.pojo.CommonResult;
import com.qiumin.pojo.Payment;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Component
@FeignClient(value = "CLOUD-PROVIDE-PAYMENT") //指定注册到注册中心的该服务名下的接口方法
public interface paymentClient {
//服务端即服务提供者的接口方法
@RequestMapping("/payment/query/{id}") //服务端的访问地址
CommonResult<Payment> query(@PathVariable("id") int id);
//服务端即服务提供者的接口方法
@RequestMapping("/payment/create")
CommonResult<Payment> insert(Payment payment);
}
package com.qiumin.config;
import feign.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class FeignConfig {
@Bean
Logger.Level feignLoggerLevel(){
return Logger.Level.FULL; //日志全打印
}
}
package com.qiumin.controller;
import com.qiumin.client.paymentClient;
import com.qiumin.pojo.CommonResult;
import com.qiumin.pojo.Payment;
import lombok.extern.slf4j.Slf4j;
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;
@RestController
@Slf4j
public class OrderController {
@Autowired
paymentClient paymentClient;
@RequestMapping("/consumer/payment/query/{id}") //调用该路径实际是通过openfeign调用远程服务
public CommonResult<Payment> query(@PathVariable("id") int id){
log.info("进入了该方法!!");
return paymentClient.query(id);
}
@RequestMapping("/consumer/payment/create")
public CommonResult<Payment> insert(Payment payment){
return paymentClient.insert(payment);
}
@RequestMapping("/test")
public String test(){
return "成功";
}
}
package com.qiumin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient //开启eureka客户端
@EnableFeignClients //开启openfeign远程调用
public class consumerApplication {
public static void main(String[] args) {
SpringApplication.run(consumerApplication.class, args);
}
}
<dependencies>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-hystrixartifactId>
<version>2.2.10.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-openfeignartifactId>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
dependency>
<dependency>
<groupId>com.qiugroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
<version>2.6.5version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-devtoolsartifactId>
<version>2.6.5version>
<scope>runtimescope>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
server:
port: 8888
spring:
application:
name: cloud-consumer-order
eureka:
client:
register-with-eureka: true
service-url:
defaultZone: http://localhost:7001/eureka
feign:
circuitbreaker:
enabled: true //开启服务降级
package com.qiumin.client;
import com.qiumin.pojo.CommonResult;
import com.qiumin.pojo.Payment;
import com.qiumin.service.FallbackService;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@Component
@FeignClient(value = "CLOUD-PROVIDE-PAYMENT",fallback = FallbackService.class) //对应一个服务降级的类,见下
public interface paymentClient {
@RequestMapping("/payment/query/{id}")
CommonResult<Payment> query(@PathVariable("id") int id);
@RequestMapping("/payment/create")
CommonResult<Payment> create(Payment payment);
}
该类实现client接口,即接口中的所有方法
package com.qiumin.service;
import com.qiumin.client.paymentClient;
import com.qiumin.pojo.CommonResult;
import com.qiumin.pojo.Payment;
import org.springframework.stereotype.Component;
@Component
public class FallbackService implements paymentClient {
@Override
public CommonResult<Payment> query(int id) {
return new CommonResult(444,"请求获取数据超时或错误,进行了服务降级操作!!!",null);
}
@Override
public CommonResult<Payment> create(Payment payment) {
return new CommonResult(444,"请求获取数据超时或错误,进行了服务降级操作!!!",null);
}
}
package com.qiumin.controller;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.qiumin.client.paymentClient;
import com.qiumin.pojo.CommonResult;
import com.qiumin.pojo.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@Slf4j
public class OrderController {
@Autowired
paymentClient paymentClient;
@RequestMapping("/consumer/payment/query/{id}")
@ResponseBody
//注意使用该方法时不需加 @HystrixCommand注解
public CommonResult<Payment> query(@PathVariable("id") int id){
log.info("进入了该方法!!");
return paymentClient.query(id);
}
@RequestMapping("/consumer/payment/create")
@ResponseBody
public CommonResult<Payment> create(Payment payment){
return paymentClient.create(payment);
}
@RequestMapping("/test")
@ResponseBody
public String test(){
return "成功";
}
}
package com.qiumin;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient //eureka
@EnableFeignClients //开启openfeign远程调用
@EnableCircuitBreaker //开启服务降级
public class consumerHOApplication {
public static void main(String[] args) {
SpringApplication.run(consumerHOApplication.class, args);
}
}
启动测试
qiumin