[JAVA] Feign如何实现第三方的HTTP请求

1660 0
Honkers 2022-11-8 17:31:49 | 显示全部楼层 |阅读模式
目录

    Feign调用的简单实现
      1. 默认模式,不使用配置类,作用于服务内部调用而非三方请求接口2.自定义配置类3.自定义配置类法2 4. @FeignClient参数说明5. 自定义配置的简单实现6. Feign 的其他请求方式


最近,在使用spring cloud框架时,发现feign也能实现三方请求,而且实现很简单,请求接口的结构很清晰,便果断学习一波。
记录一下。本次使用的依赖仅有openfeign。

Feign调用的简单实现

maven依赖
  1.     <!-- openfeign依赖 -->
  2.     <dependency>
  3.       <groupId>org.springframework.cloud</groupId>
  4.       <artifactId>spring-cloud-starter-openfeign</artifactId>
  5.     </dependency>
复制代码
Feign配置方式
feign有三种使用方式,前一种多是用于无需配置的微服务内部调用,后两者是用于自定义配置的三方调用或者内部微服务调用。

1. 默认模式,不使用配置类,作用于服务内部调用而非三方请求接口

这种情况下,如果不需要给注册中心的微服务添加额外的参数配置,那么可以不使用配置类,直接在yml配置打开feign开关即可。
此时默认使用SpringMVC契约模式。如下代码中,yml配置为用户中心的配置文件。
如果一个业务中心想要根据用户id查询用户信息,那么便可以直接根据用户中心的服务名定位,如UserService 类中的@FeignClient配置,注册中心会自动根据服务名寻址到用户中心的地址。
  1. # 用户中心的服务名
  2. spring:
  3.   application:
  4.     name: user-service
  5. # 注册中心
  6. eureka:
  7.   instance:
  8.     prefer-ip-address: true
  9.     hostname: localhost
  10.   client:
  11.     service-url:
  12.       defaultZone: http://localhost:8080/eureka/
  13. # feign
  14. feign:
  15.   httpclient:
  16.     enabled: true
复制代码
  1. @FeignClient(name = "user-service", fallback = UserServiceHystrix.class)
  2. public interface UserService {
  3.   @GetMapping("/user/getUserById")
  4.   Result getUserById(@RequestParam("id") String id);
  5. }
复制代码
2.自定义配置类

自定义配置类时, 直接在feign的配置类上加@Configuration注解,该注解的方式是全局的,对于所有由@FeignClient注解的调用类都生效。
这样的好处在于,调用项目注册中心的其他服务时不用频繁的手动去加载配置类。该配置类也会被加载到spring cloud feign的服务调用中。
不过,比较致命的是,调用外部API时有可能会和微服务调用之间产生冲突。
Feign契约不支持SpringMVC契约,在feign契约下使用springMVC注解时,spring注解的部分功能会失效,甚至导致创建bean失败等。
(大部分java.lang.IllegalStateException: Method getAllUrl not annotated with HTTP method type (ex. GET, POST) 异常都是由于契约问题造成的。)

3.自定义配置类法2

自定义配置类时,另一种则是不使用注解对配置类加以标识,而是在@FeignClient的注解中添加配置参数,在需要调用外部API接口的feign调用类里手动加载该配置,加载方式如后文中ApiService服务所示。
使用这种方式能将项目同注册中心的服务与外部API区分开来。
但是需要每一个feign类去手动加载该配置。@FeignClient参数会在下文中讲到。

4. @FeignClient参数说明

@FeignClient用来修饰类、接口类、注解类等。它的所有参数如下:
  1. @Target({ElementType.TYPE})
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface FeignClient {
  5.   @AliasFor("name")
  6.   String value() default "";
  7.   /** @deprecated */
  8.   @Deprecated
  9.   String serviceId() default "";
  10.   String contextId() default "";
  11.   @AliasFor("value")
  12.   String name() default "";
  13.   String qualifier() default "";
  14.   String url() default "";
  15.   boolean decode404() default false;
  16.   Class<?>[] configuration() default {};
  17.   Class<?> fallback() default void.class;
  18.   Class<?> fallbackFactory() default void.class;
  19.   String path() default "";
  20.   boolean primary() default true;
  21. }
复制代码
    value:服务名,访问第三方接口时可以随便命名。支持从配置文件中获取配置。name:请求的服务名(用于微服务时,请求其他服务名的名称)。url:第三方请求地址,支持从配置文件中获取配置。fallback:失败时请求的回调类,熔断处理。configuration:手动加载feign配置类。

5. 自定义配置的简单实现

A. Feign配置类
  1. // 增加该配置时,该配置类就变成全局配置类
  2. // @Configuration
  3. public class FeignConfig implements RequestInterceptor {
  4.   @Autowired
  5.   private ObjectFactory<HttpMessageConverters> messageConverters;
  6.   @Bean
  7.   public Contract feignContract() {
  8.     // feign 契约 @RequestLine
  9.     return new Contract.Default();
  10.     // springMVC契约 @GetMapping @PostMapping 等
  11.     // return new SpringMvcContract();
  12.   }
  13.   // 记录请求和响应的头文件,正文和元数据的日志,需要在配置文件指出需要打印日志的类
  14.   @Bean
  15.   Logger.Level feignLoggerLevel() {
  16.     return Logger.Level.FULL;
  17.   }
  18.   // 连接超时时间说明:连接超时时间,单位分钟,读取超时时间,单位秒,重定向为是
  19.   @Bean
  20.   public Options options() {
  21.     return new Options(10, TimeUnit.MINUTES, 60, TimeUnit.SECONDS, true);
  22.   }
  23.   // 编码方式
  24.   @Bean
  25.   public Encoder feignFormEncoder() {
  26.     return new SpringFormEncoder(new SpringEncoder(messageConverters));
  27.   }
  28.   // (全局设置)设置请求头等业务需要参数。
  29.   @Override
  30.   public void apply(RequestTemplate template) {
  31.   }
  32. }
复制代码
B. 配置文件
使用yml文件配置。Feign默认使用URLConnection发送HTTP请求。可以通过配置文件修改他的http发送方式如:httpclient、okhttp等。可以根据自己的需求进行修改。
  1. server:
  2.   port: 8080
  3. #设置feign请求方式
  4. feign:
  5.   httpclient:
  6.     enabled: true
  7. # 打开debug请求日志 可以使用的参数有info warn error debug等
  8. logging:
  9.   level:
  10.     com.example.feign.feign.ApiService: debug
  11. # 第三方请求地址
  12. api:
  13.   url: https://api.apiopen.top
复制代码
C. 正式使用,feign无参数GET方式 请求三方接口
该部分的测试接口都是基于开源社区的测试接口。使用很久了,再次感谢一下开源社区大佬们的幸苦付出。现在有好多接口都用不了。希望大家不要恶意刷接口。
请求方式:GET
请求地址:https://api.apiopen.top/getSingleJoke
方法上使用的注解是feign契约(Contract)RequestLine。要使用Spring契约 GetMapping 等注解时,需要在FeignConfig中配置即可。
ApiService类代码如下:
  1. @FeignClient(value = "api-service", url = "${api.url}"
  2.     , fallback = ApiServiceHystrix.class, configuration = FeignConfig.class)
  3. public interface ApiService {
  4.   /**
  5.    * 平台接口预览 方法名可以随便取
  6.    */
  7.   @RequestLine("GET /getAllUrl")
  8.   List<String> getAllUrl();
  9. }
复制代码
ApiServiceHystrix类代码:
  1. public class ApiServiceHystrix implements ApiService {
  2.   @Override
  3.   public List<String> getAllUrl() {
  4.     // 设置调用失败时的降级处理
  5.     return null;
  6.   }
  7. }
复制代码
调用写好的接口,查看参数:


调用成功!Feign的基础调用很简单,如果需要调用多个相同地址的第三方请求,只需要新增方法即可,无需再增加额外的配置。
但仅仅用于单次调用时,feign比起其他HTTP请求方式又稍显麻烦,不过胜在简洁明了。

6. Feign 的其他请求方式

    Query参数
请求方式:POST
请求地址:https://api.apiopen.top/getImages
现在尝试用feign来进行Query请求。请求成功后,用于接收数据的对象可以是一个Java 对象类,也可以是JSONObject对象。当返回内容结构稳定时(成功失败所返回的数据格式相同时),Java对象才能准确接收到信息。
创建一个结果类:
  1. @Data
  2. public class ApiResult implements Serializable {
  3.   private static final long serialVersionUID = 1L;
  4.   private Integer code;
  5.   private String message;
  6.   private List result;
  7. }
复制代码
ApiService类中增加对应方法:
  1.   @RequestLine("POST /getImages?page={page}&count={count}")
  2.   ApiResult getImages(@Param("page") String page, @Param("count") String count);
复制代码
请求结果:


    POST表单
post表单请求发送时,请求参数要为Map类型的键值对。示例代码:
  1.   @RequestLine("POST /deleteFeedback")
  2.   ApiResult deleteFeedback(@RequestBody Map<String, ?> bodyMap);
复制代码
    设置Header请求头
请求头可以通过feign注解 @HeaderMap(import feign.HeaderMap;)示例代码:
  1.   @RequestLine("POST /requestHeader")
  2.   JSONObject getTcText(@HeaderMap Map<String, Object> headers, @RequestBody Map<String, Object> map);
复制代码
其他请求可移步git:open-feign
以上为个人经验,希望能给大家一个参考,也希望大家多多支持中国红客联盟。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Honkers

荣誉红客

关注
  • 4004
    主题
  • 36
    粉丝
  • 0
    关注
这家伙很懒,什么都没留下!

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行