基于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 与我们一般编…...
OpenClaw多模态实践:Qwen3-14B分析截图生成操作指南
OpenClaw多模态实践:Qwen3-14B分析截图生成操作指南 1. 为什么需要截图分析自动化 上周团队来了三位新同事,我需要反复演示软件操作流程。每次截屏标注步骤后,还要手动整理成PDF发送。这种重复劳动让我开始思考:能否让AI自动识别…...
Phi-3-mini-128k-instruct处理复杂数据结构:算法题解答与优化展示
Phi-3-mini-128k-instruct处理复杂数据结构:算法题解答与优化展示 最近在尝试用一些轻量级的模型来辅助解决编程问题,特别是算法和数据结构这块。很多人觉得大模型只能写写简单的脚本,处理复杂逻辑可能不太行。正好手头有Phi-3-mini-128k-in…...
BilibiliDown:突破B站视频离线限制的高效解决方案
BilibiliDown:突破B站视频离线限制的高效解决方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bi…...
C++ 模板参数推导机制剖析
C 模板参数推导机制剖析 C的模板参数推导是泛型编程的核心机制之一,它允许编译器在调用模板函数或类时自动推断类型参数,从而减少冗余代码并提升开发效率。理解这一机制不仅能帮助开发者编写更灵活的代码,还能避免因类型推导错误导致的编译问…...
Qwen2.5-VL-7B-Instruct效果对比:vs InternVL2、LLaVA-1.6在中文场景表现
Qwen2.5-VL-7B-Instruct效果对比:vs InternVL2、LLaVA-1.6在中文场景表现 1. 多模态视觉-语言模型概述 Qwen2.5-VL-7B-Instruct是阿里云推出的新一代多模态视觉-语言模型,专为中文场景优化设计。该模型能够同时理解图像和文本输入,并生成符…...
OpenClaw故障排查:千问3.5-9B接口连接问题解决大全
OpenClaw故障排查:千问3.5-9B接口连接问题解决大全 1. 问题背景与排查思路 上周我在本地部署OpenClaw时,遇到了对接千问3.5-9B模型的连接问题。作为一个开源AI智能体框架,OpenClaw需要稳定接入大模型才能发挥自动化能力。但在实际配置过程中…...
Unity游戏翻译解决方案:多框架适配与实时翻译优化应用指南
Unity游戏翻译解决方案:多框架适配与实时翻译优化应用指南 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator Unity游戏翻译技术正成为全球化游戏开发的关键环节,XUnity.AutoTranslat…...
[Python] venv、pip、解释器到底什么关系?一篇讲清环境管理
在学习 Python 的过程中,很多开发者都会遇到这样一个“经典困惑”: 为什么我用 pip install 安装了包,但代码里却 import 失败? 为什么有多个 Python? venv 到底在干嘛?它是不是“虚拟 Python”? 如果你也有这些疑问,那么这篇文章就是为你准备的。 本文将从底层逻辑出…...
OpenClaw配置备份:千问3.5-35B-A3B-FP8环境快速迁移方案
OpenClaw配置备份:千问3.5-35B-A3B-FP8环境快速迁移方案 1. 为什么需要配置备份? 上周我的主力开发机突然硬盘故障,导致OpenClaw与千问3.5-35B-A3B-FP8的对接配置全部丢失。重新配置花了整整两天时间——从模型地址验证、飞书通道重建到技能…...
基于STM32LXXX的数字电位器(MCP4017T-103E/LT)驱动应用程序设计
一、简介:MCP4017T-103E/LT 是 Microchip 公司推出的一款 7位(128抽头)数字电位器,采用 IC 接口控制。二、主要技术特性:参数值电阻值 (R_AB)10 kΩ抽头数128 (7-bit)接口IC (支持 Standard/ Fast Mode, 从机模式)存储…...
