# dilib
**Repository Path**: zyqjava/dilib
## Basic Information
- **Project Name**: dilib
- **Description**: 强大的接口访问工具,可以大幅降低后台调用接口的工作量。支持JSON、JSONP等格式接口。
- **Primary Language**: Unknown
- **License**: GPL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 27
- **Created**: 2016-07-26
- **Last Updated**: 2020-12-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# dilib 简易接口访问工具
* 当前版本:1.0.2
* 构建时间:2016.3.29
* 主页:https://git.oschina.net/loongzcx/dilib
## 项目依赖包
* cglib 3.2.0
* gson 2.6.1
* httpclient 4.5.1
* commons-logging 1.2
## API文档
### 1. package com.loong.dilib
* ApiFactory
* Api实体工厂类
* 方法:
* Object createApi(String className) 创建API实体对象
* <T> T createApi(Class<T> targetClass) 创建API实体对象
* ApiProxyFactory
* Api代理工厂类
* setCache(ApiCache cache) 添加缓存处理器
* setShowLog(Boolean showLog) 是否打印日志(默认不打印)
* createApiProxy() 创建Api代理类
### 2. package com.loong.dilib.annotation
* @ DIRequest
* 接口请求注释
* 用于 API接口类、API接口方法
* DIRequest.Method
* 请求方式类型
* GET(默认)、POST
* @ DIResponse
* 接口响应注释
* 用于 API接口类、API接口方法
* DIResponse.Type
* 响应格式化类型
* STRING - 字符串响应类型(不用使用,API接口方法直接返回String类型即可)
* JSON - JSON格响应式类型(默认)
* JSONP - JSONP格式响应类型
* ~~XML~~ - XML响应类型(暂不支持)
* @ DIHeader
* 请求头部信息注释
* 用于 API接口方法参数注释
* @ DICookie
* 请求Cookie信息注释
* 用于 API接口方法参数注释
* @ DIJson
* 请求体JSON参数注释
* 用于 API接口方法参数注释
* @ DIPath
* REST参数注释
* 用于 API接口方法参数注释
* @ DIParam
* 请求参数注释
* 用于 API接口方法参数注释
* 主要用于标明简单访问参数的参数名
* @ DICache
* 缓存配置注释
* 用于 API接口类、API接口方法
* 缓存时间单位:秒
### 3. package com.loong.dilib.exception
* DIAnnotationException
* API接口注释异常
* 如果API接口注释有问题,会直接在API创建时抛出
* DIConnectException
* 接口访问失败异常,接口访问失败时抛出
* DIFormatException
* 响应信息格式化异常,接口响应后,响应体格式化失败时抛出
### 4. package com.loong.dilib.cache
* ApiCache
* API缓存处理类接口
* AbstractApiCache
* API缓存处理抽象类
* 实现了 buildKey() 方法
* MemoryApiCache
* 简单内存缓存处理器
## 使用说明
### 简单例子:
API接口类:
```java
public interface TestApi {
@DIRequest("http://xxx/test")
public String test(@DIParam("p") int value);
@DIRequest("http://xxx/test2")
public String test2(Bean bean);
}
```
```java
public class Bean {
private String p1;
private String p2;
// get set
// ......
}
```
简单使用:
```java
TestApi api = ApiFactory.createApi(TestApi.class);
String html = api.test(1);
Bean bean = new Bean();
bean.setP1("111");
bean.setP2("222");
String htnl2 = api.test2(bean);
```
1. 调用 `api.test(1)` 相当于GET方式访问 http://xxx/test?p=1
2. 调用 `api.test2(bean)` 相当于GET方式访问 http://xxx/test2?p1=111&p2=222
Spring环境下:
```xml
```
```java
@Service
public interface Test {
@Resource
private TestApi api;
public String test() {
String html = api.test(1);
}
}
```
### 复杂点的例子:
```java
@DIRequest("http://xxx")
@DIResponse(Type.JSONP)
public interface TestApi {
@DIRequest(value = "test", method = DIRequest.Method.POST)
@DIResponse
@DICache(3600)
public Result test(
@DIHeader Map h1,
@DIHeader HBean h2,
@DIHeader("xxx") String h3,
@DICookie Map c1,
@DICookie CBean c2,
@DICookie("xxx") String c3,
@DIJson PBean p
);
@DIRequest(value = "test2", method = DIRequest.Method.POST, charset = "GBK")
@DICache(60)
public Map> test2(
@DIHeader Map h1,
@DIHeader HBean h2,
@DIHeader("xxx") String h3,
@DICookie Map c1,
@DICookie CBean c2,
@DICookie("xxx") String c3,
Map p1,
PBean p2,
@DIParam("xxx") String p3
);
@DIRequest(value = "test3/{xxx}/{x2}/{x3}", method = DIRequest.Method.POST)
public Map> test3(
@DIHeader HBean h,
@DICookie CBean c,
PBean p,
@DIPath Map path1,
@DIPath PathBean path2,
@DIPath("xxx") String path3,
);
}
```
说明:
1. @DIHeader
* 标明方法参数是请求头
* 一个方法里可以有多个
* 使用方式:
* `example(@DIHeader Map h)`
* `example(@DIHeader Bean h)`
* `example(@DIHeader("name") String h)`
2. @DICookie
* 标明方法参数是请求Cookie
* 一个方法里可以有多个
* 使用方式:
* `example(@DICookie Map c)`
* `example(@DICookie Bean c)`
* `example(@DICookie("name") int c)`
3. @DIPath
* 标明方法参数是REST参数
* 一个方法里可以有多个
* 参数会通过 `name` 替换 `@DIRequest` 中访问路径被标识 `{name}` 的值
* 多余的字段会被忽略(没有找到对应的`{name}`)
* 使用方式:
* `example(@DIPath Map p)`
* `example(@DIPath Bean p)`
* `example(@DIPath("name") String p)`
4. 访问请求参数
* 被 `@Param` 注释 或 没有被 `@DIHeader`、`@DICookie`、`@DIPath` 注释的字段,都会被认定为是请求参数
* 一份方法里可以有多个
* 使用方式:
* `example(Map p)`
* `example(Bean p)`
* `example(@Param("name") String p)`
5. @DIJson
* 一般用于复杂请求参数的传递
* 被注释的参数会转换为 Json 格式,加入到 Request Body 里面
* 只能在 POST 方式中使用
* 会自动添加头部信息 `Content-Type = application/json`
* 一个方法里只能有一个
* 使用方式:
* `example(@DIJson Map p)`
* `example(@DIJson Bean p)`
6. @DIRequest
* 用户注释请求路径及请求方式
* 接口类上的 `@DIRequest` 的 `method`、`charset` 参数无效,只有接口方法上的有效
* DIRequest.Method.GET 为默认请求方式
* 默认编码方式为 `UTF-8 `
7. @DIResponse
* 如果接口方法的返回类型为 `String`,会将 Response Body 的内容直接返回
* 可以使用在接口类及接口方法上,若接口方法上没有使用,则会取接口类上的注释,接口类上没有使用则使用默认值
* Type.JSON 是默认的处理方式
* Type.JSONP 是针对 JSonp 接口的处理
8. @DICache
* 具体说明见下方
## API实体类的创建方式
###方法一:
简单方式
```java
TestApi api = ApiFactory.createApi(TestApi.class);
TestApi2 api2 = ApiFactory.createApi(TestApi2.class);
```
###方法二:
Api代理工厂方式创建
```java
// 新建API代理工厂
ApiProxyFactory proxyFactory = new ApiProxyFactory();
// proxyFactory.setShowLog(true);
// 创建代理类
ApiProxy proxy = proxyFactory.createApiProxy();
TestApi api = proxy.createApi(TestApi.class);
TestApi2 api2 = proxy.createApi(TestApi2.class);
```
## 缓存配置
### 简单使用方式
1. 在 API方法(或者API接口类)上添加 `@DICache` 注释(时间以秒为单位)
2. 使用 API代理工厂方式创建 API实体处理类
3. 在 API代理工厂中注入缓存处理器
```java
// 缓存处理器
ApiCache apiCache = new MemoryApiCache();
// API代理工厂
ApiProxyFactory proxyFactory = new ApiProxyFactory();
proxyFactory.setCache(apiCache);
```
### 自定义缓存处理器
1. 必须实现 `ApiCache` 接口或继承 `AbstractApiCache` 抽象类
2. `ApiCache` 接口中包含三个方法:
* buildKey(Object api, Method method, Object[] params) 构建存储键
* put(Object api, Method method, String key, String html, int expire) 添加缓存
* get(Object api, Method method, String key) 获取缓存
* 参数:
* `Object api` API接口实体类
* `Mehtod method` API接口方法
* `Object[] params` 方法访问参数集
* `String key`通过 `buildKey()` 构建的缓存键
* `String html` 接口响应信息
* `int expire` 过期时间(秒)
3. `AbstractApiCache` 抽象接口已实现了 `buildKey()` 方法
4. `MemoryApiCache` 是已经写好的一个简单的缓存处理器,对于少量数据的情况可以直接使用。
备注:
1. 最好还是使用 Redis 这样的 Key-Value数据库来保存缓存
2. `AbstractApiCache` 现在的 `buildKey()` 还有待优化,主要是对于参数是Bean类型的,并且Bean里面包含Map或者Set的情况。
3. `AbstractApiCache` 中构建的缓存键已经可以区分接口类和接口方法,因此如果用继承抽象类的方式,在 `put()` 和 `get()` 中,可以直接忽略掉方法中的 `Object api` 和 `Mehtod method` 参数(当然用来分类储存也可以)。
4. ps: 其实参数 `Object api` 基本没啥用...从 `Mehtod method` 中其实可以取到接口类型的,暂时保留方便直接使用。
## 版本更新历史
* 1.0.2
* **新增缓存及缓存拓展机制**
* `@DIRequest` 注释中新增 `charset()` 编码设置
* 新增 `ApiProxyFactory` API代理工厂类
* 新增请求日志打印及打印设置
* 1.0.1
* **新增 REST 访问方式的处理**
* 废弃 `@DIN` 注释,新增 `@DIParam` 注释
* 优化对 `Map` 的处理(以前只支持`Map`)
* 1.0.0
* **基础版本**
## 新版本预期
* 增加对 XML 的支持
## 鸣谢
* 感谢 Longlive 提供了很多很好的修改建议。