基于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;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/143968.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【贪心算法】原理思想、算法步骤,应用示例(找零问题、活动选择问、霍夫曼编码、最小生成树问题、车辆路径问题)

贪心算法是一种基于贪心策略的优化算法&#xff0c;它在每一步选择中都采取当前状态下的最优决策&#xff0c;而不考虑未来的后果。通常&#xff0c;这种算法对于解决一些最优化问题非常有效&#xff0c;尤其是那些可以通过局部最优解来达到全局最优解的问题。 1 贪心算法的基…

pg_bouncer在使用中的坑勿踩

目录 简介 环境信息 问题配置 问题配置 启动pgbouncer 链接逻辑图 测试存在问题 pgadmin4 Idea JAVA调用 ​编辑 dbeaver 建议&#xff1a; 简介 前面文章说过关于pg_bouncer的安装讲解&#xff0c;这里讲一下在使用中的坑&#xff0c;在进行配置的时候需要注意。 …

系列三、双亲委派机制

一、概述 当一个类收到了类加载的请求&#xff0c;它首先不会尝试自己去加载这个类&#xff0c;而是把这个请求委派给父类去完成&#xff0c;每一层的类加载器都是如此&#xff0c;因此所有的请求都应该传送到启动类加载器中&#xff0c;只有当父类加载器反馈自己无法完成这个…

PowerPoint技巧:如何将一张图片同时加到全部幻灯片里?

想把一张图片加到PPT每一张幻灯片的同一个位置&#xff0c;如果一张一张的添加就太耗时间了&#xff0c;一起来看看如何利用母版快速设置同时添加吧。 首先&#xff0c;打开需要编辑的PPT&#xff0c;在菜单栏依次点击【视图】→【幻灯片母版】&#xff1b; 打开母版后&#x…

vue3实现数据大屏内数据向上滚动,鼠标进入停止滚动 vue3+Vue3SeamlessScroll

1.效果图 2.npm下载依赖及main.js文件配置 npm install vue3-seamless-scroll --saveimport vue3SeamlessScroll from vue3-seamless-scroll;app.use(vue3SeamlessScroll) 3.html代码 <!-- scrollFlag为true时再渲染,vue3只要涉及到传值子页面需要加flag判断&#xff0c;否…

【BIM入门实战】Revit图元的选择方式,总有一款适合你

Revit图元的五种常见选择方式,总有一款适合你。 文章目录 一、直接单击二、加选和减选三、连续框选四、按类别选择五、全选过滤选择操作可以在三维视图、平面视图等多种视图中进行。 一、直接单击 直接单击,即可选中某一个图元,如选择一个扶手。 二、加选和减选 按住ctrl键…

python 调用HEG对MODIS数据进行批处理

HEG其实可以批处理可以看我另外一篇博文&#xff0c;不需要写代码。但是对于300以上数量的MODIS影像非常容易自动停止&#xff0c;而且越来越慢。还是打算利用python每个调用。 只提取了MODIS数据当中的IST一个波段&#xff0c;输出成tif&#xff0c;其他什么都没做。在处理前…

yum提示Another app is currently holding the yum lock; waiting for it to exit...

解决方法&#xff1a; rm -f /var/run/yum.pid 再重新运行yum 原因&#xff1a;可能是系统自动升级正在运行&#xff0c;yum在锁定状态中&#xff0c;要等待那个进程结束退出: 另一个应用程序是&#xff1a;PackageKit内存&#xff1a; 29 M RSS &#xff08;445 MB VSZ&…

vue-router配置

1、路由安装 npm install vue-router4 2、创建router目录 3、编辑文件且引入router包 4、main.js引入

Ubuntu18.04平台下Qt开发程序打包的一些问题总结

目录 前言 一、在Ubuntu18.04开发环境下打包有两种方式 1、利用linuxdeployqt软件进行打包 2、利用编写shell脚本的方式进行打包 二、详细介绍shell脚本打包的方式 1、新建一个空的文件夹 2、准备脚本copylib.sh 3、准备脚本xxxx.sh。 4、给上述两个脚本添加可执行权限…

Git目录不对,即当前文件夹不对应git仓库

报错信息是&#xff1a; fatal: not a git repository (or any of the parent directories): .git 如&#xff1a; 是当前文件夹不对应git仓库&#xff0c;一般在git clone之后&#xff0c;需要进入下一级文件夹才对应仓库。 在文件夹看&#xff0c;本层中没有.git文件夹&…

JavaScript的函数的形参与实参是怎么回事

0 写在前面 此文给小白看的&#xff0c;如果不是可以直接关闭 1 讲解 例如JavaScript中定义函数 //定义函数 function 方法名(形参){方法体-->使用形参}//使用函数 方法名字(实参)具体干了什么呢&#xff1f;此处以伪代码举例 //定义函数 function eat(A,B){A 去 B 家吃…

C_9练习题

一、单项选择题(本大题共20小题,每小题2分,共40分。在每小题给出的四个备选项中,选出一个正确的答案,并将所选项前的字母填写在答题纸的相应位置上。) C语言程序中,要使用数学库函数(例sqrt、sin等),需要在程序最前面加上包含文件的预处理命令&#xff08;)。 A. #include <…

解决STM32F429烧录程序后还需复位才能植入程序的bug

1.打开魔术棒&#xff0c;打开debug 2.打开setting 3.打开Flas Download 4.开启Reset and Run 5.点进去Pack选项页面&#xff0c;去掉enable

部署LCM(Latent Consistency Models)实现快速出图

LCM&#xff08;Latent Consistency Models&#xff09;可以通过很少的迭代次数就可以生成高清晰度的图片&#xff0c;目前只可以使用一个模型Dreamshaper_v7&#xff0c;基于SD版本Dreamshaper微调而来的。 LCM模型下载&#xff1a; https://huggingface.co/SimianLuo/LCM_D…

wpr -start generalprofile -start pool -filemode 这句命令具体是什么意思

注意事项&#xff1a; 总体而言&#xff0c;WPR 和 WPA 是强大的性能分析工具&#xff0c;通过它们&#xff0c;你可以深入了解系统运行时的性能特性&#xff0c;找出潜在问题并进行优化。 查看详细信息&#xff1a; wpr -start generalprofile -start pool -filemode 对应的结…

内存泄漏、new、delete

1. 内存泄漏 内存泄漏&#xff1a;指针被销毁&#xff0c;指针指向的空间依旧存在 2. new过程 与内存分配、构造函数有关 1&#xff09;分配空间&#xff1a;void* mem operator new( sizeof( ) )&#xff0c;内部调用malloc 2&#xff09;static_cast<目标类型>(mem) …

快速删除MySQL服务 。

以管理员身份执行终端&#xff0c;输入&#xff1a;sc delete MYSQL&#xff08;这个名字按着自己的来&#xff0c;可能是MYSQL8或者MYSQL5.7&#xff0c;有些时还不需要名字是一样的话&#xff0c;你要看服务名字是什么&#xff09;&#xff0c;就可以把服务中的MYSQL删除了 …

centos 6.10 安装 svn1.14.2

安装 apr 和 apr-util 下载地址 我下载的分别是 apr-1.7.4 和 apr-unit-1.6.3 常规的安装步骤 ./configure --prefix/usr/local/xxx make && make install注意要先安装 apr 再安装 apr-unit-1.6.3 安装 lz4 下载地址 要配置好环境变量&#xff0c;不然可能还是找…

.Net(C#)常用转换byte转uint32、byte转float等

1、byte转String Encoding.ASCII.GetString(byte[]); 2、base64string转byte byte[]Base64Decoder.Decoder.GetDecoded(string); 3、byte转UInt16 方法一 (UInt16)(bytes[0] * 256 bytes[1]) 方法二 (UInt16)((bytes[0] << 8) | bytes[1]); 方法三 字节序要对…