# japi-plus
**Repository Path**: zhan_pu/japi-plus
## Basic Information
- **Project Name**: japi-plus
- **Description**: 基于一款快速集成springboot,适用于java接口开的starter
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2022-06-19
- **Last Updated**: 2025-03-04
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## japi-plus
### 描述
基于java+springboot快速集成接口开发的一款starter
### 使用说明
#### 引入maven坐标
```xml
top.v5it
japi-plus-spring-boot-starter
0.0.1
```
#### application.yml 配置
```yml
spring:
japi:
# 防XSS攻击配置
xss:
enabled: true
include-rich-text: true
exclude:
includes:
- /**
interceptor:
# 配置自定义拦截器,clazz拦截器路径,order拦截器order序号,includes拦截器拦截地址,excludes排除不拦截地址
properties:
- clazz: com.xx.yy.MyInterceptor
order: 60
excludes:
- /v1/produc
- /v1/order
# http请求自定义head名称前缀
head-prefix: Example
# http请求token验证
token:
enabled: true
excludes:
- /v1/example
# 加解密算法
eada:
algorithm: AES
includes:
- /**
excludes:
- /v1/example/post
- /v1/example/get
# http请求授权认证
authorized:
diff-time: 6000
timeout: 10
type: HMAC_SHA256
# 自定义缓存key名称前缀
cache-prefix: example
timeout: 3000
# 自定义异常全限定名称路径
exception-set:
- top.v5it.japi.plus.support.limit.FrequencyLimitedException
# 参数验证配置
validator:
enabled: true
fail-fast: true
# id生成配置
idcenter:
id-type: redis
worker-id: 10
datacenter-id: 2
# http请求流量限制
limit: sliding_win
# 初始化,数据缺失情况是否抛出异常
init:
load-throw: false
ssl:
cert-filepath: /xxx/yyy.cer
private-key-filepath: /xxx/yyy.der
```
#### 启动类
```java
@EnableJdbcAuditing
@EnableJapiOperLog
@EnableJapiLimit
@EnableJapiWrapper
@EntityScan
@EnableJdbcRepositories
@SpringBootApplication
@Import({OperLogConfigurationSelector.class})
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
```
### 请求日志
> 在配置类上添加 @EnableJapiOperLog 启动操作日志记录
>
> 在 Controller 类方法上面添加 @JapiOperLog("测试") 针对单个请求记录操作日志
>
> 具体日志详情参考 top.v5it.japi.plus.log.OperLog 类
### 请求限流
> 在配置类上添加 @EnableJapiLimit 启动限流
>
> 1、在 Controller 类方法上面添加 @JapiLimit(limit = 5, time = 10) 针对单个请求10秒限制5次请求
>
> 2、或在 Controller 类方法上面添加 @JapiLimit 添加resources/limit.cnf文件,文件写入具体限流参数[limit.cnf](#限流配置)
>
> 具体限流详情参考 top.v5it.japi.plus.support.limit.JapiLimit 类
>
> 配置限流方式(count|sliding_win)
>
>```yml
> spring:
> japi:
> limit: sliding_win
> ```
#### 限流配置
```text
# 若引入“其他(统一controller)”全局配置[global],在没有具体配置按此全局限流,未引入可以不配置[global]
[global]
# controller方法请求地址,限止大小,时间,类型(GLOBAL|SIGNAL)
query/{bean},120,60,GLOBAL
orm/{bean}/{method},180,60,GLOBAL
batch/{bean}/{method},80,60,GLOBAL
[more]
query/product,600,60,GLOBAL
orm/product/add,300,60,GLOBAL
v1/person/{id},2,5,GLOBAL
```
### 统一响应
> 在配置类上添加 @EnableJapiWrapper 启动统一响应
>
> 在 Controller 类方法上面添加 @JapiEada(isDecrypt = false) 针对单个请求响应结果 resource 中敏感信息进行加密并统一响应
>
> 在 Controller 类上添加 @JapiEada(isDecrypt = false) 针对整个 Controller 中所有方法请求响应结果 resource 中敏感信息进行加密并统一响应
>
> 在 Controller 类上或者类中方法上加 @JapiEada(isEncrypt = false, isDecrypt = false) 等同于默认不加 @JapiEada 注解,只统一响应
>
>> - 响应失败示例
>> ```
>> HTTP/1.1 401 Unauthorized
>> Connection: keep-alive
>> Content-Type: application/json;charset=UTF-8
>> Content-Length: 59
>> Date: Wed, 20 Jul 2022 10:08:38 GMT
>>
>> {
>> "message": "验证签名失败",
>> "return_code": "SIGN_ERROR"
>> }
>> ```
>
>> - 响应成功示例
>> ```
>> HTTP/1.1 200 OK
>> Example-Channel: 65faf9e0803f41d0967ce9c4aa7e5563
>> Request-ID: af0b5bc8-75d0-4a8e-9c73-acd347cdf540
>> Example-Nonce: 4441145cb03549669ebc0db45f06dbcb
>> Date: Wed, 20 Jul 2022 10:21:05 GMT
>> Connection: keep-alive
>> Transfer-Encoding: chunked
>> Content-Type: application/json
>> Example-Signature: ff0733a99b5c7460e26425c6e340d54c92324b65c27d4869712d5c7c3c6dbaea
>> Example-Timestamp: 1658312465
>>
>> {
>> "id": 1,
>> "name": "zhangshan",
>> "sex": "男",
>> "birthday": "1999-12-20",
>> "resource": "uOnvViBfvkGM4Yx9Pb2QmIe6Sj/jJK0/qMxuqK5mDMkJdGJ9R8M0ar9uCmMoOCCKORX2aqbJpCY5WDe7vEiMdQ==",
>> "resourceType": "ENCRYPT"
>> }
>>
>> ```
>
> 具体加解密详情参考 top.v5it.japi.plus.core.spring.web.JapiEada 类
### 自定义拦截器
#### 实现自定义拦截器
```java
@Slf4j
public class MyInterceptor extends AbstractJapiInterceptor {
public MyInterceptor(OperLogService operLogService) {
super(operLogService);
log.info("MyInterceptor初始化成功");
}
@Override
protected void preHandle(HttpServletRequest request, HttpServletResponse response, long startTime) throws Exception {
log.info("MyInterceptor#preHandle");
}
@Override
protected void prePostHandle(HttpServletRequest request, HttpServletResponse response, Map authMap, long startTime) throws Exception {
log.info("MyInterceptor#prePostHandle");
}
}
```
#### 加载自定义拦截器
> 在工程 resources 下面添加 META-INF/services/org.springframework.web.servlet.HandlerInterceptor 文件,写入自定义拦截器的包名和类名称(com.xx.yy.MyInterceptor)
#### 配置自定义拦截器
```yml
spring:
japi:
interceptor:
# 配置自定义拦截器,clazz拦截器路径,order拦截器order序号,includes拦截器拦截地址,excludes排除不拦截地址
properties:
- clazz: com.xx.yy.MyInterceptor
order: 60
excludes:
- /v1/produc
- /v1/order
```
### 敏感信息加解密
#### 定义传输对象
```java
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class TestExampleDTO implements Serializable {
private static final long serialVersionUID = 1356075427403479014L;
private Long id;
private String name;
private String sex;
private LocalDate birthday;
private Resource resource;
/**
* 申明需要加解的密敏感信息放在Resource中
*/
@Data
public static class Resource {
/**
* 手机号
*/
private String tel;
/**
* 身份证号
*/
private String idNum;
}
}
```
#### 配置加解密算法(AES|RSA)
```yml
spring:
japi:
interceptor:
# 加解密算法
eada:
algorithm: AES
```
#### [开启统一响应](#统一响应)
### API认证
#### 配置认证
```yml
spring:
japi:
interceptor:
# http请求自定义head名称前缀
head-prefix: Example
includes:
- /**
excludes:
- /v1/example/post
- /v1/example/get
# http请求授权认证
authorized:
diff-time: 6000
timeout: 10
type: HMAC_SHA256
```
#### 认证类型
>
>> SHA256_RSA2048
>>
>> ```
>> Authorization: EXAMPLE-SHA256-RSA2048 signature=I4puMuoB3+FW/we87lBiAjLkW/aodvH0SIRCJGscsqYpV9NyRDW26nQscF3EYjgx7q7LnoLnkm28L+/pvpKMcsXgC+tz/Wf61dzuFWxSq15NuA1YHM9e+7Y3R2xdNLCJ25Kz/3/f3WcE/fRK7JS61V7KWSnopqx4KrJbvR9Nxs1t2VHrys0laFB10SJl/MUwk3TP86jd/eozEGA4ZOnBTdO756zjHQ3Gqcx8VtB0uhhKhXUQl/W5P4/f0B1sgpm/Y8EfOL7l/veAQQ695ePHR3DIyccIx85I0aK4kUDsuudbrwLocDC6ptcXW/FUJRDxzrqsNchmXeAQPFFarfqqAA==,serial_no=277758666191060001921921044729396318802466633735,timestamp=1655893653,nonce_str=fj790ijkjhoiufdu3jlf9uhdwk3jvlsnvoej,channel=0dae0b38284a4a7d9532908bc20cdab5
>> ```
>>
>> HMAC_SHA256
>>
>> ```
>> Authorization: EXAMPLE-HMAC-SHA256 signature=f049804df52eed2149b3b95ebffbc155e4080f94a67190656c33eadd78e08618,timestamp=1655882456,nonce_str=fjoej,channel=65faf9e0803f41d0967ce9c4aa7e5563
>> ```
### 统一异常处理
#### 实现自定义异常
```java
public class ExampleException extends JapiException {
public ExampleException() {
}
public ExampleException(ResultStatusTemplate resultStatusTemplate) {
super(resultStatusTemplate);
}
public ExampleException(ResultStatusTemplate resultStatusTemplate, String messageTemplate, Object... params) {
super(resultStatusTemplate, messageTemplate, params);
}
public ExampleException(ResultStatusTemplate resultStatusTemplate, Throwable cause, String messageTemplate, Object... params) {
super(resultStatusTemplate, cause, messageTemplate, params);
}
public ExampleException(ResultStatusTemplate resultStatusTemplate, Throwable cause) {
super(resultStatusTemplate, cause);
}
}
```
#### 配置异常
```yml
spring:
japi:
exception-set:
- com.xx.yy.ExampleException
```
- 响应码说明
> 常见响应码参考 top.v5it.japi.plus.core.api.ResultStatus
### 参数检验
#### 编写检验规则
```java
@NotBlank(message = "用户名称不能为空")
private String name;
```
> 常见检验规则 javax.validation.constraints 包路径下注解
#### 开启参数检验
```yml
spring:
japi:
validator:
enabled: true
fail-fast: true
```
### 唯一ID
#### 开启生成唯一ID(redis|snow)
```yml
spring:
japi:
idcenter:
id-type: snow
worker-id: 10
datacenter-id: 2
```
### 其他(统一controller)
>
> 所有http请求按照(JapiQueryController|JapiOrmController|JapiBatchController)三个controller进入处理,引入系统无需再开发controller可以更专注业务与数据处理
>
>> JapiQueryController:对应分页查询(query/{bean}),支持GET和POST方法[请求示例-分页查询](#分页查询)
>
>> JapiOrmController:对应CRUD操作(orm/{bean}/{method}),支持GET和POST方法[请求示例-CRUD操作](#CRUD操作)
>
>> JapiBatchController:对应批量操作(batch/{bean}/{method}),支持GET和POST方法[请求示例-批量操作](#批量操作)
>
> 如若拒绝某方法访问添加resources/deny.cnf文件,文件写入拒绝的某方法[deny.cnf](#拒绝请求配置)
>
#### 引入maven坐标
```xml
top.v5it
japi-plus-extra
1.0
```
#### 拒绝请求配置
```text
# 全局配置
[global]
removeAllInBatch
changeAllInBatch
removeById
remove
count
removeAll
existsById
exists
removeInBatch
searchAll
# 账户配置
[product]
searchProdut
```
#### 请求示例
##### 分页查询
```http request
### GET方法请求
GET http://localhost:7474/query/product?page=1&size=10&sort=desc&properties=createTime&name=book
Content-Type: application/x-www-form-urlencoded
Accept: application/json
### POST方法请求
GET http://localhost:7474/query/product
Content-Type: application/json
Accept: application/json
{
"page": 1,
"size": 10,
"sort": "desc",
"properties": "createTime",
"name": "book"
}
```
##### CRUD操作
```http request
### GET方法请求
GET http://localhost:7474/orm/product/add?name=book&price=5000&quantity=10&remark=apple book&year=2020
Content-Type: application/x-www-form-urlencoded
Accept: application/json
### POST方法请求
GET http://localhost:7474/orm/product/add
Content-Type: application/json
Accept: application/json
{
"price": 5000,
"quantity": 10,
"remark": "apple book",
"year": 2020,
"name": "book"
}
```
##### 批量操作
```http request
### GET方法请求,一个集合参数
POST http://localhost:7474/batch/trade/addInBatch
Content-Type: application/json
Accept: application/json
[
{
"name": "adb",
"amount": 10000
},
{
"name": "ddb",
"amount": 10000
}
]
### POST方法请求,第一个参数为集合参数,第二个参数为常量,其他参数按依次通过url传参
GET http://localhost:7474/batch/account/addInBatch?batchSize=100
Content-Type: application/json
Accept: application/json
[
{
"name": "adb",
"amount": 10000
},
{
"name": "ddb",
"amount": 10000
},
...
]
```