# http-api-invoker
**Repository Path**: mirrors_gspandy/http-api-invoker
## Basic Information
- **Project Name**: http-api-invoker
- **Description**: 一个让http接口调用跟调用本地方法一样自然优雅的项目
- **Primary Language**: Unknown
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-09-24
- **Last Updated**: 2026-04-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[**English**](./README-en.md)
# HTTP接口调用框架
**让 HTTP 接口调用跟调用本地方法一样自然优雅**
将 HTTP 请求和接口绑定,然后由框架生成接口的代理类,直接调用接口的方法就会自动构建请求参数并发送请求,然后处理请求响应转换为接口方法的返回值返回(**支持泛型**)。
若与 **Spring 集成(可选)**,更能使用 @Autowired 进行自动注入接口的代理实现。
# 特色
1. 像 MyBatis 一样,只写接口,由框架提供实现
2. 轻量级,不要求依赖Spring,只使用少量注解
3. 支持上传和下载文件
4. 若使用 Spring ,则可以使用 Autowired 自动注入接口的实现
5. 完善的文档用例和单元测试
# 技术栈
* 动态代理
* 反射
* 注解
* 自动包扫描
# 快速开始
## 一、添加maven依赖
```xml
com.github.dadiyang
http-api-invoker
1.1.4
```
## 二、定义接口
假设有一个 GET 请求 `http://localhost:8080/city/allCities` 会响应:
```json
[
{
"id": 1,
"name": "beijing"
},
{
"id": 2,
"name": "shanghai"
}
]
```
我们定义一个接口来调用这个请求:
```java
@HttpApi
public interface CityService {
@HttpReq("http://localhost:8080/city/allCities")
List getAllCities();
}
```
注:这里只展示最简单的使用方法,完整功能的示例可查看[单元测试中的CityService接口](./src/test/java/com/github/dadiyang/httpinvoker/interfaces/CityService.java)
## 三、获取代理
获取代理有两种方式,一种是直接通过工厂方法获取,一种是集成Spring通过 @Autowired 注入
### HttpApiProxyFactory
通过调用 `HttpApiProxyFactory.getProxy` 方法获取,如:
```java
CityService cityService = HttpApiProxyFactory.getProxy(CityService.class);
List cities = cityService.getAllCities()
System.out.println(cities);
```
### Spring 集成
#### 配置开启 HTTP API 扫描
只需添加`@HttpApiScan`到任意一个 `@Configuration` 的类上即可:
```java
@Configuration
@HttpApiScan
public class TestApplication {
}
```
**注**:加上 @HttpApiScan 后会自动扫描这个 Configuration 类所在的包及其子包中所有带有 @HttpApi 注解的接口并生成代理类注册到Spring容器中。你也可以通过设置 `@HttpApiScan` 中的 value 值来指定要扫描的包。
#### @Autowired 注入接口代理
```java
@Autowired
private CityService cityService;
public void test() {
List cities = cityService.getAllCities();
System.out.println(cities);
}
```
**注**:因为是动态代理生成并注册到Spring容器中的,所以IDE可能会警告 "Could not autowired. no beans of type 'xxx' type found." 忽略即可。
## 四、占位符
在 `@HttpApi` 注解的 prefix 和 `@HttpReq` 注解的 url 中都支持配置和路径参数占位符
* 配置占位符:${},如 ${api.url.city}
* 路径参数占位符:{},如 {cityId}
* 保留到请求参数中的路径参数占位符:#{},如 #{cityId}
配置占位符中的配置项将会从以下几个来源中获取:
* 在 `@HttpApiScan` 中设置的 **configPaths** 对应的配置文件中
* **系统配置**,即 System.getProperty("property")
* 与Spring集成时,也会从**Spring Environment**中获取
## 五、重试策略
当调用接口失败时,可能是网络不通或者接口返回的状态码不是2xx时,我们可能需要重试几次。这种情况下,我们可以使用`@RetryPolicy`注解。这个注解可以打在类和方法上,方法上的策略优先于类上的。支持的参数如下:
* times 尝试调用次数,默认 3 次
* retryFor 当发生该异常时才重试,默认只在 IOException 时触发重试
* retryForStatus 当服务器返回的状态码为某一类型时触发,默认只要服务器返回非 20x 的状态都进行重试
* fixedBackOffPeriod 退避策略,当需要进行重试时休眠的秒数,默认不休眠
## 六、扩展
### 请求前置处理器
有些情况下,我们需要给所有的请求添加一个请求头、Cookie或者固定的参数,这时候如果我们在接口里添加这些参数会很冗余
此时,我们可以实现 RequestPreprocessor 接口,并在初始化代理工厂时使用该接口,此时所有的请求都会通过这个接口进行预处理
我们可以在框架发送请求之前对请求体做任何修改
```java
public void preprocessorTest() {
HttpApiProxyFactory factory = new HttpApiProxyFactory(request -> {
// 我们为所有的请求都加上 cookie 和 header
request.addCookie("authCookies", authKey);
request.addHeader("authHeaders", authKey);
});
CityService cityService = factory.getProxy(CityService.class);
City city = cityService.getCity(id);
}
```
### 响应处理器
接管响应结果的处理逻辑。通过实现 `ResponseProcessor` 接口并在初始化代理工厂时使用,可以拿到响应结果,并根据自己的需求对响应结果进行反序列化等操作
```java
ResponseProcessor cityResultProcessor = (response, method) -> {
ResultBean cityResultBean = JSON.parseObject(response.getBody(),
new TypeReference>() {
});
return cityResultBean.getData();
};
HttpApiProxyFactory factory = new HttpApiProxyFactory(cityResultProcessor);
CityService cityServiceWithResponseProcessor = factory.getProxy(CityService.class);
City city = cityServiceWithResponseProcessor.getCity(id);
```
# 核心注解
## @HttpApiScan
启动包扫描,类似@ComponentScan。
* value属性设定扫包的 basePackage,如果没有设置则使用被标注的类所在的包为基包
* configPaths属性指定配置文件
## @HttpApi
标注一个类是与Http接口绑定的,需要被包扫描的接口。类似Spring中的@Component注解
## @HttpReq
标注方法对应的url
## @Param
value: 指定方法参数名对应的请求参数名称
isBody: 指定是否将该参数的所有字段都做为单独的参数
这两个参数不能同时为空
## @Headers
指定方法参数为 Headers,目前只允许打在类型为 `Map` 的参数上,否则会抛出 `IllegalArgumentException`
## @Cookies
指定方法参数为 Cookies,目前只允许打在类型为 `Map` 的参数上,否则会抛出 `IllegalArgumentException`
## @Form
指定方法或类中的所有方法都为 Form 表单形式提交,即 Content-Type 为 application/x-www-form-urlencoded
## @RetryPolicy 重试策略
重试策略。可以打在类和方法上,方法上的策略优先于类上的。
* times 尝试调用次数,默认 3 次
* retryFor 当发生该异常时才重试,默认只在 IOException 时触发重试
* retryForStatus 当服务器返回的状态码为某一类型时触发,默认只要服务器返回非 20x 的状态都进行重试
* fixedBackOffPeriod 退避策略,当需要进行重试时休眠的秒数,默认不休眠