SpringBoot项目整合OpenFeign

  • 基础操作
    • pom依赖
    • 配置application.yml
    • 服务启动类
    • 基础跨服务调用
  • 动态IP+URL请求 + 动态编码器\解码器
    • 自定义跨服务请求,Encoder编译器
    • 自定义跨服务响应,Decoder 解码器
    • 方式1:`FeignFactory.class`
      • 工具类: `FeignUtils.class`
    • 方式2:`FeignApiFactory.class`

基础操作

pom依赖

OpenFeign是Spring Cloud在Feign的基础上支持了SpringMVC的注解,如@RequestMapping等等。OpenFeign的@FeignClient可以解析SpringMVC的@RequestMapping注解下的接口,并通过动态代理的方式产生实现类,实现类中.

<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency> 

配置application.yml

#====《跨服务HTTP接口请求工具》====
feign:client:config:#可指定需要配置的:服务名称# manage-client:#或 默认配置:全局default:#日志打印级别loggerLevel: basic#跨服务接口请求超时readTimeout: 5000#跨服务请求连接超时connectTimeout: 5000

服务启动类

启动类加上注解:@EnableDiscoveryClient

@SpringBootApplication
@EnableDiscoveryClient
public class OpenFeignServer {public static void main(String[] args) {SpringApplication.run(OpenFeignServer.class, args);}
}

基础跨服务调用

/*** @Author Owen* @Date 2020/8/18* @Description Admin后台管理服务*/
@FeignClient("serverName")
public interface AdminServiceClient {@RequestMapping(value = "/XXX/XXXX/XXXX", method = RequestMethod.GET, produces = {"application/json"}, consumes = {"application/glue+json"})<T> T doGet(@RequestParam("params") String params);@RequestMapping(value = "/XXX/XXXX/XXXX", method = RequestMethod.PUT, produces = {"application/json"}, consumes = {"application/communication+json"})<T> T doPut(@RequestBody Object params);@RequestMapping(value = "/XXX/XXXX/XXXX", method = RequestMethod.POST, produces = {"application/json"}, consumes = {"application/communication+json"})<T> T doPost(@RequestBody Object params);}

动态IP+URL请求 + 动态编码器\解码器

自定义跨服务请求,Encoder编译器

import com.details.utils.ConvertUtils;
import com.details.utils.JsonUtils;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import feign.RequestTemplate;
import feign.Util;
import feign.codec.EncodeException;
import feign.codec.Encoder;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Map;/*** @author Owen* @date 2022/10/22 21:10* @Description:自定义Feign跨服务请求,编译器*/
@Slf4j
public class FeignEncoder implements Encoder {ObjectMapper mapper = new ObjectMapper();@SneakyThrows@Overridepublic void encode(Object object, Type bodyType, RequestTemplate template) {log.info("Feign requset encode details: {}", object);try {//获取请求头详情Map<String, Collection<String>> headers = template.headers();//查看请求方式Collection<String> contentType = headers.get("Content-Type");//Json请求方式if (CollectionUtils.isNotEmpty(contentType) && contentType.contains("application/json") && !(object instanceof String)) {template.body(JsonUtils.object2Json(object));}//字符串else if (object instanceof String) {template.body(object.toString());} else {JavaType javaType = this.mapper.getTypeFactory().constructType(bodyType);template.body(ConvertUtils.writeAsBytes(javaType, object), Util.UTF_8);}} catch (Exception e) {throw new EncodeException(String.format("%s is not a type supported by this encoder.", object.getClass()));}}
}

自定义跨服务响应,Decoder 解码器

import feign.Response;
import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Type;/*** @author Owen* @date 2022/10/22 21:10* @Description:自定义Feign跨服务响应,解码器*/
@Slf4j
public class FeignDecoder implements Decoder {@Overridepublic Object decode(Response response, Type type) {log.info("URL:[{}] response result: {}", response.request().url(), response);return response.body();}
}

方式1:FeignFactory.class

动态URL

import feign.*;
import java.net.URI;/*** @Author: Owen* @Date: 2022/10/22* @Description:Feign公共接口(自定义请求API,内部请求)*/
public interface FeignFactory {/*** @param host 接口主机地址,如:http://localhost:8080,该参数是实现动态URL的关键* @param path 接口路径,如:/test/hello* @param body 请求消息体对象* @Author: Owen* @Date: 2022/10/22* @Description:通用POST请求,请求消息体格式为JSON*/@RequestLine("POST {path}")@Headers({"Content-Type: application/json", "Accept: application/json"})<T> T doPost(URI host,@Param("path") String path, Object body);/*** @param host 接口主机地址* @param path 接口路径,如:/test/hello* @Author: Owen* @Date: 2022/10/22* @Description:通用Get请求*/@RequestLine("POST {path}")<T> T doGet(URI host, @Param("path") String path);}

工具类: FeignUtils.class

import com.alibaba.nacos.api.naming.pojo.Instance;
import com.details.nacos.NacosFactory;
import com.details.utils.CacheUtils;
import com.details.utils.ExceptionUtils;
import com.details.utils.IocUtils;
import com.details.utils.TcpIpUtils;
import feign.Feign;
import feign.Logger;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.slf4j.Slf4jLogger;
import lombok.extern.slf4j.Slf4j;
import java.net.URI;
import java.util.*;/*** @author: Owen* @date: 2021/3/24* @description:跨服务API请求工具 集成Spring openfeign各个功能* 动态设置 编译器 解码器 熔断器* 跨服务器 动态API请求 自定义构建 IP(单机\集群)+服务名*/
@Slf4j
public class FeignUtils {private static  Feign.Builder  feignClient = null; /*** @param ip   对应服务器公网IP* @param path API接口地址* @Author: Owen* @Date: 2022/10/22* @Description:通用Get请求*/public static <T> T doGet(String ip, String path) {T result = null;ExceptionUtils.isBlank(ip, "Params :[ip] is null !");ExceptionUtils.isBlank(ip, "Params :[path] is null !");ExceptionUtils.isTrue(!ip.contains(":"), "Ip port not null!");ExceptionUtils.isTrue(!ip.contains("http://"), "Ip formal error, lack \"http://\"");try {//构建Feign基础实例Feign.Builder client = feigenClient();ExceptionUtils.isNull(client, "Feign client is null !");//自定义配置client.encoder(new FeignEncoder()); //API请求 编译器client.decoder(new FeignDecoder()); //API响应 解码器client.logger(new Slf4jLogger());   //日志client.logLevel(Logger.Level.FULL); //日志级别//构建工厂//注意:这里的url参数不能为空字符串,但是可以设置为任意字符串值,在这里设置为“EMPTY”FeignFactory factory = client.target(FeignFactory.class, "EMPTY");//跨服务请求result = factory.doGet(URI.create(ip), path);} catch (Exception e) {log.error("HTTP get requset faild: {}", e.getMessage());}return result;}/*** @param ip   对应服务器公网IP* @param path API接口地址* @param body Json数据体* @Author: Owen* @Date: 2022/10/22* @Description:跨服务POST请求接口,类型:application/json*/public static <T> T doPost(String ip, String path, Object body) {T result = null;ExceptionUtils.isBlank(ip, "Params :[ip] is null !");ExceptionUtils.isBlank(ip, "Params :[path] is null !");ExceptionUtils.isNull(body, "Params :[body] is null !");ExceptionUtils.isTrue(!ip.contains(":"), "ip port not null!");ExceptionUtils.isTrue(!ip.contains("http://"), "Ip formal error, lack \"http://\"");try {//构建Feign基础实例Feign.Builder client = feigenClient();ExceptionUtils.isNull(client, "Feign client is null !");//自定义配置client.encoder(new FeignEncoder()); //API请求 编译器client.decoder(new FeignDecoder()); //API响应 解码器client.logger(new Slf4jLogger());   //日志client.logLevel(Logger.Level.FULL); //日志级别FeignFactory factory = client.target(FeignFactory.class, ip);//跨服务请求result = factory.doPost(URI.create(ip), path, body);} catch (Exception e) {log.error("HTTP post requset faild: {}", e.getMessage());}return result;}/*** @author: Owen* @date: 2020/12/4* @description:获取Feign实例(单例模式)*/private static Feign.Builder feigenClient() {try {//feign客户端(http跨服务请求 单例模式)if (Objects.isNull(feigenClient)) {//第一次判空//保证线程安全synchronized (Feign.Builder.class) {//第二次判空,保证单例对象的唯一性,防止第一次有多个线程进入第一个if判断if (Objects.isNull(feigenClient)) {try {feigenClient = Feign.builder();} catch (Exception e) {log.error("Feigen client initialize fail: " +e.getMessage());}}}}} catch (Exception e) {log.error("Feigen client get faild: {}", e.getMessage());}return feigenClient;}
}

方式2:FeignApiFactory.class

import feign.*;
import feign.codec.Decoder;
import feign.codec.Encoder;
import feign.slf4j.Slf4jLogger;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.context.annotation.Bean;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import java.net.URI;/*** @Author: Owen* @Date: 2022/10/22* @Description:Feign公共接口(走网关转发)*/
@FeignClient(value = "server-gateway", url = "EMPTY", configuration = FeignApiFactory.CallbackConfiguration.class)
public interface FeignApiFactory {/*** @param host 接口主机地址,如:http://localhost:8080* @param path 接口路径,如:/test/hello* @param body 请求消息体对象* @Author: Owen* @Date: 2022/10/22* @Description: 统一回调接口方法,请求消息体格式为JSON,响应消息体格式也为JSON*/@RequestMapping(value = "{path}", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)<T> T doPost(URI host, @PathVariable("path") String path, @RequestBody Object body);/*
==========《Deme》==========:String uri = "http://localhost:8080";Map<String, Object> queryMap = new HashMap<>(0);queryMap.put("k","v");Map<String,Object> body = new hashMap<String,Object>();body.put("params1","value");Object result = this.callbackAPI.callback(URI.create(uri), "/test/apiTest", queryMap, body);
*///自定义回调接口配置@Componentclass CallbackConfiguration {@Beanpublic Encoder feignEncoder() {return new FeignEncoder();}@Beanpublic Decoder feignDecoder() {return new FeignDecoder();}@Beanpublic Retryer feignRetryer() {return new Retryer.Default();}@Beanpublic Logger feignLogger() {return new Slf4jLogger();}@Beanpublic Logger.Level feignLoggerLevel() {return Logger.Level.FULL;}}
}

SpringBoot项目整合OpenFeign、实现动态IP+URL请求、自定义(编码器\解码器)相关推荐

  1. Docker 部署 SpringBoot 项目整合 Redis 镜像做访问计数Demo

    Docker 部署SpringBoot项目整合 Redis 镜像做访问计数Demo 最终效果如下 大概就几个步骤 1.安装 Docker CE 2.运行 Redis 镜像 3.Java 环境准备 4. ...

  2. springboot项目整合mybatis

    SpringBoot项目整合mybatis 本章内容 使用 idea创建 SpringBoot项目 SpringBoot项目中配制 mybatis 框架 1 创建 SpringBoot项目 1.1 在 ...

  3. springboot项目整合阿里云oss的内容审核

    springboot项目整合阿里云 内容审核 第一 添加依赖 <dependency><groupId>com.aliyun</groupId><artifa ...

  4. Nginx安装配置与SpringBoot项目整合

    本篇文章将在上篇<Redis安装与SpringBoot项目整合详细教程>(上文链接:https://blog.csdn.net/sp958831205/article/details/88 ...

  5. Java springBoot项目整合海康威视摄像头抓拍车辆功能

    Java springBoot项目整合海康威视摄像头抓拍获取车辆信息功能 这篇文字写于去年的11月份,项目部署上去一段时间后,被反应有自动停止抓拍的BUG,我在代码中的解决办法是写了一个定时任务, 让 ...

  6. SpringBoot项目整合Retrofit最佳实践,这才是最优雅的HTTP客户端工具!

    作者:六点半起床 juejin.im/post/6854573211426750472 大家都知道okhttp是一款由square公司开源的java版本http客户端工具.实际上,square公司还开 ...

  7. springboot系列学习(十九):springboot项目整合Druid,Druid到底是什么,他是在项目中如何使用的

    目录 Druid是什么 先看一下之前的整合的jdbc使用的数据源是什么 创建一个springboot项目,导入Druid依赖 写一个Druid的配置类 yml文件和配置类绑定,这个之前就写过 解释以上 ...

  8. spring-boot项目整合obs服务器-华为云

    目录 前言 1.购买服务并从官网获得我们项目所需的配置参数 1-1.登录华为云 1-2.进入控制台 1-3.创建桶 ​ ​1-4.获取sk.ak 2.spring-boot项目集成OBS服务器 2-1 ...

  9. OAuth2.0 社交登录-Gitee springboot项目整合(微服务分布式)完整代码包括 数据库、前、后端

    文章目录 社交登录(Gitee) 1.模拟请求 项目整合 1.数据库增加字段 2.前端 2.后端 社交登录(Gitee) 完成这个踩了很多坑,包括第一时间忘了浏览器缓存这回事以及微博一些平台申请社交登 ...

最新文章

  1. SortedMap接口
  2. Java基于FTPClient上传文件到FTP服务器
  3. JDBC详解系列之流程
  4. javascript权威指南--学习笔记
  5. win10开机时不显示锁屏壁纸
  6. sublime 执行print带有中文时出错Decode error - output not utf-8
  7. 1. COM编程——什么是组件
  8. 客户关系管理软件的作用是什么?
  9. ms17010漏洞复现-2003
  10. oracle磁带库清洁带标签,LTO-1/2/3/4/5/6/7/8 Ultrium数据磁带 清洗带 清洁带 磁带标签批发...
  11. Unity 鼠标进入UI控件,显示控件名称
  12. java论坛 基于SSM框架的游戏论坛 java游戏贴吧 java游戏论坛 java论坛 ssm论坛 ssm贴吧 可以改为各种论坛,分类可在后台自己控制,图片可任意换
  13. 开关电源中电容与电感时间常数
  14. 怎么用python编写心形图案,python编程爱心形状turtle
  15. 50个SQL语句练习题
  16. OSChina 周六乱弹 —— 周六啦,我们一起去堆雪人吧~
  17. 网站底部的统计代码HTML
  18. 如何用VR改变驾驶陋习?
  19. unix sed命令
  20. 关于键盘asdw键和上下左右键互换问题

热门文章

  1. 【网络设备配置与管理实验一】PT 设置主机名,IP 地址
  2. 机器学习算法系列(十五)-软间隔支持向量机算法(Soft-margin Support Vector Machine)
  3. webflux oracle,從MVC到WebFlux
  4. 安装baidupcs-go
  5. oracle踩坑: [Err] ORA-00911: invalid character
  6. pcap文件格式及文件解析
  7. 计算机找不到wlan,Win10网络设置找不到wlan选项怎么办?
  8. 时间频度,时间复杂度的计算
  9. 服务器安装Centos教程
  10. Slackel Live ,惊艳与惊讶并存