通用查询类接口开发的另类思路
文章目录
- 一、需求概述
- 二、开发方式
- 1、传统开发方式
- 2、将接口视为资源文件
- 1.)springmvc工程
- 2.)springboot工程
- 3.)nginx代理
- 三、接口数据如何更新
- 1、原始数据文件生成接口数据
- 1.)定义启动类
- 2.)启动监听
- 3.)文件处理
- 4.) 完整代码
- 2、借助crontab定时执行
一、需求概述
通用查询类接口的需求,在开发过程中是比较常见的一类需求,一般具有以下的特点:
- 数据更新频率较低
- 无强制鉴权需求
- 短时间内数据内容固定
二、开发方式
1、传统开发方式
传统的开发方式,偏向于遵循MVC 模式使用@RestController注解来定义restful接口来进行后续开发。此开发模式大部分开发人员已经司空见惯,驾轻就熟不再详细阐述。
2、将接口视为资源文件
具体做法分为以下几种情况
1.)springmvc工程
springmvc工程配置文件一般为spring-mvc.xml,在此文件添加如下配置指向外部文件目录
<mvc:resources mapping="/pics/**" location="file:C:\Users\DELL\Pictures\" />
注意:需要以file:绝对文件路径 方式配置
参考项目:https://gitee.com/00fly/java-code-frame/blob/master/springmvc-dbutils/
2.)springboot工程
springboot工程一般以javaCofig代码方式定义资源文件映射
@Slf4j
@Configuration
@ConditionalOnWebApplication
public class WebMvcConfig implements WebMvcConfigurer
{....../*** 加载静态资源文件或文件映射<br>* 映射路径优先级顺序为:META-INF/resources > resources > static > public*/@Overridepublic void addResourceHandlers(final ResourceHandlerRegistry registry){try{registry.addResourceHandler("/pics/**").addResourceLocations("classpath:/data/pic/");registry.addResourceHandler("/upload/**").addResourceLocations("file:" + new File("./upload/").getCanonicalPath() + "/");}catch (IOException e){log.error(e.getMessage(), e);}}
参考项目:https://gitcode.com/00fly/springboot-hello/
示例:https://00fly.online/upload/data.json
3.)nginx代理
nginx代理更方便,只需要在nginx根目录添加文件即可
典型的nginx配置文件如下:
default.conf
server {listen 80;server_name localhost;#access_log /var/log/nginx/host.access.log main;location / {root /usr/share/nginx/html;index index.html index.htm;}
}
我们只需在目录 /usr/share/nginx/html 放入资源文件即可。
示例:http://124.71.129.204/data.json
三、接口数据如何更新
上部分我们已经解决了接口发布和访问的问题,不要忘了:通用查询类接口仍然有数据更新的需求,我们如何来解决这个需求呢?
1、原始数据文件生成接口数据
具体概括为:监听原始数据文件,当数据发生变化时,生成接口数据文件,适用于数据不定期更新,
原始数据:点击获取
1.)定义启动类
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.stream.Collectors;
import java.util.stream.Stream;import org.apache.commons.lang3.StringUtils;import lombok.extern.slf4j.Slf4j;@Slf4j
public class MainRun
{/*** 文件监听程序一直运行* * @param args* @throws IOException*/public static void main(String[] args)throws IOException{// 默认监听项目当前目录String path = new File("").getCanonicalPath();URL url = MainRun.class.getProtectionDomain().getCodeSource().getLocation();if (url.getPath().endsWith(".jar")){log.info("please start jar like: java -jar files-listener-0.0.1.jar --path=/work/test");path = Stream.of(args).filter(arg -> arg.contains("--path")).map(arg -> StringUtils.substringAfter(arg, "=")).collect(Collectors.joining());if (StringUtils.isBlank(path) || !new File(path).exists() || !new File(path).isDirectory()){log.error("please check path is a exist directory!");return;}}FileMonitor.initJsonFilesMonitor(path);}
}
2.)启动监听
import java.io.File;
import java.util.concurrent.TimeUnit;import org.apache.commons.io.filefilter.FileFilterUtils;
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
import org.apache.commons.io.monitor.FileAlterationMonitor;
import org.apache.commons.io.monitor.FileAlterationObserver;import com.fly.simple.service.JsonDataService;import lombok.extern.slf4j.Slf4j;/*** 监听文件变化*/
@Slf4j
public class FileMonitor
{/*** 初始化文件监听器*/public static void initJsonFilesMonitor(String path){try{log.info("start monitor {} ......", path);FileAlterationObserver observer = new FileAlterationObserver(path, FileFilterUtils.suffixFileFilter(".json"));File dir = new File(path);observer.addListener(new FileAlterationListenerAdaptor(){@Overridepublic void onFileCreate(File file){log.info("★★★★★★★★ {} created.", file.getName());JsonDataService.parseDir(dir);}@Overridepublic void onFileChange(File file){log.info("★★★★★★★★ {} changed.", file.getName());JsonDataService.parseDir(dir);}@Overridepublic void onFileDelete(File file){log.info("★★★★★★★★ {} deleted.", file.getName());JsonDataService.parseDir(dir);}});// 开始监听new FileAlterationMonitor(TimeUnit.SECONDS.toMillis(10), observer).start();}catch (Exception e){log.error(e.getMessage(), e.getCause());}}
}
3.)文件处理
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ResourceBundle;
import java.util.stream.Collectors;import org.apache.commons.io.FileUtils;import com.fly.simple.entity.Article;
import com.fly.simple.entity.BlogData;
import com.fly.simple.utils.JsonBeanUtils;import lombok.extern.slf4j.Slf4j;/*** JsonData服务类*/
@Slf4j
public class JsonDataService
{private static File dir = new File(ResourceBundle.getBundle("config").getString("out"));public static void parseDir(File directory){try{// 遍历目录下json文件Collection<File> files = FileUtils.listFiles(directory, new String[] {"json"}, false);List<Article> data = files.stream().map(f -> parseToArticles(f)).flatMap(List::stream).distinct().collect(Collectors.toList());FileUtils.writeStringToFile(dir, JsonBeanUtils.beanToJson(data, true), StandardCharsets.UTF_8, false);log.info("articles length : {}", data.size());}catch (IOException e){log.error(e.getMessage(), e);}}/*** 解析File为List* * @param resource* @return*/private static List<Article> parseToArticles(File file){try{String jsonData = FileUtils.readFileToString(file, StandardCharsets.UTF_8);return JsonBeanUtils.jsonToBean(jsonData, BlogData.class, true).getData().getList();}catch (IOException e){log.error(e.getMessage(), e);return Collections.emptyList();}}
}
4.) 完整代码
https://gitee.com/00fly/effict-side/tree/master/files-listener
2、借助crontab定时执行
具体概括为:按照设定时间点生成接口数据文件,适用于数据固定周期更新
files-listener项目根目录执行打包
mvn clean package -f pom-json.xml
执行后会在target文件目录生成files-listener-0.0.1.jar,将jar上传到服务器目录如:/work/files-listener-0.0.1.jar后
命令行执行
#查看定时任务
crontab -l#编辑定时任务
crontab -e
编辑时输入以下内容
0 */12 * * * java -jar /work/files-listener-0.0.1.jar
此命令实现,每12小时执行一次Jar
不再详细阐述,实现思路具体请查阅文章:服务器docker应用一览
有任何问题和建议,都可以向我提问讨论,大家一起进步,谢谢!
-over-
相关文章:
通用查询类接口开发的另类思路
文章目录 一、需求概述二、开发方式1、传统开发方式2、将接口视为资源文件1.)springmvc工程2.)springboot工程3.)nginx代理 三、接口数据如何更新1、原始数据文件生成接口数据1.)定义启动类2.)启动监听3.)文…...
uc/os-II 原理及应用(八) 系统裁减以及移植到51单片机-下
现在说明几个重要的点, OSStartHighRdy 的作用就是把任务栈复制到系统栈上面,再利用RET的时候会从系统栈上到一个地址放到PC寄存器上来实现任务运行。OSCtxSw是任务切换,把系统栈全部备份到当前任务栈映射上,然后改OSTCBCur,调用…...
职场沟通与行为
职场沟通与行为 引言 在职场上,你是否曾遇到过困惑的沟通?是否对同事的行为有过疑虑?这不仅是个别现象,而是我们这个时代工作文化中的普遍问题。许多职场的摩擦,来自沟通不畅或是行为不当。那么,如何才能…...
【tailscale 和 ssh】当服务器建立好节点,但通过客户端无法通过 ssh 连接
背景 当服务器建立好节点,一切显示正常但通过客户端无法通过 vs code 中的 ssh 连接到服务器 问题解决 因为服务器是重装过的,所以忘记在服务器上下载 ssh 了。。。安装完成并启动 SSH 服务后便可正常连接! sudo apt update sudo apt in…...
Spark 之 Aggregate
Aggregate 参考链接: https://github.com/PZXWHU/SparkSQL-Kernel-Profiling完整的聚合查询的关键字包括 group by、 cube、 grouping sets 和 rollup 4 种 。 分组语句 group by 后面可以是一个或多个分组表达式( groupingExpressions )。 聚合查询还支持 OLAP 场景下的多…...
【JSqlParser】Java使用JSqlParser解析SQL语句总结
简述 Java解析SQL语句有很多工具都可以做到,比如Mybatis、Druid、目前用来用去最全面的仍然是Jsqlparser,它是一个Github上的开源项目,JSqlParser是一个用于解析SQL语句的Java库,它可以帮助开发者分析和操作SQL语句的结构。无论是…...
Linux下的dev,sys和proc(TODO)
(TODO) 还有一个sysfs 在 Linux 系统中,/dev、/sys 和 /proc 是三个特殊的虚拟文件系统目录,它们各自有特定的用途,主要用于与设备和内核交互。以下是它们的详细区别和功能说明: 1. /dev(Devi…...
【Unity3D】利用Hinge Joint 2D组件制作绳索效果
目录 一、动态绳索 (可移动根节点) 二、静态绳索 三、利用Skinning Editor(Unity2022.3.15f1正常使用) 四、注意事项 一、动态绳索 (可移动根节点) 动态绳索 DynamicRope空物体 Anchor和whitecircle是相同位置的物体ÿ…...
Springer Nature——Applied Intelligence 投稿指南
投稿系统:Editorial Manager (Manuscript and Peer Review) : 使用Editorial Manager 投稿系统的期刊列表:期刊列表 期刊主页:Spring Nature 主页 投稿主页:Spring Nature Submit SystemSubmission Guidelines: Official Submissi…...
数据结构、数据类型、数字编码、字符编码:保姆级图文详解
文章目录 前言1、数据结构分类1.1、逻辑结构:线性与非线性1.2、物理结构:连续与分散1.3、数据结构的实现方式1.4、数据结构的选择依据 2、基本数据类型2.1、定义与分类2.2、存储形式 3、数字编码3.1、原码、反码与补码3.2、浮点数编码3.3、整数与浮点数区…...
DM适配连接kettle迁移工具(资源库+数据源配置)
适配改造介绍及说明 本次修改基于8.2.0.0版本调整,在该源码基础上进行DM的适配,已支持DM为资源库的配置以及相关数据迁移。kettle资源库是Kettle ETL工具内置的一个资源库。配置好的数据库可以直接缓存到资源库当中;创建、编辑好的转换/作业…...
WINFORM - DevExpress -> alertControl1提示信息框
第一个按钮为常规按钮, 单击触发 ButtonClick 事件. 第二个按钮有选中和未选中状态. 单击触发 ButtonDownChanged 事件。 if (e.ButtonName "alertButton2") { } 在dev用户界面中进行提示(usecontrolwinform) AlertInfo info new AlertInfo("提示",…...
STM32-串口-UART-Asynchronous
一,发送数据 #include "stdio.h" uint8_t hello[]"Hello,blocking\r\n"; HAL_UART_Transmit(&huart1,hello,sizeof(hello),500); 二,MicroLIB-printf(" hello\r\n") #include "stdio.h" #ifdef __GNUC…...
Nginx三种不同类型的虚拟主机(基于域名、IP 和端口)
🏡作者主页:点击! Nginx-从零开始的服务器之旅专栏:点击! 🐧Linux高级管理防护和群集专栏:点击! ⏰️创作时间:2025年1月15日13点14分 目录 1. 基于域名的虚拟主机 …...
Shell控监Kafka积压
1、获取Kafka消息堆积情况 vi check-kafka-lag.sh #!/bin/bashTOPIC"total_random" GROUP_ID"etl-dw" BOOTSTRAP_SERVER"node-01:9092,node-02:9092,node-03:9092"# 检查第一个参数是否为数字 if ! [[ $1 ~ ^[0-9]$ ]]; thenecho &…...
element-ui textarea备注 textarea 多行输入框
发现用这个组件,为了给用户更好的体验,要加下属性 1. 通过设置 autosize 属性可以使得文本域的高度能够根据文本内容自动进行调整,并且 autosize 还可以设定为一个对象,指定最小行数和最大行数。:autosize"{ minRows: 3, ma…...
Transformer创新模型!Transformer+BO-SVR多变量回归预测,添加气泡图、散点密度图(Matlab)
Transformer创新模型!TransformerBO-SVR多变量回归预测,添加气泡图、散点密度图(Matlab) 目录 Transformer创新模型!TransformerBO-SVR多变量回归预测,添加气泡图、散点密度图(Matlab࿰…...
大疆机场及无人机上云
最近基于大疆上云api进行二次开发,后面将按照开发步骤对其进行说明!...
用Cursor生成一个企业官网前端页面(生成腾讯、阿里官网静态页面)
用Cursor生成一个企业官网前端页面 第一版: <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><…...
Java 数组排序
目录 1.Java冒泡排序(Bubble Sort) 1.冒泡排序 2.冒泡排序的算法原理 3.冒泡排序的复杂度和性能 4.形成代码 2.Java快速排序(Quick Sort) 3.Java归并排序(Merge Sort) 4.Java选择排序(S…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
解析奥地利 XARION激光超声检测系统:无膜光学麦克风 + 无耦合剂的技术协同优势及多元应用
在工业制造领域,无损检测(NDT)的精度与效率直接影响产品质量与生产安全。奥地利 XARION开发的激光超声精密检测系统,以非接触式光学麦克风技术为核心,打破传统检测瓶颈,为半导体、航空航天、汽车制造等行业提供了高灵敏…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10+pip3.10)
第一篇:Liunx环境下搭建PaddlePaddle 3.0基础环境(Liunx Centos8.5安装Python3.10pip3.10) 一:前言二:安装编译依赖二:安装Python3.10三:安装PIP3.10四:安装Paddlepaddle基础框架4.1…...
