SpringCloud如何利用Feign访问外部http请求

 更新时间:2022年03月10日 08:40:36   作者:wsdl-king  
这篇文章主要介绍了SpringCloud如何利用Feign访问外部http请求,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Feign访问外部http请求

大家好,目前接手了一个项目,具体的逻辑并不复杂,主要是一个"中间商"角色, 比如客户端通过我访问高德地图API,就不需要带秘钥,直接带高德API所需的入参和url后缀,就可以访问。

目前遇到这样一个问题,项目架构师要求所有的项目自己写的htttpClintUtils或者其他工具,需要替换到feign的形式来完成调用,但是,目前这个项目访问外部的http接口很多,比如,提供的高德服务就有10多种,一共有大几十类型,这样的话,如果按照以前的方式,一个接口指定一个高德子服务,那岂不是要累死 = =!

 累死人的写法:(仅参考)

@FeignClient(value = "test",url = "http://ip:port")
public interface TestFeign {
    /**
     * @return 高德服务接口
     * @description 访问高德地理编码服务
     */
    @PostMapping(value = "/Amap/geo")
    Object geo(@RequestBody GeoEntity entity);
 
    /**
     * @return 高德服务接口
     * @description 访问高德逆地理编码服务
     */
    @PostMapping(value = "/Amap/regeo")
    Object regeo(@RequestBody RegeoEntity entity);  
    .........
    ...........
}

然后如果我除了高德服务还有其他外部服务,并且其他外部服务下的子接口,不一定就两个,那这样写的话,要头大死,并且这样的写法,在服务的内部,不能做秘钥和权限的动态配置,只能在url上做指定,比较笨拙,所以就需要一种可以灵活访问外部httpClient的Feign接口,只需要我指定一个url,指定下提交的post数据,就可以得到返回结果,岂不是美滋滋?

话不多说,先上pom.xml

 <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.0.1.RELEASE</version>
        </dependency>
 
        <!-- 引入 httpclient -->
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
        </dependency>
        <dependency>
            <groupId>com.netflix.feign</groupId>
            <artifactId>feign-httpclient</artifactId>
            <version>8.18.0</version>
        </dependency>

前两个是feign和服务降级用到的包,后两个是用Apache Http替换原生的feign-http-client用来提供连接池等功能。

bootstap.yml 部分配置

feign:
  httpclient:
    enabled: true
  hystrix:
    enabled: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 3000  #降级超时时间,我设置为3秒。 feign.retry默认超时时间是5s.

设置了个降级超时时间,还有启动了feign访问外部httpClient配置和服务降级配置。

在spingbootApplication启动类上增加注解

@EnableFeignClients  @EnableHystrix

代码部分:

public interface HttpRequestFeign { 
    @RequestLine("GET")
    String sendGetRequest(URI baseUri);
 
    @RequestLine("POST")
    String sendPostRequest(URI baseUri, Map map);
}

调用部分,这里我在我的BaseController构造注解,其他服务Controller继承,提供调用能力:

 @Autowired
    public BaseController(Decoder decoder, Encoder encoder) {
        httpRequestFeign = Feign.builder().encoder(encoder).decoder(decoder)
                .target(Target.EmptyTarget.create(HttpRequestFeign.class)); 
    }
 protected String httpPostSend( String url, Map map) {
        String response = "";
        try {
            response = httpRequestFeign.sendPostRequest(new URI(url), map);
            logger.info("调用外部服务返回的数据为->{}", response);
            // 这里改成重试的超时异常
        } catch (RetryableException a) {
            logger.error("调用外部服超时错误->{}", response);
        } catch (Exception e) {
            logger.error("调用外部服异常错误->{}", response);
        }
        return response;
    }

这里只列举了Post的,Get方式,就不用了携带map参数了。

然后在你的Controller层增加降级@HystrixCommand注解,并指定降级方法:

 @HystrixCommand(fallbackMethod = "fallback")
 @PostMapping(value = "/1_0_0/{subServer}", produces = "application/json;charset=UTF-8")
 public Object send(@RequestBody Map<String, Object> map, @PathVariable String subServer) {
 
.......................
.................... 
 
 private Object fallback(Map<String, String> map, String subserver, Throwable e) {
        logger.error("xxx服务发生问题,入参:{},地址:{}", map, subserver);
        return Result.fail(ResultCode.INTERNAL_SERVER_ERROR.getCode(), ERROR_MSG + e.toString());
    }

在send方法里可以自行进行拼接url,而Map就是传递给第三方服务的数据。 

FeignClient外部http请求

springboot 4.0.0

pom.xml 引入openfeign 2.0.2

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-openfeign</artifactId>
                <version>2.0.2.BUILD-SNAPSHOT</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
<!--外部http请求 FeignClient-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
</dependencies>
<repositories>
        <!--外部http请求 FeignClient-->
        <repository>
            <id>spring-snapshots</id>
            <name>Spring Snapshots</name>
            <url>https://repo.spring.io/libs-snapshot</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </repository>
    </repositories>

启动类 添加注解@EnableFeignClients

@SpringBootApplication
@MapperScan("com.sichuang.repository.dao")//将项目中对应的mapper类的路径加进来就可以了
@ServletComponentScan
@EnableFeignClients
public class RepositoryApplication extends SpringBootServletInitializer{
    public static void main(String[] args) {
        SpringApplication.run(RepositoryApplication.class, args);
    }
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        // TODO Auto-generated method stub
//      return super.configure(builder);
        return builder.sources(RepositoryApplication.class);
    }
}

外部接口类。调用方式同service

@RequestParam 参数注解

produces = MediaType.APPLICATION_JSON_UTF8_VALUE 返回json参数

package com.sichuang.repository.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.Map;
/**
 * 对接接口
 *
 * @author xs
 * @date 2018/10/8 9:08
 */
@FeignClient(url = "${url}", name = "Ewaytec2001API")
public interface Ewaytec2001API {
    /**
     */
    @GetMapping(value = "${url}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    String getEmployeeInfo(@RequestParam("id") int id, @RequestParam("sign") String sign);
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • 详解Spring Boot Security工作流程

    详解Spring Boot Security工作流程

    Spring Security,这是一种基于 Spring AOP 和 Servlet 。这篇文章主要介绍了Spring Boot Security的相关知识,需要的朋友可以参考下
    2019-04-04
  • 详解SpringBoot+Thymeleaf 基于HTML5的现代模板引擎

    详解SpringBoot+Thymeleaf 基于HTML5的现代模板引擎

    本篇文章主要介绍了SpringBoot+Thymeleaf 基于HTML5的现代模板引擎,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • Spring Boot整合邮箱发送邮件实例

    Spring Boot整合邮箱发送邮件实例

    大家好,本篇文章主要讲的是Spring Boot整合邮箱发送邮件实例,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-02-02
  • 浅谈Java 8 新增函数式接口到底是什么

    浅谈Java 8 新增函数式接口到底是什么

    这篇文章主要介绍了浅谈Java 8 新增函数式接口到底是什么,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • JavaWeb简单文件上传流程的实战记录

    JavaWeb简单文件上传流程的实战记录

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,下面这篇文章主要给大家介绍了关于JavaWeb实现简单文件上传流程的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • java调用webservice接口,并解析返回参数问题

    java调用webservice接口,并解析返回参数问题

    这篇文章主要介绍了java调用webservice接口,并解析返回参数问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-07-07
  • spring cloud学习教程之config修改配置详解

    spring cloud学习教程之config修改配置详解

    这篇文章主要给大家介绍了关于spring cloud学习教程之config修改配置的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2017-09-09
  • 解密Java Map如何高效地操作键值对

    解密Java Map如何高效地操作键值对

    Map是Java中非常重要的数据结构之一,它存储键值对,可以通过键快速查找对应的值,是我们在实际开发中使用最为频繁的数据结构之一,下面小编就来和大家探讨一下Map是如何高效地操作键值对的吧
    2023-09-09
  • 浅谈springboot一个service内组件的加载顺序

    浅谈springboot一个service内组件的加载顺序

    这篇文章主要介绍了springboot一个service内组件的加载顺序,具有很好的参考价值,希望对大家有所帮助。以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家
    2021-08-08
  • Java线程让步yield用法实例分析

    Java线程让步yield用法实例分析

    这篇文章主要介绍了Java线程让步yield用法,结合实例形式分析了java中yield()方法的功能、原理及线程让步操作的相关实现技巧,需要的朋友可以参考下
    2019-09-09

最新评论