一、运行截图
二、实现原理
简易图,用画图随手画了一个,正规的还是推荐大家思考的时候使用PDM,接口序列图来描述实现过程。
实现步骤:
- 调用业务数据接口获取基础业务数据
- 将获取的业务数据存储为json格式文件
- 将json数据文件推送至PDA或Android设备固定目录
- 获取PDA指定目录或者android设备中产生的业务数据
- 调用业务数据接口上传json文件数据或者音视频图像资料
限制条件:
- 目前程序运用场景:离线PDA数据同步
- 目前程序内调用android设备使用adb(安卓调试桥)
- 程序运行依赖jre环境
三、配置文件及文件结构
四、核心代码实现
4.1操作程序界面
package com.jsonliu.rest;
import com.jsonliu.config.PropertiesConf;
import com.jsonliu.service.PdaOperateDao;
import com.jsonliu.service.SafeServerDao;
import com.jsonliu.service.impl.PdaOperateDaoImpl;
import com.jsonliu.service.impl.SafeServerDaoImpl;
import java.io.IOException;
import java.util.Properties;
import java.util.Scanner;
public class OperateFile {
private static Properties properties = null;
private static PropertiesConf conf=null;
private static PdaOperateDao pdaOperateDao = null;
private static SafeServerDao safeServerDao = null;
private static Scanner scanner = new Scanner(System.in);
private static String token = "";
public static void main(String[] args) throws IOException {
//加载配置文件
properties = PropertiesConf.getInstance().getProp();
conf = PropertiesConf.getInstance();
switch (properties.getProperty("env")) {
case "1"://不能与服务相连
{
//加载配置文件
if (!initPda()) return;
//选择操作菜单
menuPda();
}
break;
case "2"://与服务同一网络(不可连接PDA)
{
//登录服务获取token
if (!initSafe()) return;
//选择操作菜单
menuServer();
}
break;
case "3"://与服务同一网络(可以连接PDA)
{
//加载配置文件
if (!initPda()) return;
//登录服务获取token
if (!initSafe()) return;
//选择操作菜单
menuAll();
}
break;
default:
break;
}
}
/**
* 初始化PDA
*
* @return
*/
private static boolean initPda() {
//加载PDA文件
pdaOperateDao = new PdaOperateDaoImpl();
//判断PDA是否连接
boolean res = pdaOperateDao.connection();
if (!res) {
System.out.println("PDA连接失败");
return false;
}
return true;
}
/**
* 选择Pda操作菜单
*/
private static void menuPda() {
f:
while (true) {
System.out.println("请选择以下操作:1-导入PDA数据 2-导出PDA数据 0-退出");
String s = scanner.nextLine();
switch (s) {
case "1"://导入PDA数据
{
if (pdaOperateDao.pushFiles()) {
System.out.println("导入成功,导入目录:" + properties.getProperty("androidDir"));
}
}
break;
case "2"://导出PDA业务数据
{
if (pdaOperateDao.pullFiles()) {
System.out.println("导出成功,导出目录:" + conf.getPcSerDir());
}
}
break;
case "0"://退出
System.out.println("谢谢使用!");
break f;
default:
System.out.println("输入错误,请重新输入");
break;
}
}
}
/**
* 初始化Safe:获取token
*
* @return
*/
private static boolean initSafe() {
//加载safe服务
safeServerDao = new SafeServerDaoImpl();
//登录获取token
String tokenStr = safeServerDao.LoginSafe();
if (tokenStr == null || tokenStr.trim().equals("")) {
System.out.println("登录安全环保系统失败");
return false;
}
token = "Bearer " + tokenStr;
return true;
}
/**
* 安环服务数据同步菜单
*/
private static void menuServer() {
f:
while (true) {
System.out.println("请选择以下操作:1-导出安环系统基础数据 2-导入安环系统业务数据 0-退出");
String s = scanner.nextLine();
switch (s) {
case "1"://导出安环系统基础数据
if (safeServerDao.getSafeData(token)) {
System.out.println("导出成功,导出目录:" + conf.getPcDir());
}
break;
case "2"://导入安环系统业务数据
if (safeServerDao.setSafeData(token)) {
System.out.println("数据导入安全环保系统成功!");
}
break;
case "0"://退出
System.out.println("谢谢使用!");
break f;
default:
System.out.println("输入错误,请重新输入");
break;
}
}
}
/**
* PDA操作、安环服务数据同步菜单
*/
private static void menuAll() {
f:
while (true) {
System.out.println("请选择以下操作: 1-导入PDA数据 2-导出PDA数据 3-导出安环系统基础数据 4-导入安环系统业务数据 0-退出");
String s = scanner.nextLine();
switch (s) {
case "1"://导入PDA数据
{
if (pdaOperateDao.pushFiles()) {
System.out.println("导入成功,导入目录:" + properties.getProperty("androidDir"));
}
}
break;
case "2"://导出PDA数据
{
if (pdaOperateDao.pullFiles()) {
System.out.println("导出成功,导出目录:" + conf.getPcSerDir());
}
}
case "3"://导出安环系统基础数据
if (safeServerDao.getSafeData(token)) {
System.out.println("导出成功,导出目录:" + conf.getPcDir());
}
break;
case "4"://导入安环系统业务数据
if (safeServerDao.setSafeData(token)) {
System.out.println("数据导入安全环保系统成功!");
}
break;
case "0"://退出
System.out.println("谢谢使用!");
break f;
default:
System.out.println("输入错误,请重新输入");
break;
}
}
}
}
4.2 PDA实现类
package com.jsonliu.service.impl;
import com.jsonliu.config.PropertiesConf;
import com.jsonliu.service.PdaOperateDao;
import com.jsonliu.util.IOUtil;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* pda操作命令
*
* @Author JSONLiu
* @Date:2021-04-20
*/
public class PdaOperateDaoImpl implements PdaOperateDao {
//运行时环境
private Runtime rt = Runtime.getRuntime();
//配置文件信息
private Properties properties = PropertiesConf.getInstance().getProp();
private PropertiesConf conf = PropertiesConf.getInstance();
/**
* 解压ADB
*
* @return
*/
private boolean getAdb() {
if (new File(conf.getAdbPath() + "adb.exe").exists()) {//存在就不解压
return true;
}
//不存在
try {
Process process = rt.exec("jar -xvf operateAndroid.jar");
String msg = IOUtil.readProMsg(process);
if (msg.contains("adb.exe")) return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean connection() {
if (!getAdb()) {
return false;
}
//执行pda命令
try {
Process process = rt.exec(conf.getAdbPath() + "adb devices");
//获取连接消息
String msg = IOUtil.readProMsg(process);
String[] devices = msg.replace("List of devices attached", "").trim().split("device");
if (devices.length > 0 && !devices[0].equals("")) return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean pullFiles() {
//获取所有文件
List<String> fileNames = getAndroidFile();
if (fileNames == null || fileNames.size() == 0) {
System.out.println("目录下不存在文件");
return false;
}
//清空业务数据目录下原来的文件
IOUtil.clearDir(conf.getPcSerDir());
//拉取所有文件到本地pc
StringBuffer sb = new StringBuffer();
for (String fileName : fileNames) {
sb.append(conf.getAdbPath() + "adb pull " + properties.getProperty("androidDir") + fileName
+ " " + conf.getPcSerDir() + " && ");
}
String cmd = sb.toString();
if (cmd != "") cmd = cmd.substring(0, cmd.lastIndexOf("&&"));
//执行pda命令
try {
Process process = rt.exec(cmd);
//获取连接消息
String msg = IOUtil.readProMsg(process);
if (msg.contains("pulled")) return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
@Override
public boolean pushFiles() {
//获取本地所有文件
List<String> fileNames = getPcFile();
if (fileNames == null || fileNames.size() == 0) {
System.out.println("目录下不存在文件");
return false;
}
//推送本地所有文件到android设备
StringBuffer sb = new StringBuffer();
for (String fileName : fileNames) {
sb.append(conf.getAdbPath() + "adb push " + fileName + " " + properties.getProperty("androidDir") + " && ");
}
String cmd = sb.toString();
if (cmd != "") cmd = cmd.substring(0, cmd.lastIndexOf("&&"));
//执行pda命令
try {
Process process = rt.exec(cmd);
//获取连接消息
String msg = IOUtil.readProMsg(process);
if (msg.contains("pushed")) return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
/**
* 获取pc基础数据文件夹文件
*
* @return
*/
private List<String> getPcFile() {
List<String> list = new ArrayList<>();
File file = new File(conf.getPcDir());
if (!file.exists()) {
System.out.println("路径错误");
return null;
}
File[] files = file.listFiles();
for (File file1 : files) {
if (file1.isDirectory()) continue;
list.add(file1.getAbsolutePath());
}
return list;
}
/**
* 获取android文件夹文件
*
* @return
*/
private List<String> getAndroidFile() {
//执行pda命令
try {
Process process = rt.exec(conf.getAdbPath() + "adb shell \"cd "
+ properties.getProperty("androidDir") + " && ls\"");
//获取连接消息
return IOUtil.readLineProMsg(process);
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
4.3 业务系统交互实现类
package com.jsonliu.service.impl;
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
import com.google.gson.reflect.TypeToken;
import com.jsonliu.bean.BaseAttachment;
import com.jsonliu.bean.CheckLogVO;
import com.jsonliu.bean.Result;
import com.jsonliu.config.PropertiesConf;
import com.jsonliu.service.SafeServerDao;
import com.jsonliu.util.HttpUtil;
import com.jsonliu.util.IOUtil;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
public class SafeServerDaoImpl implements SafeServerDao {
//配置文件信息
private Properties properties = PropertiesConf.getInstance().getProp();
private PropertiesConf conf = PropertiesConf.getInstance();
@Override
public String LoginSafe() {
//获取用户名
String username = properties.getProperty("safeUser");
try {
username = URLEncoder.encode(username, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
//获取密码
String pwd = Base64.getEncoder().encodeToString(properties.getProperty("safePwd").getBytes());
pwd = pwd.replace("=", "%3D");
//登录地址
String linkUrl = properties.getProperty("safeUrl") + "/authorization-server/oauth/token";
//参数
linkUrl = linkUrl + "?grant_type=password&scope=read&password=" + pwd + "&username=" + username;
//请求登录
Result result = HttpUtil.doPost(linkUrl, null, properties.getProperty("safeAuth"));
if (result != null && result.getData() != null) {
HashMap hashMap = new Gson().fromJson(String.valueOf(result.getData()), HashMap.class);
return hashMap.get("access_token").toString();
}
return null;
}
@Override
public boolean getSafeData(String token) {
//清空基础数据目录下原来的文件
IOUtil.clearDir(conf.getPcDir());
try {
//1、危险点台账 /safe/api/proRisk/getList
writeJsonFile("/safe/api/proRisk/getList", "{}", token, properties.getProperty("proRiskName"));
//2、特种设备 /equipment/api/specialEqu/getList
writeJsonFile("/equipment/api/specialEqu/getList", "{}", token, properties.getProperty("specialEquName"));
//3、非标设备 /safe/api/proNonstandard/getList
writeJsonFile("/safe/api/proNonstandard/getList", "{}", token, properties.getProperty("proNonstandardName"));
//4、环境风险点 /envpro/api/envRiskPoint/getList
writeJsonFile("/envpro/api/envRiskPoint/getList", "{}", token, properties.getProperty("envRiskPointName"));
//5、环保治理设施 /envpro/api/envEqu/getList
writeJsonFile("/envpro/api/envEqu/getList", "{}", token, properties.getProperty("envEquName"));
//6、职业危害设施 /safe/api/heaHarmequ/getList
writeJsonFile("/safe/api/heaHarmequ/getList", "{}", token, properties.getProperty("heaHarmequName"));
//7、高能耗设备 /equipment/api/highEqu/getList
writeJsonFile("/equipment/api/highEqu/getList", "{}", token, properties.getProperty("highEquName"));
//8、供能设备 /equipment/api/supplyEqu/getList
writeJsonFile("/equipment/api/supplyEqu/getList", "{}", token, properties.getProperty("supplyEquName"));
//9、消防重点部位 /safe/api/firePosition/getList
writeJsonFile("/safe/api/firePosition/getList", "{}", token, properties.getProperty("firePositionName"));
//10、消防设备 /equipment/api/fireEqu/getList
writeJsonFile("/equipment/api/fireEqu/getList", "{}", token, properties.getProperty("fireEquName"));
//11、应急物资管理 /safe/api/emeMaterials/getList
writeJsonFile("/safe/api/emeMaterials/getList", "{}", token, properties.getProperty("emeMaterialsName"));
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean setSafeData(String token) {
String jsonStr = null;
//读取文件内容
try {
jsonStr = IOUtil.readFile(conf.getPcSerDir() + properties.getProperty("checkName"));
} catch (IOException e) {
e.printStackTrace();
}
if (jsonStr == null || jsonStr.equals("")) {
System.out.println("检查记录文件内容为空");
return false;
}
//将json字符串转为集合对象
List<CheckLogVO> list = new Gson().fromJson(jsonStr, new TypeToken<List<CheckLogVO>>() {
}.getType());
if (list == null || list.size() == 0) {
System.out.println("检查记录文件内容为空");
return false;
}
//上传文件至服务器,更新集合文件路径
//如果此处文件较多,1000+ 如何处理??
try {
upLoadFiles(list, token);
} catch (FileNotFoundException e) {
System.out.println(e.getMessage());
return false;
}
//批量保存检查记录 batchInsert
String apiUrl="/organization/api/baseCheckLog/batchAdd";
Result result = HttpUtil.doPost(properties.getProperty("safeUrl") + apiUrl,new Gson().toJson(list), token);
Object obj = getResultData(apiUrl, result);
if (obj instanceof String && obj.equals("")) {
return false;
}
return true;
}
/**
* 调取远程API,获得基础数据,写出json数据至文件中
*
* @param apiUrl api路径
* @param params 条件参数
* @param token 登录获取的token
* @param fileName 写出文件名称
* @return
* @throws IOException
*/
private boolean writeJsonFile(String apiUrl, String params, String token, String fileName) throws IOException {
//调用远程方法,获取数据
Result result = HttpUtil.doPost(properties.getProperty("safeUrl") + apiUrl, params, token);
Object obj = getResultData(apiUrl, result);
if (obj instanceof String && obj.equals("")) {
return false;
}
//将数据写入文件
IOUtil.writeFile(obj.toString(), conf.getPcDir() + fileName);
return true;
}
/**
* 上传检查附件,并更新检查记录
*
* @param checkLogList
* @param token
* @return
*/
private boolean upLoadFiles(List<CheckLogVO> checkLogList, String token) throws FileNotFoundException {
System.out.println("开始文件上传,请等待...");
String apiUrl = "/xfile/api/minio/upload";
for (CheckLogVO vo : checkLogList) {
if (vo.getAttachmentList() == null) {
continue;
}
for (BaseAttachment attachment : vo.getAttachmentList()) {
Result result = HttpUtil.doPostFile(properties.getProperty("safeUrl") + apiUrl, token,
conf.getPcSerDir() + attachment.getSfPath());
Object obj = getResultData(apiUrl, result);
if (obj instanceof String && obj.equals("")) {
continue;
}
LinkedTreeMap treeMap = (LinkedTreeMap) obj;
attachment.setSfPath(String.valueOf(treeMap.get("url")));
}
}
System.out.println("文件上传结束...");
return true;
}
/**
* 获取result返回data数据
*
* @param apiUrl api路径
* @param result result结果
* @return data字符串
*/
private Object getResultData(String apiUrl, Result result) {
if (result == null) return "";
if (result != null && result.getCode() != 200) {
System.out.println("接口:" + apiUrl + "-->>" + result.getMessage());
return "";
}
//解析result.getData()
HashMap json = new Gson().fromJson(String.valueOf(result.getData()), HashMap.class);
if (json.get("data") == null) {
System.out.println("接口:" + apiUrl + "-->>" + json.get("mesg"));
return "";
}
return json.get("data");
}
}
4.4 配置文件读取类
package com.jsonliu.config;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/**
* @Author: JSONLiu
* @Description: 获取配置类
* @Date Created in 2021-04-21 22:54
* @Modified By:
*/
public class PropertiesConf {
//Properties参数
private Properties prop = null;
//adb相关资源解压路径
private String adbPath = System.getProperty("user.dir") + "\\adb\\";
//PC基础数据目录
private String pcDir = System.getProperty("user.dir") + "\\baseDir\\";
//PC业务数据目录
private String pcSerDir = System.getProperty("user.dir") + "\\serviceDir\\";
private PropertiesConf() {
try {
//读取配置
InputStream stream = this.getClass().getClassLoader()
.getResourceAsStream("app.properties");
Properties properties = new Properties();
properties.load(stream);
prop = properties;
//创建adb目录
File file1 = new File(adbPath);
if (!file1.exists()) {
file1.mkdirs();
}
//创建PC基础数据目录
File file2 = new File(pcDir);
if (!file2.exists()) {
file2.mkdirs();
}
//创建PC基础数据目录
File file3 = new File(pcSerDir);
if (!file3.exists()) {
file3.mkdirs();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static PropertiesConf propertiesConf = new PropertiesConf();
public static PropertiesConf getInstance() {
return propertiesConf;
}
public Properties getProp() {
return prop;
}
public String getAdbPath() {
return adbPath;
}
public String getPcDir() {
return pcDir;
}
public String getPcSerDir() {
return pcSerDir;
}
}
4.5 其他工具实现类参考:
HttpUtil
IOUtil
源码下载地址: