# jc-send
**Repository Path**: pjhpeter/jc-send
## Basic Information
- **Project Name**: jc-send
- **Description**: 在线数据传输接口
- **Primary Language**: Unknown
- **License**: Not specified
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-05-08
- **Last Updated**: 2020-12-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 前言
这个接口是基于jeesite的,不懂jeesite的就不要往下看了,先劝退一波
设计场景是这样的,一个中心端,多个单位端,还可以有一些特殊端,比如像军工项目有个叫服务窗口端的,单位端和特殊端可以向中心端发送数据。如果中心端的数据要到单位端或特殊端,是由单位端或特殊端来从中心端拉取数据,总之中心端永远不会主动向单位端和特殊端推送数据的,因为他最牛的┗|`O′|┛ 嗷~~
# 1.导包
```xml
com.jeesite
jc-send
${project.parent.version}
```
# 2.建表
```sql
-- 记录数据传输的碎片文件信息,用于断点续传
CREATE TABLE trans_temp_file (
id VARCHAR(64) PRIMARY KEY,
bus_type varchar(100),-- 业务类型,用于记录这次数据传输是哪个业务,随意定义
path VARCHAR(100),-- 临时碎片文件存放绝对路径
file_name VARCHAR(100),-- 拆分前的文件名
pice_file_name VARCHAR(100),-- 临时碎片文件名
point BIGINT-- 文件写入起始偏移量
);
-- 有可被拉取数据的标识
CREATE TABLE trans_pull_data_flag(
id VARCHAR(64) PRIMARY KEY,
app_uri VARCHAR(50),-- 应用唯一标识
bus_type VARCHAR(100),-- 业务类型
rows_json_str longtext-- 待拉取的数据
);
```
也可以在jc-send.jar里面找到tables.sql执行
# 3.参数设置
在系统管理的参数设置里面配置两个参数:
## send.url
发送数据接收放的地址,如192.168.6.1:8080/sbos
## appUri
该系统的唯一标识,随便一个字符串,但是不能跟其他系统重复,这个参数除了在参数配置外,还需要在中心端和单位端的单位信息表添加这个字段,单位端要报给中心端保存好。如果是特殊端的话,在中心端的参数配置里面也要添加配置特殊段的appUri,参数名随便起,找得到就行
# 4.写代码
## 报送的话
### a.在entity那里加注解
```java
@SendTable(to="sbos_unit_secpost_check_haha")//当这边的表名和那边的表名不同的时候添加这个注解,如果一样就不用了
@Table(name="sbos_unit_secpost_check", alias="a", columns={
@Column(name="id", attrName="id", label="id", isPK=true),
@Column(name="unit_code", attrName="unitCode", label="单位id", comment="单位id(unit)"),
@Column(name="year", attrName="year", label="年份", comment="年份"),
@Column(name="writing_date", attrName="writingDate", label="填报日期", comment="填报日期(申请日期)"),
@Column(name="confirm_date", attrName="confirmDate", label="确认日期"),
@Column(name="writing_user", attrName="writingUser", label="填报人",queryType=QueryType.LIKE),
@Column(name="is_sure", attrName="isSure", label="确认状态", comment="确认状态(0未报送,1审核中,2已通过 3不通过 )"),
@Column(name="nopass_reason", attrName="nopassReason", label="不通过的理由")
},joinTable={
@JoinTable(type=Type.LEFT_JOIN, entity=Unit.class, alias="b",
on="b.unit_code = a.unit_code",
columns={
@Column(name="unit_name", label="区域名称"),
@Column(name="unit_cellphone", label="联系电话")
}),
}, extColumnKeys="extColumn",orderBy="a.year DESC"
)
public class UnitSecpostCheck extends DataEntity {
private static final long serialVersionUID = 1L;
@SendField(isPK = true)//在要报送的成员变量上面添加这个注解,主键的话要加上isPK参数,支持联合主键,如果没有一个变量有isPK,默认把id作为主键
private String unitCode;
@SendField(isPK = true)
private Date writingDate;
@SendField(isPK = true)
private Date confirmDate;
@SendField(to = "current_user")//当接收端和推送端对应的数据库字段命名不一致时可以加上这个to
private String writingUser;
@SendField
private Integer isSure;
private String nopassReason;
private Integer year;
private Unit unit;
private String secPostCount;
}
```
### b.写报送的代码
```java
List list = secbookService.findList(new SbosMemberSecbook());
// 基本参数
TransEntity transEntity = new TransEntity<>();
transEntity.setList(list);
transEntity.setEntityType(SbosMemberSecbook.class);
transEntity.setBusType("SbosMemberSecbook");
// 有额外要传输的文件,比如自己生成的通知书等,可以这样加
List extraFileList = ListUtils.newArrayList();
extraFileList.add(new ExtraFile("temp", "11-27疫苗全称追溯平台方案(1).pdf"));
extraFileList.add(new ExtraFile("temp", "20180105金立手机官网设设计提案.pdf"));
extraFileList.add(new ExtraFile("temp", "20180727福特STA数字化平台-视觉风格提案.pdf"));
transEntity.setExtraFileList(extraFileList);
// 如果有额外传输的数据就加这个,任意格式的字符串,但是接口只负责传过去,并不会自动解析,需要触发器解析
transEntity.setExtraStr("{\"msg\" : \"哈哈\"}");
// 如果报送完数据之后,需要在接收端执行一些业务代码的话可以这样,当然前提是接收端那边有一个叫TestTrigger(这个名字随便起的,不要到时满大街的TestTrigger哟(°ー°〃))的触发器哦,不然就搞笑咧^_^
transEntity.setTriggerName("testTrigger");//这里给的是触发器的spring容器里的id,注解注入的话一般默认类名首字母小写
// 接收端处理接到的数据之前也可以做一些业务操作,原理跟上面的触发器一样,给一个预处理触发器的名字就可以啦
transEntity.setPreTriggerName("testPreTrigger");//这里给的是触发器的spring容器里的id,注解注入的话一般默认类名首字母小写
if(transmissionService.clientHasRenewal(busType)) {// 判断是否可以断点续传
transEntity.setRenewal(true);
}
// 调用报送接口
Result result = transmissionService.clientSend(transEntity);
System.out.println(result);
```
触发器TestTrigger的写法

```java
@Component
public class TestTrigger implements ReceiveTrigger {
/**
* rows 报送过来的所有数据
* busType 业务类型
*/
@Override
public void run(JSONArray rows, String busType) {
System.out.println("这里是业务代码,哈哈哈");
System.out.println(rows);
System.out.println(busType);
}
}
```
报送就这样写完
-----------------------------------------------------------我是华丽的分割线------------------------------------------------------------------------
## 推送的话
### a.推送端的entity添加注解
```java
@PushTable(to = "sbos_unit_secpost_determine_book_haha") // 当这边的表名和那边的表名不同的时候添加这个注解,如果一样就不用了
@Table(name = "sbos_unit_secpost_determine_book", alias = "a", columns = { @Column(name = "id", attrName = "id", label = "id", isPK = true),
@Column(name = "unit_secpost_check_id", attrName = "unitSecpostCheckId", label = "岗位审核表id"), @Column(name = "unit_secpost_item_id", attrName = "unitSecpostItemId", label = "涉密岗位备案id"),
@Column(name = "unit_code", attrName = "unitCode", label = "单位编号"), @Column(name = "year", attrName = "year", label = "年份"),
@Column(name = "designation", attrName = "designation", label = "文号"), @Column(name = "post_sure_date", attrName = "postSureDate", label = "涉密岗位确定时间"),
@Column(name = "post_surebook_url", attrName = "postSurebookUrl", label = "电子版涉密岗位确认书路径"), @Column(name = "template_content", attrName = "templateContent", label = "模板内容"), }, joinTable = {
@JoinTable(type = Type.LEFT_JOIN, entity = Unit.class, alias = "b", on = "b.unit_code = a.unit_code", columns = { @Column(includeEntity = Unit.class) }), }, orderBy = "a.id DESC")
public class UnitSecpostDetermineBook extends DataEntity {
private static final long serialVersionUID = 1L;
@PushField(isPK = true)//在要推送的成员变量上面添加这个注解,主键的话要加上isPK参数,支持联合主键,如果没有一个变量有isPK,默认把id作为主键
private String unitSecpostCheckId;
@PushField(isPK = true)
private String unitSecpostItemId;
@PushField
private Integer year;
@PushField(to = "unit_id")//当接收端和推送端对应的数据库字段命名不一致时可以加上这个to
private String unitCode;
@PushField
private String designation;
@PushField
private Date postSureDate;
@PushField
private String postSurebookUrl;
@PushField
private String templateContent;
private Unit unit;
}
```
### b.推送端写推送代码
```java
UnitSecpostDetermineBook unitSecpostDetermineBook = new UnitSecpostDetermineBook("1164508036276912128");
UnitSecpostDetermineBook unitSecpostDetermineBook2 = unitSecpostDetermineBookService.get(unitSecpostDetermineBook);
//基本参数
TransEntity transEntity = new TransEntity<>();
transEntity.setBusType("UnitSecpostDetermineBook");
transEntity.setEntity(unitSecpostDetermineBook2);
transEntity.setEntityType(UnitSecpostDetermineBook.class);
//有额外要传输的文件,比如自己生成的通知书等,可以这样加
ExtraFile extraFile = new ExtraFile("template", "中化广东有限公司涉密岗位确认书.docx");//这里第一个参数是额外文件存放的目录,例子中的意思是指向/userfiles/template
List extralFileList = ListUtils.newArrayList();
extralFileList.add(extraFile);
transEntity.setExtraFileList(extralFileList);
//推送数据,这时数据还没有真正到达接收方,只是临时存放在待拉取的区域
Result result = transmissionService.serverPush("test_unit", transEntity);
System.out.println(result);
```
### c.接收端写拉取代码
```java
//一句话,第一个参数是busType,要跟推送端的保持一致,第二个参数就是拉取成功后要在推送端执行触发器,原理跟报送一样哦
//这一句话最好写在controller那里,不然可能会造成事物冲突!!!这一句话最好写在controller那里,不然可能会造成事物冲突!!!这一句话最好写在controller那里,不然可能会造成事物冲突!!!
Result result = transmissionService.clientPull("UnitSecpostDetermineBook", "testTrigger");
System.out.println(result.toString());//我不是一句话
```
拉取就这么写完了耶^_^
----------------------------------------------------------朕是威严的分割线------------------------------------------------------------
# 还有离线的喔
由于我懒得测试,所以不一定稳定,所以说明也写的很偷懒 ≡ω≡
## 导出
```java
//这是导出后的压缩包文件名,不传默认会用busType做文件名
String exportFileName = "某某某单位报送的数据";
//这里会下载文件哦
transmissionService.export(transEntity, exportFileName, request, response);
```
## 导入
```
//第一个参数是页面上传的文件MultipartFile,第二个是业务类型busType
transmissionService.importData(file, "SbosMemberSecbook");
```
--------------------------------------------------------我是谁?我在哪?在干嘛?-------------------------------------------------------
# 还可以批量传输呢
## 在线的
```java
// 添加要批处理对象
transmissionService.addSendBatch(transEntity1);
transmissionService.addSendBatch(transEntity2);
boolean renewal = false;
//transFlag是传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
//url是接收方的地址,如192.168.6.1:8080/sbos,如果为空默认读取参数配的send.url的值,其他应该都懂啦,我就不说了
if (transmissionService.clientHasRenewal(transFlag)) {// 看看有没有断点续传
renewal = true;
}
Result result = transmissionService.clientSendBatch(transFlag, renewal, null, "testTrigger", "testPreTrigger");// 批量传输的触发器只有在这里写才有用哦哦哦
System.out.println(result);
```
## 离线的
导出
```
// 添加要批处理对象
transmissionService.addSendBatch(transEntity1);
transmissionService.addSendBatch(transEntity2);
//transFlag是传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
//exportFileName是导出后的压缩包文件名,不传默认会用busType做文件名
//这里会下载文件哦
transmissionService.exportBatch(transFlag, exportFileName, request, response);
```
导入
```java
//transFlag是传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
transmissionService.importDataBatch(file, transFlag);
```
## 推送的
```java
// 添加要批处理对象
transmissionService.addPushBatch(transEntity1);
transmissionService.addPushBatch(transEntity2);
//transFlag是传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
Result result = transmissionService.serverPushBatch(appUri, transFlag);
System.out.println(result);
```
# API说明
最好看一下吧,不然很多东西不知道哦 ( ̄_, ̄ )
## TransEntity
```java
/**
* 传输接口参数实体 参数说明:
*
* @list 需要传输的对象集合,传输多个对象时使用(不能与entity并用)
*
* @entity 需要传输的单个对象,传输单个对象时使用(不能与list并用)
*
* @entityType 需要传输的对象的实体类型
*
* @url 传输接收方的地址,如:192.168.1.1:8080/temp
*
* @busType 业务类型,该传输业务的唯一标识,自己定义
*
* @toTableName 接收方数据库表名,针对同一业务传输向多个接收方,而且各自的表名都不一样的情况,这个参数的值不为空时会覆盖@Table、@SendTable和@PushTable的配置
*
* @renewal 是否断点续传,默认false
*
* @requireSysColumn 是否需要传输系统的5个字段(status,create_date.....),默认false
*
* @requireSysColumnArr 如果系统的5个字段只传输其中一部分的话,在这里设置,如只用了create_date和update_date,{create_date,update_date}
*
* @requireTreeColumn 是否需要传输系统的树结构字段,继承TreeEntity才有的,默认false
*
* @requireAttachment 是否需要传输业务附件,默认true
*
* @extraFileList 额外要传输的文件列表,有需要额外传输的文件,这些文件不存在于附件中,比如跳过系统上传组件自动生成的文件,需要传如此参数
*
* @extraFile 单个额外要传输的文件,有需要额外传输的文件,这些文件不存在于附件中,比如跳过系统上传组件自动生成的文件,需要传如此参数
*
* @extraStr 需要外传输的信息,随便任何格式的字符串,但是自动解析并不会处理这个字符串,需要在接收端用触发器处理
*
* @triggerName 触发器注入名称,一般为类名首字母小写后的字符串,用于数据传输完成后,在接收端需要执行的一些业务逻辑,触发器类需要在接收端写好,实现ReceiveTrigger接口
*
* @preTriggerName 预处理触发器注入名称,一般为类名首字母小写后的字符串,用于处理接收到的数据前,在接收端需要执行的一些业务逻辑,触发器类需要在接收端写好,实现PreReceiveTrigger接口
*
* @author 彭嘉辉
*
*/
public class TransEntity> implements Serializable {}
```
## TransmissionService
```java
/**
* 数据传输接口
*
* @author 彭嘉辉
*
*/
public interface TransmissionService {
/**
* 数据传输
*
* @param transEntity 传输接口参数对象
* @return 结果
*/
> Result clientSend(TransEntity transEntity);
/**
* 添加发送数据到批处理列表中,准备发送传输,在线发送和离线发送都用这个接口做批量处理
*
* @param transEntity 传输接口参数对象
* @throws Exception
*/
> void addSendBatch(TransEntity transEntity) throws Exception;
/**
* 添加推送数据到批量处理列表中,准备批量推送
*
* @param transEntity
* @throws Exception
*/
> void addPushBatch(TransEntity transEntity) throws Exception;
/**
* 执行批量传输
*
* @param transFlag 传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
* @param renewal 是否断点续传
* @param url 接收方的地址,如192.168.6.1:8080/sbos,如果为空默认读取参数配的send.url的值
* @param triggerName 触发器注入名称,一般为类名首字母小写后的字符串,用于数据传输完成后,在接收端需要执行的一些业务逻辑,触发器类需要在接收端写好,实现ReceiveTrigger接口
* @param preTriggerName 预处理触发器注入名称,一般为类名首字母小写后的字符串,用于处理接收到的数据前,在接收端需要执行的一些业务逻辑,触发器类需要在接收端写好,实现PreReceiveTrigger接口
* @return 结果
*/
Result clientSendBatch(String transFlag, boolean renewal, String url, String triggerName, String preTriggerName);
/**
* 检测当前业务类型是否存在可断点续传的数据
*
* @param busType 业务类型
* @return 是否
*/
boolean clientHasRenewal(String busType);
/**
* 检测有无可拉取的数据
*
* @param busType 业务类型
* @return 有无
*/
boolean clientHasPullData(String busType);
/**
* 向服务器拉取数据
*
* @param busType 应用类型
* @param triggerName 拉取数据成功后要执行的触发器注入名称
* @return 结果
*/
Result clientPull(String busType, String triggerName);
/**
* 离线导出数据
*
* @param transEntity 传输参数对象
* @param exportFileName 导出的文件名,如果空的话会以传入的业务类型作为文件名
* @param request 请求对象
* @param response 响应对象
*/
> void export(TransEntity transEntity, String exportFileName, HttpServletRequest request, HttpServletResponse response);
/**
* 导出批量传输数据
*
* @param transFlag 传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
* @param exportFileName 导出的文件名,如果空的话会以传入的transFlag作为文件名
* @param request 请求对象
* @param response 响应对象
*/
void exportBatch(String transFlag, String exportFileName, HttpServletRequest request, HttpServletResponse response);
/**
* 导入离线传输数据
*
* @param file 上传的文件
* @param busType 业务类型,要与导出端保持一直
* @param triggerName 触发器名称
* @param preTriggerName 预处理触发器名称
* @return 结果
*/
Result importData(MultipartFile file, String busType, String triggerName, String preTriggerName);
/**
* 导入批量传输数据
*
* @param file 上传的文件
* @param transFlag 传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
* @param triggerName 触发器名称
* @param preTriggerName 预处理触发器
* @return 结果
*/
Result importDataBatch(MultipartFile file, String transFlag, String triggerName, String preTriggerName);
/**
* 推送数据
*
* @param appUri 接收方应用唯一标识
* @param transEntity 传输接口参数对象
* @return 结果
*/
> Result serverPush(String appUri, TransEntity transEntity);
/**
* 批量推送
*
* @param appUri 接收方应用唯一标识
* @param transFlag 传输业务的标识,用于标记一组批量传输的操作,作用类似于busType
* @return 结果
*/
Result serverPushBatch(String appUri, String transFlag);
}
```
##### 觉得这个接口还可以的小伙伴点手关注啊,有兴趣了解的小伙伴就把代码check下来看一下吧
[还写了一个很难发现的文档,所以在这里给个友情链接](http://192.168.6.2/svn/jeesite/jc-modules/jc-send/blob/master/%E7%9C%9F%E2%80%A2readme.md)
ヾ( ̄▽ ̄)Bye~Bye~