ToB企服应用市场:ToB评测及商务社交产业平台

标题: 【解决方案】如何使用 Http API 代替 OpenFeign 进行远程服务调用 [打印本页]

作者: 三尺非寒    时间: 2024-4-13 04:49
标题: 【解决方案】如何使用 Http API 代替 OpenFeign 进行远程服务调用
目录

前言

看到标题大家可能会有点疑惑吧:OpenFeign 不是挺好用的吗?尤其是微服务之间的远程调用,平时用的也挺习惯的,为啥要替换呢?
背景和原因是这样的:
下面将从介绍 OpenFeign、常见的 Http API 以及重点介绍 Spring 自带的 RestTemplate Http 模板这3个方面展开。
一、何为OpenFeign

OpenFeign 是 Spring Cloud 在 Feign 的基础上支持了 SpringMVC 的注解,如 @RequesMapping 等,其底层默认使用的是 URLConnection 实现。
OpenFeign 的 @FeignClient 注解可以解析 SpringMVC 的@RequestMapping 注解下的接口,并通过动态代理的方式产生实现类,实现类中做负载均衡并调用其他服务。
1.1@FeignClient注解

只要是使用 OpenFeign 那么这个注解是一定会使用到的,该注解的主要属性如下:
简单示例如下:
  1. @FeignClient(url = "https://xxx.abcdef.com", name = "SubmitTaskClient",
  2.              configuration = OpenFeignFormConfig.class, fallback = HystrixFallbackConfig.class)
  3. public interface SubmitTaskClient {
  4.     /**
  5.      * 调用远程接口实现,入参为 json 字符串
  6.      * @param paramJsonStr
  7.      * @param header
  8.      * @return
  9.      */
  10.     @PostMapping
  11.     String submitNormalTask(@RequestBody String paramJsonStr, @RequestHeader Map<String, String> header);
  12.     /**
  13.      * 调用远程接口实现,入参为 map 的表单形式
  14.      * @param map
  15.      * @return
  16.      */
  17.     @PostMapping(value = "/task/create", headers = {"content-type=application/x-www-form-urlencoded"})
  18.     String submitTransTask(Map<String, ?> map);
  19. }
复制代码
1.2注意事项

在远程服务调用一般存在两种情况:
二、常见的Http API

OpenFeign 本质上还是使用 http 请求完成服务的调用,其实使用以下的这些 Http API 经过适当的改造后,也可以达到效果。
2.1Apache

在后端领域,出现比较早而且使用仍然很广泛的 HTTP 客户端框架非 Apache HttpClien 莫属了,目前大量项目和公司仍在采用该框架。
Apache HttpClient 有着不错的性能、丰富的功能以及强大的自定义实现等特色。但是随着技术的发展和设计理念的改变,Apache HttpClient 显的有些落伍了。
个人认为其最不受欢迎的点主要在于 API 的设计过于臃肿,大量的配置需要手动声明,当见过了更多好的的 Http API 后你可能就会不太想继续用了。当然公司框架正在使用 Apache HttpClient 的情况下也无可厚非,虽然复杂点,但用还是可以用的。
引入 pom 依赖:
  1.         
  2.         <dependency>
  3.             <groupId>org.apache.httpcomponents</groupId>
  4.             <artifactId>httpclient</artifactId>
  5.             <version>4.5.13</version>
  6.         </dependency>
复制代码
POST 请求示例如下:
  1.     public String apacheHttpClientPost(String url, String params) throws Exception {
  2.         CloseableHttpClient httpclient = HttpClients.createDefault();
  3.         HttpPost httpPost = new HttpPost(url);
  4.         httpPost.setHeader("Content-Type", "application/json");
  5.         String charSet = "UTF-8";
  6.         StringEntity entity = new StringEntity(params, charSet);
  7.         httpPost.setEntity(entity);
  8.         CloseableHttpResponse response = null;
  9.         try {
  10.             response = httpclient.execute(httpPost);
  11.             StatusLine status = response.getStatusLine();
  12.             int state = status.getStatusCode();
  13.             if (state == 200) {
  14.                 HttpEntity responseEntity = response.getEntity();
  15.                 return EntityUtils.toString(responseEntity);
  16.             }
  17.         } finally {
  18.             if (response != null) {
  19.                 try {
  20.                     response.close();
  21.                 } catch (IOException e) {
  22.                     e.printStackTrace();
  23.                 }
  24.             }
  25.             try {
  26.                 httpclient.close();
  27.             } catch (IOException e) {
  28.                 e.printStackTrace();
  29.             }
  30.         }
  31.         return null;
  32.     }
复制代码
2.2Okhttp

OkHttp3 是 OkHttp 发展到版本3.0之后的名字。在 maven 中央仓库搜索 okhttp,可以看到 3.0 之后的版本统一称为 OkHttp3。
OKHttp3 是一个当前主流的网络请求的开源框架,由 Square 公司开发,目标是用于替代 HttpUrlConnection 和 Apache HttpClient。
  1.         
  2.         <dependency>
  3.             <groupId>com.squareup.okhttp3</groupId>
  4.             <artifactId>okhttp</artifactId>
  5.             <version>4.9.1</version>
  6.         </dependency>
复制代码
POST 请求示例如下:
  1.         public String okHttpPostMethod(String url,String body,  OkHttpClient okHttpClient) throws IOException {
  2.         MediaType JSON_TYPE = MediaType.parse("application/json");
  3.         Request request = new Request.Builder()
  4.                 .url(url).post(RequestBody.create(JSON_TYPE, body)).addHeader("Content-Type", "application/json")
  5.                 .build();
  6.         Response response = null;
  7.         try {
  8.             response = okHttpClient.newCall(request).execute();
  9.         } catch (Exception e) {
  10.             e.printStackTrace();
  11.         }
  12.         assert response != null;
  13.         if (response.isSuccessful()) {
  14.             return response.body() == null ? "" : response.body().string();
  15.         }
  16.         return null;
  17.     }
复制代码
对于需要单独处理 POST、GET 等请求的情况来说,OkHttp3 是很适合的。
但是对于一些通用请求,比如在一个通用方法的参数里只需要传入 Method 枚举(POST、GET 等)就可以实现对应类型的请求,Hutool 和 RestTemplate 可能更为合适。
2.3Hutool

Hutool 中的工具方法来自每个用户的精雕细琢,它涵盖了 Java 开发底层代码中的方方面面,是国内 Java 开发工具类库的集大成者,很多公司的很多项目都在用。
其中 Hutool 的 http 部分是基于 HttpUrlConnection 的 Http 客户端封装,大致发起调用的步骤:首先构建一个http请求,包括请求的地址、请求方式、请求头、请求参数等信息,然后执行请求返回一个 http 响应类,最后通过这个相应类可以获取响应的主体、是否请求成功等信息。
但遗憾的是,团队里也有比较明确的安全规定:不允许在项目中引入 Hutool 依赖包。
引入 pom 依赖:
  1.         
  2.         <dependency>
  3.             <groupId>cn.hutool</groupId>
  4.             <artifactId>hutool-all</artifactId>
  5.             <version>5.8.8</version>
  6.         </dependency>
复制代码
创建通用请求的示例如下:
  1.     public String huToolMethod(String url, HttpMethod httpMethod, RequestBody body) {
  2.         Map<String, String> headers = new HashMap<>();
  3.         headers.put(HttpHeaders.CONTENT_TYPE, "application/json;charset=utf-8");
  4.         // 创建通用请求, 可以涵盖所有常见的 HTTP 方法, 同时放入 url
  5.         HttpRequest request = HttpUtil.createRequest(Method.valueOf(httpMethod.name()), url);
  6.         // 放入请求的 header 和 body
  7.         HttpResponse response = request.addHeaders(headers).body(JSON.toJSONString(body)).execute();
  8.         return response.body();
  9.     }
复制代码
三、RestTemplate

RestTemplate 是 Spring 框架用来访问 RESTFUL 服务的客户端模板类,主要功能有:
1、发起 HTTP 请求,包括 RESTful 风格的 GET,POST,PUT,DELETE 等常见方法;
2、自动将响应结果映射为 Java 对象,不用手动解析 JSON 或 XML。
3、自定义设置请求头、消息转码、Cookie 等功能。
4、对不同的输入/输出类型提供对应的方法,如字符串、对象、多部分等。
5、同时还支持远程调用,不受同源策略限制。
引入 pom 依赖:
  1.         <dependency>
  2.             <groupId>org.springframework.boot</groupId>
  3.             <artifactId>spring-boot-starter-freemarker</artifactId>
  4.         </dependency>
复制代码
配置类:
  1. @Configuration
  2. public class RestTemplateConfig {
  3.     @Bean
  4.     public RestTemplate restTemplate(ClientHttpRequestFactory factory){
  5.         return new RestTemplate(factory);
  6.     }
  7.     @Bean
  8.     public ClientHttpRequestFactory simpleClientHttpRequestFactory(){
  9.         SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
  10.         factory.setConnectTimeout(10000);
  11.         factory.setReadTimeout(10000);
  12.         return factory;
  13.     }
  14. }
复制代码
3.1详解.execute()

.execute() 是 RestTemplate 中最常见的关于执行 HTTP 请求的方法,它允许开发人员高度定制 HTTP 请求。
先来给一段示例:
  1.     public String restTemplateExecuteMethod(String url, String token, Object body, HttpMethodName method){
  2.         HttpHeaders httpHeaders = new HttpHeaders();
  3.         // headers:HttpHeaders 类型,包括所有头信息
  4.         httpHeaders.add("Authorization", token);
  5.         httpHeaders.add("Content-Type", "application/json;charset=utf-8");
  6.         // body:请求体,可以是任何对象,也可以是 null
  7.         HttpEntity<Object> httpEntity = new HttpEntity<>(JSON.toJSONString(body), httpHeaders);
  8.         RequestCallback requestCallback = restTemplate.httpEntityCallback(httpEntity, Object.class);
  9.         ResponseExtractor<ResponseEntity<Object>> responseExtractor = restTemplate.responseEntityExtractor(Object.class);
  10.         // 发送请求,method.name() 表示传入的方法,包括 GET、POST、DELETE 等
  11.         ResponseEntity<Object> entity = restTemplate.execute(url, HttpMethod.valueOf(method.name()), requestCallback, responseExtractor);
  12.         // 直接返回 body
  13.         Assert.notNull(entity, "返回体为空!");
  14.         log.info("---返回的内容:{}---", JSON.toJSONString(entity.getBody()));
  15.         return JSON.toJSONString(entity.getBody());
  16.     }
复制代码
下面是一些对象的介绍:
四、文章小结

文章的最后,我选择了 okhttp3 和 RestTemplate 来进行 OpenFeign 的替换工作:okhttp3 处理单个 POST/GET 等请求,使用.execute() 处理通用 HTTP 请求。
那么如何使用 Http API 代替 OpenFeign 进行远程服务调用的分享到这里就结束了,如有不足和错误,还请大家指正。或者你有其它想说的,也欢迎大家在评论区交流!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4