基于spring gateway 的静态资源缓存实现
由于子项目比较多,子项目都是通过嵌套的方式实现的。就会导致子页面加载比较慢,影响客户体验
实现思路(AI搜的--!):
1、通过spring boot缓存实现静态资源缓存
2、在gateway过滤器,对静态资源进行缓存
直接上代码:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-cache</artifactId>
</dependency>
package com.xxx.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;/*** @author Wang* 创建时间: 2023/11/15 10:19* 功能描述:静态资源缓存*/
@Slf4j
@Component
public class StaticResourceFilter implements GlobalFilter, Ordered {private static final String STATIC_RESOURCE_PATTERN = "\\.(html|css|js|png|jpg|jpeg|gif|woff2|woff)$";private final WebClient webClient;private final CacheManager cacheManager;List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());public StaticResourceFilter(WebClient webClient, CacheManager cacheManager) {this.webClient = webClient;this.cacheManager = cacheManager;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();URI uriInfo = request.getURI();String staticResourcePath = getUrl(uriInfo);if (isStaticResource(staticResourcePath) && !synchronizedList.contains(staticResourcePath)) {//Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);String cacheKey = request.getURI().toString();Cache cache = cacheManager.getCache("staticResources");// 尝试从缓存中获取静态资源Object cachedResource = cache.get(cacheKey);if (cachedResource != null) {if (cachedResource instanceof SimpleValueWrapper) {cachedResource = ((SimpleValueWrapper) cachedResource).get();}// 如果缓存中存在,直接返回缓存的资源ServerHttpResponse response = exchange.getResponse();HttpHeaders headers = response.getHeaders();String fileSuffix = staticResourcePath.replaceAll(".*(\\.[a-zA-Z0-9]+)$", "$1");// 根据文件后缀设置MIME类型switch (fileSuffix) {case ".html":headers.setContentType(MediaType.TEXT_HTML);break;case ".js":headers.set(HttpHeaders.CONTENT_TYPE, "application/javascript");break;case ".css":headers.set(HttpHeaders.CONTENT_TYPE, "text/css");break;case ".png":headers.setContentType(MediaType.IMAGE_PNG);break;case ".jpg":case ".jpeg":headers.setContentType(MediaType.IMAGE_JPEG);break;case ".woff":headers.set(HttpHeaders.CONTENT_TYPE, "application/font-woff");break;case ".woff2":headers.set(HttpHeaders.CONTENT_TYPE, "application/font-woff2");break;case ".ttf":headers.set(HttpHeaders.CONTENT_TYPE, "application/x-font-ttf");break;case ".eot":headers.set(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-fontobject");break;default:headers.setContentType(MediaType.ALL);break;}// 这里假设缓存的内容是字节数组,您可以根据实际情况进行调整DataBuffer dataBuffer = response.bufferFactory().wrap((byte[]) cachedResource);return response.writeWith(Mono.just(dataBuffer));}// 如果缓存不存在,则继续请求下游服务获取资源,并将其缓存起来return chain.filter(exchange).then(Mono.fromRunnable(() -> {getResourceFromDownstream(staticResourcePath, cacheKey, cache);}));}// 继续处理其他过滤器或请求return chain.filter(exchange);}@Overridepublic int getOrder() {return Ordered.HIGHEST_PRECEDENCE;}/*** 根据请求路径判断是否为静态资源请求** @param staticResourcePath 请求路径*/private boolean isStaticResource(String staticResourcePath) {Pattern pattern = Pattern.compile(STATIC_RESOURCE_PATTERN);Matcher matcher = pattern.matcher(staticResourcePath);return matcher.find();}/*** 请求下游服务静态资源的方法,这里只是一个示例,您需要根据实际情况实现此方法** @param cache 缓存* @param staticResourcePath URL* @param cacheKey 缓存Key*/private void getResourceFromDownstream(String staticResourcePath, String cacheKey, Cache cache) {synchronizedList.add(staticResourcePath);Mono<byte[]> mono = webClient.get().uri(staticResourcePath).retrieve().bodyToMono(byte[].class);// 处理响应数据mono.subscribe(res -> {synchronizedList.remove(staticResourcePath);cache.put(cacheKey, res);}, error -> {log.error("请求下游服务静态资源失败:{},\n错误详情:{}", staticResourcePath, error.toString());});}/*** 获取静态资源地址** @param uri uri* @return 静态资源地址*/private String getUrl(URI uri) {String path = uri.getPath();String host = uri.getHost();int port = uri.getPort();// 下游服务的地址是String downstreamUrl = String.format("http://%s:%s%s", host, port, path);return downstreamUrl;}
}
相关文章:
基于spring gateway 的静态资源缓存实现
由于子项目比较多,子项目都是通过嵌套的方式实现的。就会导致子页面加载比较慢,影响客户体验 实现思路(AI搜的--!): 1、通过spring boot缓存实现静态资源缓存 2、在gateway过滤器,对静态资源进行缓存 直接上代码&a…...
SDUT OJ《算法分析与设计》搜索算法
A - 子集和问题 Description 子集和问题的一个实例为〈S,t〉。其中,S{ x1 , x2 ,…,xn }是一个正整数的集合,c是一个正整数。子集和问题判定是否存在S的一个子集S1,使得: 。 试设计一个解子…...
【NI-DAQmx入门】校准
1.设备定期校准的理由 随着时间的推移电子器件的特性会发生自然漂移,可能会导致测量结果的不准确性。防止出现良品和差品筛选出错的情况满足行业国际标准降低设备出现故障的风险使测量结果更具备参考性 2.查找NI设备的校准间隔。 定期校准会使DAQ设备的精度保持在…...
C语言链表
head.h typedef struct Node_s{int data; //数据域struct Node_s *pNext; //指针域 } Node_t, *pNode_t;void headInsert(pNode_t *ppHead, pNode_t *ppTail, int data); void print(pNode_t pHead); void tailInsert(pNode_t *ppHead, pNode_t *ppTail, int data); void sort…...
LabVIEW进行MQTT通信及数据解析
需求:一般通过串口的方式进行数据的解析,但有时候硬件的限制,没法预留串口,那么如何通过网络的方式特别是MQTT数据的通信及解析 解决方式: 1.MQTT通信控件: 参考开源的mqtt-LabVIEW https://github.com…...
基于DOTween插件实现金币飞行到指定位置功能
文章目录 前言一、DOTween是什么?二、使用步骤1.导入DOTween插件在Unity官方插件商店找到DOTween插件导入DOTween插件启用DOTween插件 2.代码逻辑金币飞行代码控制飞行效果代码 3.物体配置1.物体上装配CoinEffect脚本2.在金币预制体上装配FlyControl脚本 三、效果展…...
python-opencv 培训课程作业
python-opencv 培训课程作业 作业一: 第一步:读取 res 下面的 flower.jpg,读取彩图,并用 opencv 展示 第二步:彩图 -> 灰度图 第三步:反转图像:最大图像灰度值减去原图像,即可得…...
【Go入门】并发
【Go入门】并发 有人把Go比作21世纪的C语言,第一是因为Go语言设计简单,第二,21世纪最重要的就是并行程序设计,而Go从语言层面就支持了并行。 goroutine goroutine是Go并行设计的核心。goroutine说到底其实就是协程,…...
Java虚拟机运行时数据区结构详解
Java虚拟机运行时数据区结构如图所示 程序计数器 程序计数器(Program Counter Register)是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。 多线程切换时,为了能恢复到正确的执行位置,每条线程…...
华为OD机试 - 转盘寿司(Java JS Python C)
目录 题目描述 输入描述 输出描述 用例 题目解析 JS算法源码 Java算法源码...
【ATTCK】MITRE Caldera-emu插件
CALDERA是一个由python语言编写的红蓝对抗工具(攻击模拟工具)。它是MITRE公司发起的一个研究项目,该工具的攻击流程是建立在ATT&CK攻击行为模型和知识库之上的,能够较真实地APT攻击行为模式。 通过CALDERA工具,安全…...
23111709[含文档+PPT+源码等]计算机毕业设计基于Spring Boot智能无人仓库管理-进销存储
文章目录 **软件开发环境及开发工具:****功能介绍:****论文截图:****数据库:****实现:****代码片段:** 编程技术交流、源码分享、模板分享、网课教程 🐧裙:776871563 软件开发环境及…...
SDUT OJ《算法分析与设计》贪心算法
A - 汽车加油问题 Description 一辆汽车加满油后可行驶n公里。旅途中有若干个加油站。设计一个有效算法,指出应在哪些加油站停靠加油,使沿途加油次数最少。并证明算法能产生一个最优解。 对于给定的n和k个加油站位置,计算最少加油次数。 I…...
金融业务系统: Service Mesh用于安全微服务集成
随着云计算的不断演进,微服务架构变得日益复杂。为了有效地管理这种复杂性,人们开始采用服务网格。在本文中,我们将解释什么是Service Mesh,为什么它对现代云架构至关重要,以及它是如何解决开发人员今天面临的一些最紧…...
Linux下快速确定目标服务器支持哪些协议和密码套件
实现原理是利用TLS协议的特点和握手过程来进行测试和解析响应来确定目标服务器支持哪些TLS协议和密码套件。 在TLS握手过程中,客户端和服务器会协商并使用相同的TLS协议版本和密码套件来进行通信。通过发送特定的握手请求并分析响应,可以确定目标服务器…...
LeetCode100122. Separate Black and White Balls
文章目录 一、题目二、题解 一、题目 There are n balls on a table, each ball has a color black or white. You are given a 0-indexed binary string s of length n, where 1 and 0 represent black and white balls, respectively. In each step, you can choose two a…...
系列二十六、idea安装javap -c
一、概述 javap -c是一个能够将.java文件反编译为.class文件的指令,例如我在idea中编写了一个Car.java文件,我想看看这个类被编译后长什么样的,就可以使用该指令进行查看。 二、配置 2.1、 Java Bytecode Decompiler File>Settings>Pl…...
nginx 如何根据IP做限流,以及 nginx 直接返回 json 格式数据
Nginx 限流配置 Nginx是如何限流的。随着业务的扩散,系统并发越来越高时,有三样利器用来保护系统,分别是缓存、降级和限流。 随着业务的扩散,系统并发越来越高时,有三样利器用来保护系统,分别是缓存、降…...
C语言链式栈
stack.h typedef struct Node_s {int data;struct Node_s *pNext; } Node_t, *pNode_t;typedef struct Stack_s {pNode_t pHead;//栈顶指针,指向了链表的第一个结点int size;//栈的元素个数 } Stack_t, *pStack_t;void init(pStack_t pStack); void push(pStack_t …...
【Go入门】 Go的http包详解
【Go入门】 Go的http包详解 前面小节介绍了Go怎么样实现了Web工作模式的一个流程,这一小节,我们将详细地解剖一下http包,看它到底是怎样实现整个过程的。 Go的http有两个核心功能:Conn、ServeMux Conn的goroutine 与我们一般编…...
专业构建现代化英雄联盟智能助手:基于LCU API的完整实战指南
专业构建现代化英雄联盟智能助手:基于LCU API的完整实战指南 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine Seraphine是一款基于英雄联盟官方LCU API开发的开源智能助手,专为英雄联盟…...
从subprocess报错聊起:我是怎么给NX盒子里的Python脚本做‘版本体检’和‘降级手术’的
从subprocess报错聊起:我是怎么给NX盒子里的Python脚本做‘版本体检’和‘降级手术’的 那天下午,当我正试图在NVIDIA Jetson NX上部署一个图像处理流水线时,终端突然抛出一行刺眼的红色错误:TypeError: __init__() got an unexpe…...
从 ODesign 到分子世界模型:AI 制药真正要学的,不是分子,而是相互作用
AI 制药这些年讲过许多故事。 一开始讲虚拟筛选,后来讲分子生成,再后来讲 AlphaFold、扩散模型、蛋白设计、抗体设计、干湿闭环。每一代故事都有自己的热闹,也有自己的贫乏。热闹在于工具越来越多,贫乏在于许多工具仍然像一排分工…...
18分钟攻陷GitHub!Nx Console投毒事件深度复盘:3800个核心仓库泄露的供应链安全警示
摘要:2026年5月20日,全球最大代码托管平台GitHub遭遇史上最严重的供应链攻击之一。黑客组织TeamPCP通过投毒VS Code扩展市场中的Nx Console v18.95.0版本,仅用18分钟、28次下载就成功渗透GitHub内部网络,窃取了包括Copilot、CodeQ…...
医用超声图像干扰伪像算法:原理、识别与抑制技术综述
引言 医用超声成像因其无创、实时、低成本等优点,已成为临床诊断不可或缺的工具。然而,超声图像质量极易受到各种物理因素和系统限制的影响,从而产生干扰伪像。这些伪像并非真实的解剖结构,而是由声波传播特性、设备硬件、操作手法等因素导致的虚假或失真的图像信息。准确…...
成本优化秘籍:如何通过模型路由(Model Routing)降低 Agent 推理成本?
成本优化秘籍:如何通过模型路由(Model Routing)降低 Agent 推理成本? 1. 引入与连接:推理成本的"隐形黑洞"与破解之道 1.1 引人入胜的开场:一个真实的成本困境 让我们从一个真实故事开始。今年早些时候,我与一家知名科技创业公司的CTO进行了一次深入交流。…...
Qwen-Agent实战:5步构建本地化智能助手,告别云端API依赖
Qwen-Agent实战:5步构建本地化智能助手,告别云端API依赖 【免费下载链接】Qwen-Agent Agent framework and applications built upon Qwen>3.0, featuring Function Calling, MCP, Code Interpreter, RAG, Chrome extension, etc. 项目地址: https:…...
iOS越狱终极指南:从A11到A17芯片的完整越狱解决方案
iOS越狱终极指南:从A11到A17芯片的完整越狱解决方案 【免费下载链接】Jailbreak iOS 26.4 - 26, 17 - 17.7.5 & iOS 18 - 18.7.3 Jailbreak Tools, Cydia/Sileo/Zebra Tweaks & Jailbreak News Updates || AI Jailbreak Finder 👇 项目地址: h…...
Frida Hook Java层还原App签名算法实战
1. 这不是“破解”,而是理解通信逻辑的必要手段你打开某物App,点击下单,网络请求瞬间发出——但抓包一看,body里全是密文,header里带着一串32位字符串,看着像MD5,但每次请求都变;用B…...
ARM SVE2 STNT1H指令:非临时存储优化技术详解
1. ARM SVE指令集与STNT1H指令概述在现代处理器架构中,向量处理技术已经成为提升计算性能的关键手段。作为ARMv9架构的重要组成部分,可扩展向量扩展(Scalable Vector Extension, SVE)指令集通过引入可变长度的向量寄存器,为高性能计算应用提供…...
