概述
文章目录
- 项目整体结构
- 依赖
- openfeign的一些配置
- order-service-api
- order-service
- pay-service
- 测试
- 源码分析
- 源码下载
项目整体结构
说明:
- 所有公共依赖都放在了父pom中,API接口抽离放在单独模块
依赖
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Hoxton.SR8</spring-cloud.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
这里模拟支付服务调用订单服务,订单 order-service 会依赖于 order-service-api, pay-service 会依赖于 pay-service-api,同时因为要调用 订单服务,所以也会依赖于 order-service-api
这样做的好处是抽离了公共的接口,同事将model放在了公共API采用继承方式减少重复代码,不采用这种方式模块间的相互调用就会写重复的model和接口
openfeign的一些配置
feign:
client:
config:
# 全局级别配置
default:
connectTimeout: 5000
readTimeout: 5000
# 只打印基本信息,包括请求方法、请求地址、响应状态码、请求时长
loggerLevel: basic
我们也可以采用 @Configuration的 方式来配置 feign,如果配置文件和 @Configuration都配置了,配置文件将会覆盖@configuration 值,如果希望将优先级更改为@configuration,可以将 feign.client.default-to-properties 更改为 false
在 Feign 中,定义了四种日志级别:
- NONE:不打印日志
- BASIC:只打印基本信息,包括请求方法、请求地址、响应状态码、请求时长
- HEADERS:在 BASIC 基础信息的基础之上,增加请求头、响应头
- FULL:打印完整信息,包括请求和响应的所有信息。
更多信息请参考 springboot
order-service-api
结构:
- Order
@Data
public class Order {
/**
* 订单号
*/
private String orderNo;
/**
* 价格
*/
private BigDecimal price;
/**
* 商品数量
*/
private Integer orderCount;
}
- OrderService
@RestController
@RequestMapping("/order")
public interface OrderService {
@GetMapping(value = "/get-order",headers = {"Accept=application/json"})
Order getOrder(@RequestParam("orderNo")String orderNo);
}
order-service
结构:
- application.properties
server.port=8080
spring.application.name=order-service
- OrderServiceImpl
@Service
public class OrderServiceImpl implements OrderService {
@Override
public Order getOrder(String orderNo) {
System.out.println("收到的订单号为: " + orderNo);
Order order = new Order();
order.setOrderNo("123456");
order.setOrderCount(5);
order.setPrice(new BigDecimal("52.6"));
return order;
}
}
- OrderController
public class OrderController implements OrderService{
@Autowired
OrderService orderService;
@Override
public Order getOrder(String orderNo) {
return orderService.getOrder("123");
}
}
pay-service
目录结构:
- PayController
public class PayController implements PayService{
@Autowired
PayService payService;
@Override
public boolean pay() {
payService.pay();
return true;
}
}
- OrderServiceApi
@FeignClient(name = "order-service",url = "127.0.0.1:8080")
public interface OrderServiceApi extends OrderService {
}
这里name 是服务名 即订单服务,url是订单服务的访问地址,这里因为没有用到注册中心,所以需要写url
- PayServiceImpl
@Service
public class PayServiceImpl implements PayService {
@Autowired
private OrderServiceApi orderServiceApi;
@Override
public boolean pay() {
Order order = orderServiceApi.getOrder("123456");
System.out.println("获取到订单号" + order.getOrderNo());
return true;
}
}
这里的url也是支持占位符的 类似 这种 url = "${order.service.baseUrl} 然后将地址写在配置文件中也是可以的
项目大致结构是这样,pay-service-api 和 order-service-api类似,感兴趣可以自己去源码查看
然后我们需要在 order-service 和 pay-service 的启动类开启使用Fegin的注解
测试
然后同时启动 order-service 和 pay-service,注意自己在 配置文件配置不同的端口,idea启动多个实例请查看我以前的博客教程
然后访问调用 支付接口
这里可以看到调用Order-service 服务已经成功了
源码分析
首先我们 从 启动类的 @EnableFeignClients 注解分析
这里可以看到导入了一个配置类 EnableFeignClients
那么很明显 EnableFeignClients 配置类会将FeignClient注解的类注册到Spring IOC容器里供我们使用,我们来看看看 EnableFeignClients 核心代码
在 registerDefaultConfiguration 方法中
首先会去检测 EnableFeignClients 中是否配置 clients,如果没有配置则将 通过 @FeignClient 注解去找到相应的客户端,放入BeanDefinitionBuilder,然后根据BeanDefinitionBuilder得到beanDefinition,最后beanDefinition式注入到ioc容器
通过包扫描获取到 @FeignClient 的类的 beanDefinition
这里再调用 registerFeignClient 注入到IOC容器中
注入bean之后,通过jdk的代理,当请求Feign Client的方法时会被拦截,然后通过ReflectiveFeign类获取对象,代码如下:
public <T> T newInstance(Target<T> target) {
Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
Method[] var5 = target.type().getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method method = var5[var7];
if (method.getDeclaringClass() != Object.class) {
if (Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
}
InvocationHandler handler = this.factory.create(target, methodToHandler);
T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
Iterator var12 = defaultMethodHandlers.iterator();
while(var12.hasNext()) {
DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
源码下载
最后
以上就是大意唇膏为你收集整理的Springboot整合 openfeign(基于最新Hoxton.SR8)的全部内容,希望文章能够帮你解决Springboot整合 openfeign(基于最新Hoxton.SR8)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复