Github 使用示例(https://github.com/cky-thinker/spring-feign-client/blob/master/README.md)

在微服务架构中,如果使用得是SpringCloud,那么只需要集成SpringFeign就可以了,SpringFeign可以很友好的帮我们进行服务请求,对象解析等工作。

然而SpingCloud是依赖于SpringBoot的。在老的Spring项目中通常是没有集成SpringBoot,那么我们又该如何使用Feign组件进行调用呢?

这种情况下就只能使用原生Feign了,Feign使用手册:https://www.cnblogs.com/chenkeyu/p/9017996.html

使用原生Feign的两个问题:

  一、原生Feign只能一次解析一个接口,生成对应的请求代理对象,如果一个包里有多个调用接口就要多次解析非常麻烦。

  二、Feign生成的调用代理只是一个普通对象,该如何注册到Spring中,以便于我们可以使用@Autowired随时注入。

解决方案:

  一、针对多次解析的问题,可以通过指定扫描包路径,然后对包中的类依次解析。使用工具:https://github.com/lukehutch/fast-classpath-scanner

  二、实现BeanFactoryPostProcessor接口,扩展Spring容器功能。

具体代码:

  maven依赖:

<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-core</artifactId>
<version>8.18.0</version>
</dependency>
<dependency>
<groupId>com.netflix.feign</groupId>
<artifactId>feign-jackson</artifactId>
<version>8.18.0</version>
</dependency>
<dependency>
<groupId>io.github.lukehutch</groupId>
<artifactId>fast-classpath-scanner</artifactId>
<version>2.18.1</version>
</dependency>

  自定义注解:在扫描接口的过程中,可以通过一个自定义注解,来区分Feign接口并且指定调用的服务Url

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FeignApi {
/**
* 调用的服务地址
* @return
*/
String serviceUrl();
}

  生成Feign代理并注册到Spring实现类:

import feign.Feign;
import feign.Request;
import feign.Retryer;
import feign.jackson.JacksonDecoder;
import feign.jackson.JacksonEncoder;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component; import java.util.List; @Component
public class FeignClientRegister implements BeanFactoryPostProcessor{
//扫描的接口路径
private String scanPath="com.xxx.api"; @Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
List<String> classes = scan(scanPath);
if(classes==null){
return ;
}
System.out.println(classes);
Feign.Builder builder = getFeignBuilder();
if(classes.size()>0){
for (String claz : classes) {
Class<?> targetClass = null;
try {
targetClass = Class.forName(claz);
String url=targetClass.getAnnotation(FeignApi.class).serviceUrl();
if(url.indexOf("http://")!=0){
url="http://"+url;
}
Object target = builder.target(targetClass, url);
beanFactory.registerSingleton(targetClass.getName(), target);
} catch (Exception e) {
throw new RuntimeException(e.getMessage());
}
}
}
} public Feign.Builder getFeignBuilder(){
Feign.Builder builder = Feign.builder()
.encoder(new JacksonEncoder())
.decoder(new JacksonDecoder())
.options(new Request.Options(1000, 3500))
.retryer(new Retryer.Default(5000, 5000, 3));
return builder;
} public List<String> scan(String path){
ScanResult result = new FastClasspathScanner(path).matchClassesWithAnnotation(FeignApi.class, (Class<?> aClass) -> {
}).scan();
if(result!=null){
return result.getNamesOfAllInterfaceClasses();
}
return null;
}
}

调用接口编写示例:

import com.xiaokong.core.base.Result;
import com.xiaokong.domain.DO.DeptRoom;
import feign.Headers;
import feign.Param;
import feign.RequestLine;
import com.xiaokong.register.FeignApi; import java.util.List; @FeignApi(serviceUrl = "http://localhost:8085")
public interface RoomApi {
@Headers({"Content-Type: application/json","Accept: application/json"})
@RequestLine("GET /room/selectById?id={id}")
Result<DeptRoom> selectById(@Param(value="id") String id); @Headers({"Content-Type: application/json","Accept: application/json"})
@RequestLine("GET /room/test")
Result<List<DeptRoom>> selectList();
}

接口使用示例:

@Service
public class ServiceImpl{
//将接口注入要使用的bean中直接调用即可
@Autowired
private RoomApi roomApi; @Test
public void demo(){
Result<DeptRoom> result = roomApi.selectById("1");
System.out.println(result);
}
}

注意事项:

1.如果接口返回的是一个复杂的嵌套对象,那么一定要明确的指定泛型,因为Feign在解析复杂对象的时候,需要通过反射获取接口返回对象内部的泛型类型才能正确使用Jackson解析。

如果不明确的指明类型,Jackson会将json对象转换成一个LinkedHashMap类型。

2.如果你使用的是的Spring,又需要通过http调用别人的接口,都可以使用这个工具来简化调用与解析的操作。

不使用SpringBoot如何将原生Feign集成到Spring中来简化http调用的更多相关文章

  1. quartz 集成到Spring中

    记录一下,防止忘记. 需要的jar包,quartz-2.2.3.jar,commons-collection-3.1.jar,spring-context-support-4.3.4.RELEASE. ...

  2. SpringBoot 源码解析 (十)----- Spring Boot的核心能力 - 集成AOP

    本篇主要集成Sping一个重要功能AOP 我们还是先回顾一下以前Spring中是如何使用AOP的,大家可以看看我这篇文章spring5 源码深度解析----- AOP的使用及AOP自定义标签 Spri ...

  3. SpringBoot系列(六)集成thymeleaf详解版

    SpringBoot系列(六)集成thymeleaf详解版 1. thymeleaf简介  1. Thymeleaf是适用于Web和独立环境的现代服务器端Java模板引擎.  2. Thymeleaf ...

  4. Springboot系列(七) 集成接口文档swagger,使用,测试

    Springboot 配置接口文档swagger 往期推荐 SpringBoot系列(一)idea新建Springboot项目 SpringBoot系列(二)入门知识 springBoot系列(三)配 ...

  5. 微服务通信之feign集成负载均衡

    前言 书接上文,feign接口是如何注册到容器想必已然清楚,现在我们着重关心一个问题,feign调用服务的时候是如何抉择的?上一篇主要是从读源码的角度入手,后续将会逐步从软件构架方面进行剖析. 一.R ...

  6. CAS学习笔记五:SpringBoot自动/手动配置方式集成CAS单点登出

    本文目标 基于SpringBoot + Maven 分别使用自动配置与手动配置过滤器方式实现CAS客户端登出及单点登出. 本文基于<CAS学习笔记三:SpringBoot自动/手动配置方式集成C ...

  7. 一键式Spring集成工具 Spring Boot

    最近公司使用Spring boot进行开发,稍微了解一下,不过自我感觉把集中式配置applicate.properties搞明白,注解用过Spring MVC的boot绝对没问题的 比如拦截器:@As ...

  8. Redis篇之操作、lettuce客户端、Spring集成以及Spring Boot配置

    Redis篇之操作.lettuce客户端.Spring集成以及Spring Boot配置 目录 一.Redis简介 1.1 数据结构的操作 1.2 重要概念分析 二.Redis客户端 2.1 简介 2 ...

  9. 【笔记】android sdk集成的eclipse中导入项目

    android sdk集成的eclipse中导入项目 想要把旧的ADT项目,一模一样的导入进来,需要: 1.把项目放到,非当前ADT的workspace目录下: 2.从Project中Import,选 ...

随机推荐

  1. TensorFlow学习记录(一)

    windows下的安装: 首先访问https://storage.googleapis.com/tensorflow/ 找到对应操作系统下,对应python版本,对应python位数的whl,下载. ...

  2. Failed building wheel for scandir 解决方案

    unbuntu 16.04 运行 pip install jupyter --upgrade 的时候出现了下面的错误 Failed building wheel for scandir Running ...

  3. 会话机器人Chatbot的相关资料

    Chatbot简介 竹间智能简仁贤:打破千篇一律的聊天机器人 | Chatbot的潮流 重点关注其中关于情感会话机器人的介绍 当你对我不满的时候我应该怎么应对,当你无聊,跟我说你很烦的时候,我应该怎么 ...

  4. dw cs6 trial

    试用版: https://helpx.adobe.com/x-productkb/policy-pricing/cs6-product-downloads.html English/Japanese: ...

  5. STL-Deque 源码剖析

    G++ ,cygnus\cygwin-b20\include\g++\stl_deque.h 完整列表 /* * * Copyright (c) 1994 * Hewlett-Packard Comp ...

  6. CSS学习笔记三:自定义单选框,复选框,开关

    一点一点学习CCS,这次学习了如何自定义单选框,复选框以及开关. 一.单选框 1.先写好body里面的样式,先写几个框 <body> <div class="radio-1 ...

  7. Flask请求扩展和数据库连接池

    1.1.Flask之请求扩展 #!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask, Request, render ...

  8. 2017OKR年终回顾与2018OKR初步规划

    一.2017OKR - 年终回顾 自从6月份进行了年中总结,又是半年过去了,我的2017OKR又有了一些milestone.因此,按照国际惯例,又到了年终回顾的时候了,拉出来看看完成了多少.(以下目标 ...

  9. 洛谷 P2587 解题报告

    P2587 [ZJOI2008]泡泡堂 题目描述 第XXXX届NOI期间,为了加强各省选手之间的交流,组委会决定组织一场省际电子竞技大赛,每一个省的代表队由n名选手组成,比赛的项目是老少咸宜的网络游戏 ...

  10. 闲聊 “今日头条Go建千亿级微服务的实践”

      背景    今天跟同事偶然看到<今日头条Go建千亿级微服务的实践>文章,故做了一些探讨,与大家分享下,也欢迎大家多多共同探讨!.     其他资料:   如何理解 Golang 中“不 ...