magic-api 是一款非常优秀的快速开发框架,在做大屏的过程中找到的宝贝应用,可以用类JS 语法快速开发接口,能非常方便的操作数据库及处理一些复杂的业务逻辑,而 magic-boot 是基于 magic-api 开发的一款快速开发平台,提供了基本的用户鉴权、后台管理等功能。
在实际项目过程中我基于 magic-boot 做了如下事项:
1、通过Matomo的API定时同步数据至数仓做大数据分析
2、采集coolshell.cn整站数据
3、每周五定时推送企业微信消息,提醒同事写周报
更多功能待进一步挖掘……
下面是我在项目中有用到的技术点的一个记录,会在项目过程中不断更新,便于后续有其他项目用到的话,能快速查找运用。
获取 系统设置/配置中心 模块设置的配置项
import '@/configure/getBykey' as configure;
var baseURL = configure('matomo.base-url');
var authToken = configure('matomo.auth-token');
http请求数据示例
import cn.hutool.json.JSONUtil
import org.springframework.util.StringUtils
import http;
import log;
import '@/configure/getBykey' as configure;
// 从配置中心获取接口所需数据
var baseURL = configure('matomo.base-url');
var authToken = configure('matomo.auth-token');
// 组转请求URL
var reqURL = `${baseURL}?module=API&method=${method}&format=JSON&token_auth=${authToken}`;
if (!StringUtils.isEmpty(params)) {
reqURL += `&${params}`;
}
log.info(`reqURL:${reqURL}`);
// 请求数据
var resData = http.connect(reqURL).contentType('application/json').get().getBody();
return resData;
在原基础上增加http请求出错重试机制
import cn.hutool.json.JSONUtil
import org.springframework.util.StringUtils
import cn.hutool.core.date.DateUtil
import cn.hutool.core.thread.ThreadUtil
import http
import log
import '@/configure/getBykey' as configure;
// 从配置中心获取接口所需数据
var baseURL = configure('matomo.base-url');
var authToken = configure('matomo.auth-token');
// 组转请求URL
var reqURL = `${baseURL}?module=API&method=${method}&format=JSON&token_auth=${authToken}`;
if (!StringUtils.isEmpty(params)) {
reqURL += `&${params}`;
}
// log.info(`reqURL:${reqURL}`);
var requestStartTime = DateUtil.now();
var successFlag = ''
var exceptionContent = ''
// 请求数据
var resData = ''
// 最大重试次数
var MAX_RETRY_COUNT = 5
// 当前重试次数
var retryCount = 0;
while(retryCount < MAX_RETRY_COUNT && successFlag !== 'Y') {
try {
resData = http.connect(reqURL).contentType('application/json').get().getBody();
successFlag = 'Y'
} catch(e) {
successFlag = 'N'
ThreadUtil.sleep(1000);
retryCount++
exceptionContent = e.getMessage();
}
}
var requestEndTime = DateUtil.now();
db.table('matomo_sync_log').insert({ 'apiMethod' : method, 'requestParams' : params, 'responseContent': resData.asString(), 'exceptionContent': exceptionContent, 'requestTime':requestStartTime, 'responseTime': requestEndTime, 'retryCount':retryCount, 'successFlag': successFlag});
return resData;
分页获取数据
在获取一些详情数据的时候,存在数据量超大的情况,一次性获取所有数据极有可能会导致数据库及应用挂掉,即便不挂掉的情况下,也会超长事件才会响应结果,所以采用分页获取还是很有必要的。
下面的代码是在实际项目中分页调用Matomo的接口获取输入然后将接口返回的数据,结构化处理后,保存到本地数据库。
import cn.hutool.json.JSONUtil
import log;
import '@/dmcfns/sendMatomoRequest' as getMatomoData;
var PAGE_SIZE=10 // 每页获取记录数,获取后批量入库
var currentPage = 0// 当前页
var needLoad = true // 继续加载数据标识,当当前页加载的内容小于PAGE_SIZE时则不再加载
while(needLoad) {
var resData = getMatomoData('Live.getLastVisitsDetails', `period=day&date=${date}&idSite=${siteId}&doNotFetchActions=1&filter_offset=${PAGE_SIZE * currentPage}&filter_limit=${PAGE_SIZE}`)
if (resData.asString().startsWith("[")) {
var siteDatas = JSONUtil.parseArray(resData);
var siteData = [];
for (index, site in siteDatas) {
var siteObj = siteDatas.getJSONObject(index);
var visitId = siteObj.getStr("idVisit");
var visitorId = siteObj.getStr("visitorId");
var visitIp = siteObj.getStr("visitIp");
var longitude = siteObj.getStr("longitude");
var latitude = siteObj.getStr("latitude");
var userId = siteObj.getStr("userId");
var country = siteObj.getStr("country");
var referrerName = siteObj.getStr("referrerName");
var visitProps = JSONUtil.toJsonStr(siteObj);
db.table('matomo_daily_visit').insert({
date,
siteId,
visitId,
visitorId,
visitIp,
longitude,
latitude,
userId,
country,
referrerName,
visitProps
})
}
if (siteDatas.size() === PAGE_SIZE) {
currentPage++
} else {
needLoad = false
}
}
}
使用多数据源操作数据库
db['ZR'].table('crawler_list').insert({
pageURL: linkURL,
articleTitle:linkTitle
})
根据主键更新部分字段内容
var updateMap = {
id: visitItem.id,
ipCountry: country,
ipProvince: province,
ipCity: city
}
db.table('matomo_daily_visit').primary('id').update(updateMap)
修改某个字段的值
db.table("sys_user").column("isLogin", isLogin).where().eq("id",id).update()
推送消息至企业微信机器人
import http
import log
// 测试机器人
// var ROBOT_URL = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx'
// 超算云研发部2023 微信群的eHour 机器人
var ROBOT_URL = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx'
var msg = {
"msgtype": "text",
"text": {
"content": """为便于公司开展项目成本核算相关工作,请各位同事及时登录eHour系统录入本周工作工时,如有系统使用相关问题可联系 XXX,感谢配合[抱拳][抱拳]\neHour系统链接如下:http://172.18.3.xxx/""",
"mentioned_list":["@all"]
}
}
http.connect(ROBOT_URL).body(msg).post();
log.info('eHour消息推送成功')
// 以下cron表达式为每周五16:30分执行
00 30 16 * * 05
读取Excel文件并转换为json
import cn.hutool.poi.excel.ExcelUtil
import request
import log
var datas = ExcelUtil.getReader(new ByteArrayInputStream(request.getFile('file').getBytes())).readAll()
var sourceDatas = datas::stringify::json
导出Excel
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.json.JSONUtil;
import log;
import response
import java.io.*;
var list = db['MDC'].select("select * from crawler_resource limit 10")
//通过hutool工具创建的excel的writer,默认为xls格式
ExcelWriter writer= ExcelUtil.getWriter();
var bos = new ByteArrayOutputStream();
log.info("List:\n" + JSONUtil.toJsonPrettyStr(list))
try {
//一次性写出内容,使用默认样式,强制输出标题
writer.write(list,true);
writer.flush(bos,true);
} finally {
bos.flush();
writer.close();
}
return response.download(bos.toByteArray(), "crawler_resource_list.xlsx");
数据库事务处理
db.transaction(() => {
if (archived_at == null) {
//项目取消归档
//推送取消归档的通知
db.table("project_tasks").primary("project_id").primary("archived_follow").update({
project_id: project_id,
archived_follow: 1,
archived_at: null,
archived_follow: 0,
})
} else {
//项目归档
db.table("project_tasks").primary("project_id").primary("archived_at").update({
project_id: project_id,
archived_at: null,
archived_at: archived_at,
archived_follow: 1,
})
}
db.table("projects").primary("id").update({
id: project_id,
archived_at: archived_at,
archived_userid: userid
})
})
评论 (0)