目录

引言

一、UniHttp与HttpApiProcessor简介

1、生命周期钩子的重要性

2、公共参数填充的需求

3、生命周期钩子相关介绍

二、HttpApiProcessor的实际应用

1、在Yml中定义相关参数

2、自定义HttpAPI注解 

3、对接接口的定义

4、HttpApiProcessor的具体实现

5、实际调用

三、结语


引言

        在当今的软件开发领域,网络请求几乎是每一个应用程序不可或缺的一部分。无论是获取远程服务器的数据,还是向服务器发送请求以更新信息,高效且灵活地处理HTTP请求对于提升应用性能和用户体验至关重要。UniHttp作为一个强大的HTTP客户端框架,提供了丰富的功能来简化网络请求的处理。其中,HttpApiProcessor及其生命周期钩子是UniHttp框架中的一大亮点,它们为开发者提供了在请求发送前后以及响应处理等关键时机进行干预的能力。

        本文将以百度天气接口为例,深入介绍HttpApiProcessor的生命周期钩子以及如何利用这些钩子来填充公共参数,帮助开发者更好地理解和运用UniHttp框架,以实现更加高效和灵活的网络请求处理。

一、UniHttp与HttpApiProcessor简介

        UniHttp是一个基于Java的HTTP客户端框架,旨在为开发者提供简单易用、功能强大的HTTP请求处理能力。它支持同步和异步请求,能够自动处理JSON、XML等数据的序列化与反序列化,并且可以轻松集成到各种Java应用中,如Spring Boot、Spring Cloud等微服务架构中。HttpApiProcessor是UniHttp中的一个核心组件,它负责处理HTTP请求的整个生命周期,包括请求的构建、发送、响应的接收以及结果的解析等。通过使用HttpApiProcessor,开发者可以更加专注于业务逻辑的实现,而不必过多地关注底层的网络通信细节。

1、生命周期钩子的重要性

        在HTTP请求的处理过程中,往往需要在不同的阶段执行一些特定的操作。例如,在请求发送前,可能需要添加一些公共的请求头,如API密钥、用户代理等;在请求发送后,可能需要对响应进行一些预处理,如检查响应状态码、解析响应数据等。如果每个请求都手动编写这些逻辑,不仅代码冗余,而且难以维护。而生命周期钩子提供了一种优雅的解决方案,允许开发者在请求处理的不同阶段插入自定义的逻辑,从而实现代码的复用和逻辑的集中管理。通过合理利用生命周期钩子,可以大大提高开发效率,降低代码的复杂度,并且使得整个网络请求的处理流程更加清晰和可控。

2、公共参数填充的需求

        在调用许多第三方API时,通常需要传递一些公共参数,这些参数对于每个请求都是必需的。以百度天气接口为例,可能需要传递API密钥、城市代码等参数。如果每个请求方法中都手动添加这些参数,不仅繁琐,而且容易出错。因此,将这些公共参数的填充逻辑集中管理显得尤为重要。通过HttpApiProcessor的生命周期钩子,可以在请求发送前自动填充这些公共参数,确保每个请求都包含必要的信息,从而简化请求方法的编写,提高代码的可维护性。

3、生命周期钩子相关介绍

        HttpApiProcessor表示是一个发送和响应和反序列化一个Http请求接口的各种生命周期钩子,开发者可以在里面自定义编写各种对接逻辑。 支持配置到 @HttpApi注解 或者 具体的@HttpInterface注解上, 在调用时就会拿到这个对象去执行自定义的钩子(这个对象如果Spring容器存在则从容器拿,如果不存在则会手动new一个请确保有无参构造)。目前提供了8种钩子,执行顺序流程如下:

postBeforeHttpRequest                (请求发送前)在发送请求之前,对Http请求进行二次处理|VpostBeforeSendHttpRequest              (请求发送前) 请求真正发送前回调|VpostSendingHttpRequest                (请求发送时)在同步Http请求发送时回调处理 |VpostAfterHttpResponse               (请求之后)发送请求后,不管成功还是失败都会回调此方法|VpostAfterHttpResponseBodyString          (请求响应后)对响应body文本字符串进行后置处理|VpostAfterHttpResponseBodyStringDeserialize  (请求响应后) 对响应body字符串自定义反序列化后置处理|VpostAfterHttpResponseBodyResult           (请求响应后)对响应body反序列化后的结果进行后置处理|VpostAfterMethodReturnValue                (请求响应后)对代理的方法的返回值进行后置处理,类似aop的后置处理

1、postBeforeHttpRequest: 可在发送http请求之前对请求体进行二次处理,比如加签之类

2、postBeforeSendHttpRequest: 可在真正发送请求前进行回调处理,比如修改请求信息、执行自定义逻辑

3、postSendHttpRequest:  同步Http请求发送时会回调该方法,可以在该方法执行自定义的发送逻辑, 注意如果是异步请求不会回调此方法。

4、postAfterHttpResponse: 发送请求后,不管成功还是失败都会回调此方法, 如果失败会返回异常信息,没有异常信息则为成功. 建议在此处打印请求的日志、耗时、和执行情况

5、postAfterHttpResponseBodyString: Http请求响应后,对响应body字符串进行进行后置处理,比如如果是加密数据可以进行解密,修改返回的json结构,移除无用字段。

6、postAfterHttpResponseBodyStringDeserialize: 对响应body字符串进行反序列化, 默认框架自动处理, 也可覆盖实现自定义逻辑

7、postAfterHttpResponseBodyResult: Http请求响应后,对响应body反序列化后的对象进行后置处理,比如填充默认值之类

8、postAfterMethodReturnValue: Http请求响应后,对代理的方法的返回值进行后置处理,类似aop的后置处理

方法参数介绍:

  • UniHttpRequest: 表示此次Http请求的请求体,包含请求url,请求头、请求方式、请求cookie、请求体、请求参数等等。
  • UniHttpResponse: 表示此次Http请求的响应信息
  • HttpApiMethodInvocation: 继承自MethodInvocation, 表示被代理的方法调用上下文,可以拿到被代理的类,被代理的方法,被代理的HttpAPI注解、HttpInterface注解等信息

         以上信息是来源于UniHttp官方网站的相关信息介绍,想了解更详细的信息的可以自行去搜索相关信息。

二、HttpApiProcessor的实际应用

        百度天气接口是一个提供天气信息查询服务的API,开发者可以通过调用该接口获取指定城市的天气情况。在使用该接口时,需要传递一些公共参数,如API密钥、城市代码等。通过UniHttp的HttpApiProcessor及其生命周期钩子,可以方便地实现这些公共参数的填充。例如,在请求发送前,可以通过beforeRequest钩子自动将API密钥和城市代码添加到请求参数中;在响应接收后,可以通过afterResponse钩子对返回的天气数据进行解析和封装,使其更易于在应用中使用。这种集中管理公共参数的方式,不仅使得代码更加简洁,而且当API密钥或城市代码发生变化时,只需在钩子逻辑中进行修改,无需在每个请求方法中逐一更新,大大提高了代码的可维护性和灵活性。接下来我们跟着UniHttp的官方文档来进行逐一的学习,仿照着改造成符合我们的实现。

1、在Yml中定义相关参数

        在这里,我们将百度的对接地址和公共的ak进行单独的设置,在常规的SpringBoot项目中,一般都会有yml文件,因为我们在yml中定义相关的配置信息,比如需要代理的url地址和公共的可以,当然,你也可以根据实际的需求来进行调整,增加一些符合自己业务需要的字段。这里只定义令人url和ak信息。关键代码如下:

#unihttp对接接口配置  
channel:baidu:#天气查询接口weather:# 请求域名url: https://api.map.baidu.com/weather/v1# 分配的akak: ak_value

2、自定义HttpAPI注解 

        这里我们需要创建一个注解对象,假设叫@BaiduHttpApi吧,然后需要在该注解上标记@HttpApi注解,并且需要配置processor字段,需要去自定义实现一个HttpApiProcessor这个具体实现后续讲。 有了这个注解后就可以自定义该注解与对接渠道方相关的各种字段配置,当然也可以不定义。 注意这里url的字段是使用 @AliasFor(annotation = HttpApi.class), 这样构建的UniHttpRequest中会默认解析填充要请求体,不标记则也可自行处理。关键代码如下:

package com.yelang.project.thridinterface;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import com.burukeyou.uniapi.http.annotation.HttpApi;
@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@HttpApi(processor = BaiduHttpApiProcessor.class)
public @interface BaiduHttpApi {/*** -渠道方域名地址*/@AliasFor(annotation = HttpApi.class)String url() default "${channel.baidu.weather.url}";/*** -申请分配的ak*/String ak() default "${channel.baidu.weather.ak}";
}

        这里请注意在注解类中,url其实也是httpApi类的一个属性,源代码的设置如下:

@Inherited
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface HttpApi {/*** Configure global HTTP request URL*      Support taking values from environmental variables, such as ${xx.url}*/String url() default "";
}

         在前面的注解类定义中,我们已经设置了一个BaiduHttpApiProcessor,为了让代码编译通过,因此先来创建一个空的类,里面可以没有任何实现方法,关键代码如下:

package com.yelang.project.thridinterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import com.burukeyou.uniapi.http.core.channel.HttpApiMethodInvocation;
import com.burukeyou.uniapi.http.core.channel.HttpSender;
import com.burukeyou.uniapi.http.core.request.UniHttpRequest;
import com.burukeyou.uniapi.http.core.response.UniHttpResponse;
import com.burukeyou.uniapi.http.extension.processor.HttpApiProcessor;
@Component
public class BaiduHttpApiProcessor implements HttpApiProcessor<BaiduHttpApi>{
}

        关于这个Processor的具体实现在后续的介绍中会说明。

3、对接接口的定义

        接下来对对接的接口的进行定义,由于我们期望使用公共参数的方式来定义对接接口以及设置对应的公共参数,因此与之前的定义方式不一样的是,在设置了公共配置之后,对于url和ak不用在每个接口中进行统一传递,如果有不一样的,请大家按照管网的要求进行调整。下面是我演示的简单对接j接口:

package com.yelang.project.thridinterface;
import com.burukeyou.uniapi.http.annotation.param.QueryPar;
import com.burukeyou.uniapi.http.annotation.request.GetHttpInterface;
import com.burukeyou.uniapi.http.core.response.HttpResponse;
@BaiduHttpApi()
public interface BaiduWeatherApiServcie {@GetHttpInterface("/")public HttpResponse<String> getWeather(@QueryPar("district_id") String district_id,@QueryPar("data_type") String data_type);
}

        在这里需要注意的是,在接口的声明处,配置的注解要替换成前面定义过的。 

4、HttpApiProcessor的具体实现

        本节重点描述BaiduHttpApiProcessor的具体实现,与常规的接口实现一样,使用java语言进行调用。这里我们只涉及三个简单的狗子钩子函数,其它的暂时用不上暂且用不上。

@Component
public class BaiduHttpApiProcessor implements HttpApiProcessor<BaiduHttpApi>{/***  渠道方分配的key,可以直接配置读取*/@Value("${channel.baidu.weather.ak}")private String ak;@Autowiredprivate Environment environment;/** 实现-postBeforeHttpMetadata: 发送Http请求之前会回调该方法,可对Http请求体的内容进行二次处理** @param uniHttpRequest              原来的请求体* @param methodInvocation          被代理的方法* @return                          新的请求体*/@Overridepublic UniHttpRequest postBeforeHttpRequest(UniHttpRequest uniHttpRequest,HttpApiMethodInvocation<BaiduHttpApi> methodInvocation) {// 获取BaiduHttpApi注解BaiduHttpApi apiAnnotation = methodInvocation.getProxyApiAnnotation();System.out.println(apiAnnotation.url());System.out.println(apiAnnotation.ak());// 获取BaiduHttpApi注解的appId,由于该appId是环境变量所以我们从environment中解析取出来String akVar = apiAnnotation.ak();System.out.println("打印相关参数:");akVar = environment.resolvePlaceholders(akVar);System.out.println("从环境对象中获取akVar===>" + akVar);System.out.println("本类中的注解获取AK===>" + ak);System.out.println("系统获取url: " + environment.resolvePlaceholders(apiAnnotation.url()));// 添加到查询参数中,必须要添加,可以从uniHttpRequest.putQueryParam("ak",akVar);return uniHttpRequest;}@Overridepublic void postBeforeSendHttpRequest(UniHttpRequest uniHttpRequest, HttpSender httpSender,HttpApiMethodInvocation<BaiduHttpApi> methodInvocation) {HttpApiProcessor.super.postBeforeSendHttpRequest(uniHttpRequest, httpSender, methodInvocation);}@Overridepublic UniHttpResponse postSendingHttpRequest(HttpSender httpSender, UniHttpRequest uniHttpRequest,HttpApiMethodInvocation<BaiduHttpApi> methodInvocation) {return HttpApiProcessor.super.postSendingHttpRequest(httpSender, uniHttpRequest, methodInvocation);}/***  实现-postAfterHttpResponseBodyResult: 反序列化后Http响应体的内容后回调,可对该结果进行二次处理返回* @param bodyResult                     Http响应体反序列化后的结果* @param rsp                            原始Http响应对象* @param methodInvocation               被代理的方法* @return*/@Overridepublic Object postAfterHttpResponseBodyResult(Object bodyResult, UniHttpResponse rsp,HttpApiMethodInvocation<BaiduHttpApi> methodInvocation) {System.out.println("bodyResult===>"+bodyResult);System.out.println("在这里可以做一些时候的处理,比如格式化和解析等,做成插件似的......");System.out.println("rsp===>" + rsp);/*if (bodyResult instanceof BaseRsp){BaseRsp baseRsp = (BaseRsp) bodyResult;// 设置baseRsp.setCode(999);}*/return bodyResult;}
}

        这里主要就是在发送请求前设置公共参数,在接口响应后对返回值进行序列化等转换。通过这样的实例基本就符合了我们数据处理要求。上面我们分别重写了postBeforeHttpRequest、postSendHttpRequest、postAfterHttpResponseBodyResult三个生命周期的钩子方法去完成我们的需求。

5、实际调用

        最后基于自来定义的ApiProcessor对象来进行相应的处理,最后我们使用main函数来模拟程序的调用,调用代码和实现逻辑如下:

package com.yelang.project.unihttp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.burukeyou.uniapi.http.core.response.HttpResponse;
import com.yelang.project.thridinterface.BaiduWeatherApiServcie;
@SpringBootTest
@RunWith(SpringRunner.class)
public class UniHttpProcessorCase {@Autowiredprivate BaiduWeatherApiServcie baiduWeatherApiService;@Testpublic void getWeather4Baidu() {String district_id = "431226";//表示String data_type = "all";HttpResponse<String> result  = baiduWeatherApiService.getWeather(district_id, data_type);System.out.println(result.getBodyResult());}
}

        在Eclipse中运行上述程序后就可以看到有以下的数据:

        可以在控制台中看到相应的接口返回,说明集成成功。通过这个例子可以看到,通过统一设置能极大的简化。

三、结语

        通过本文的介绍,读者可以深入了解UniHttp中HttpApiProcessor的生命周期钩子以及如何利用这些钩子来填充公共参数。以百度天气接口为例,展示了生命周期钩子在实际开发中的应用场景和优势。掌握这些知识,将有助于开发者更加高效地使用UniHttp框架,提升网络请求处理的灵活性和可维护性,从而构建出更加健壮和易于扩展的应用程序。行文仓促,难免有许多不足之处,如有不足,在此恳请各位专家博主在评论区不吝留言指出,不胜感激。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90865.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90865.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/90865.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

pytorch深度学习—RNN-循环神经网络

结合生活实例&#xff0c;先简单认识一下什么是循环神经网络先想个问题&#xff1a;为什么需要 “循环”&#xff1f;你平时看句子、听语音、看视频&#xff0c;都是 “按顺序” 来的吧&#xff1f;比如 “我吃苹果” 和 “苹果吃我”&#xff0c;字一样但顺序不同&#xff0c;…

深度学习常见名词解释、评价指标

目录 一、鲁棒性(robustness) 二、泛化能力&#xff08;Generalization Ability&#xff09; 核心含义&#xff1a; 如何衡量泛化能力&#xff1f; 三、先验信息&#xff08;Prior Information&#xff09; 四、mIoU &#xff08;Mean Intersection over Union&#xff0…

docker-compose安装常用中间件

分为3大部分&#xff1a;数据库&#xff1a;mysql&#xff0c;redis&#xff0c;mongodb&#xff0c;elasticsearch&#xff0c;neo4j&#xff0c;minio&#xff0c;influxdb&#xff0c;canal-server应用中间件&#xff1a;nacos&#xff0c;apollo&#xff0c;zookeeper&…

基于无人机 RTK 和 yolov8 的目标定位算法

目录 背景 算法思路 代码实现 验证 背景 在城市交通巡检中如何进行车辆违停判断很重要&#xff0c;一个方法是通过精确坐标判断车辆中心是否位于违停框中&#xff0c;我们假设无人机坐标已知&#xff0c;并且无人机云台镜头垂直地面朝下&#xff0c;可根据图像分辨率、无人机参…

go入门 - day1 - 环境搭建

0. 介绍 go语言可以做什么&#xff1f; a. 区块链 b. 分布式/微服务/云原生 c. 服务器/游戏软件go的优势 a. 代码量比C和Java少 b. 编译速度比Java或者C快上5到6倍&#xff0c;比Scale块10被 c. 性能比C慢20%&#xff0c;但是比Java、python等快上5到10倍 d. 内存管理和C媲美&a…

【华为OD】MVP争夺战(C++、Java、Python)

文章目录题目描述输入描述输出描述示例解题思路算法思路核心步骤代码实现C实现Java实现Python实现算法要点复杂度分析解题总结题目描述 在星球争霸篮球赛对抗赛中&#xff0c;最大的宇宙战队希望每个人都能拿到MVP&#xff0c;MVP的条件是单场最高分得分获得者。可以并列所以宇…

Datawhale 2025 AI夏令营 MCP Server Task2

魔搭MCP &Agent赛事&#xff08;MCP Server开发&#xff09;/夏令营&#xff1a;动手开发MCP Server学习链接&#xff1a;魔搭MCP &Agent赛事&#xff08;MCP Server开发&#xff09; - Datawhale Task1回顾 1.task1应用功能 luner_info每日黄历 这是一个可以获取某天…

敏捷开发方法全景解析

核心理念:敏捷开发是以快速响应变化为核心的项目管理方法论,通过迭代式交付、自组织团队和持续反馈,实现高质量软件的高效交付。其本质是拥抱变化优于遵循计划,强调"可工作的软件高于详尽的文档"。 一、敏捷核心思想体系 #mermaid-svg-y7iyWsQGVWn3IpEi {font-fa…

Socket到底是什么(简单来说)

简单来说&#xff1a; Socket 抽象了网络通信的复杂底层细节&#xff0c;让应用程序开发者可以专注于发送和接收数据&#xff0c;而不用去操心数据在网络上是如何传输的。 它就像一个“黑盒子”&#xff0c;你只需要把数据扔进去&#xff0c;或者从里面取数据&#xff0c;至于数…

linux系统mysql性能优化

1、系统最大打开文件描述符数查看限制 ulimit -n更改配置 # 第一步 sudo vim /etc/security/limits.conf* soft nofile 1048576 * hard nofile 1048576# 第二步 sudo vim /etc/sysctl.conffs.file-max 1048576# 第三步&#xff08;重启系统&#xff09; sudo reboot验证生效 u…

免费的需要尝试claude code的API安利,截至今天可用(7月13号)

安装方法放最后&#xff08;很简单&#xff0c;但是你得搞定网络&#xff09; 注册如下&#xff1a; 链接如下&#xff08;有详细说明&#xff09;&#xff1a; &#x1f680; AnyRouter&#xff5c;Claude Code 免费共享平台 安装&#xff08;windows用户特殊点&#xff0…

Java 属性配置文件读取方法详解

Java 属性配置文件读取方法详解 一、配置文件基础概念 1. 配置文件类型对比类型格式优点缺点适用场景Propertieskeyvalue简单易读&#xff0c;Java原生支持不支持层级结构简单配置&#xff0c;JDBC参数XML标签层级结构结构化强&#xff0c;支持复杂数据类型冗余&#xff0c;解析…

NW728NW733美光固态闪存NW745NW746

美光NW系列固态闪存深度解析&#xff1a;NW728、NW733、NW745与NW746的全方位评测技术架构与核心创新美光NW系列固态闪存&#xff08;包括NW728、NW733、NW745、NW746&#xff09;的技术根基源于其先进的G9 NAND架构。该架构通过5纳米制程工艺和多层3D堆叠技术&#xff0c;在单…

【面试八股文】2025最新软件测试面试

一、测试基础 1、测试策略或测试包括哪些&#xff0c;测试要覆盖哪些方面 UI、功能、性能、可靠性、易用性、兼容性、安全性、安装卸载 2、设计测试用例的办法 等价类、边界值、错误推测法、场景法等设计方法来编写测试用例的 &#xff08;1&#xff09;等价类分为有效等价…

AI软件出海SEO教程

一、出海SEO核心思路 本地化&#xff1a;内容、技术、用户体验全面适应目标市场。关键词策略&#xff1a;围绕目标用户的真实搜索习惯做关键词挖掘和布局。内容为王&#xff1a;持续输出高质量、解决用户痛点的内容。技术优化&#xff1a;保证网站速度、结构、移动端体验及安全…

PyVision:基于动态工具的具身智能体

论文地址&#xff1a; [2507.07998v1] PyVision: Agentic Vision with Dynamic Tooling 1. 背景 现有的智能体一般都是通过大模型规划调用已经预定义好的一些工具&#xff08;具体来说也就是一些函数&#xff09;来解决问题。这样就会导致在针对特征的任务上Agent去解决问题…

Higress 上架 KubeSphere Marketplace,助力企业构建云原生流量入口

随着企业数字化转型持续深化&#xff0c;云原生架构正逐渐成为构建现代应用的主流选择。而服务治理作为云原生落地的核心能力之一&#xff0c;急需更灵活、高效的解决方案。近日&#xff0c;AI 原生的 API 网关 Higress 正式上架 KubeSphere Marketplace&#xff0c;助力用户轻…

在LC480T上部署xapp1052

实验环境&#xff1a;LC480T加速卡 开发环境&#xff1a;windows11vivado2020 运行环境&#xff1a;ubuntu22.04 硬件电路&#xff1a;LC480T加速卡(xc7k480tffg1156-2) vivado工程文件下载&#xff1a;https://download.csdn.net/download/xiaolangyangyang/91349686 驱动及应…

TCP的socket编程

TCP客户端逻辑void Usage(const std::string & process) {std::cout << "Usage: " << process << " server_ip server_port" <<std::endl; } // ./tcp_client serverip serverport int main(int argc, char * argv[]) {if (ar…

【理念●体系】模板规范篇:打造可标准化复用的 AI 项目骨架

【理念●体系】从零打造 Windows WSL Docker Anaconda PyCharm 的 AI 全链路开发体系-CSDN博客 【理念●体系】Windows AI 开发环境搭建实录&#xff1a;六层架构的逐步实现与路径治理指南-CSDN博客 【理念●体系】路径治理篇&#xff1a;打造可控、可迁移、可复现的 AI 开…