当前位置: 首页 > news >正文

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

相关文章:

  • 求臻医学张怡然博士,肿瘤基因检测“解码之旅”的践行者
  • 酷开会员 | 酷开系统壁纸模式,感受无法言说的灵魂震颤
  • Golang之火爆原因
  • 【原创】java+swing+mysql通讯录管理系统设计与实现
  • CSS样式穿透
  • 人脸106和240点位检测解决方案
  • 力扣labuladong一刷day11拿下打家劫舍问题共3题
  • 【AI视野·今日Robot 机器人论文速览 第六十五期】Mon, 30 Oct 2023
  • 除了chatGPT网站外,国内有些可以使用的AI网站 文心一言 讯飞星火 豆包 通义千问 人工智能网站 AI网站
  • 爱上C语言:操作符详解(下)
  • 软路由R4S+iStoreOS实现公网远程桌面局域网内电脑
  • Python中神奇的「type」,即可查看类型,又可以创建对象
  • Postman:API测试之Postman使用完全指南
  • [Python学习笔记]Requests性能优化之Session
  • spark性能调优 | 内存优化
  • 深入了解以太坊
  • gf框架之分页模块(五) - 自定义分页
  • HTTP传输编码增加了传输量,只为解决这一个问题 | 实用 HTTP
  • IDEA常用插件整理
  • k8s如何管理Pod
  • Mac转Windows的拯救指南
  • Netty源码解析1-Buffer
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • python学习笔记 - ThreadLocal
  • 缓存与缓冲
  • 解析 Webpack中import、require、按需加载的执行过程
  • 扑朔迷离的属性和特性【彻底弄清】
  • 入门到放弃node系列之Hello Word篇
  • 一起来学SpringBoot | 第十篇:使用Spring Cache集成Redis
  • 因为阿里,他们成了“杭漂”
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • ​TypeScript都不会用,也敢说会前端?
  • ​二进制运算符:(与运算)、|(或运算)、~(取反运算)、^(异或运算)、位移运算符​
  • #ifdef 的技巧用法
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (12)Linux 常见的三种进程状态
  • (17)Hive ——MR任务的map与reduce个数由什么决定?
  • (4) PIVOT 和 UPIVOT 的使用
  • (6)【Python/机器学习/深度学习】Machine-Learning模型与算法应用—使用Adaboost建模及工作环境下的数据分析整理
  • (C语言)strcpy与strcpy详解,与模拟实现
  • (LeetCode) T14. Longest Common Prefix
  • (附源码)springboot教学评价 毕业设计 641310
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (十)DDRC架构组成、效率Efficiency及功能实现
  • (未解决)macOS matplotlib 中文是方框
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (一)认识微服务
  • (原創) X61用戶,小心你的上蓋!! (NB) (ThinkPad) (X61)
  • (转)socket Aio demo
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .java 指数平滑_转载:二次指数平滑法求预测值的Java代码
  • .NET 4.0中的泛型协变和反变
  • .net core 6 集成和使用 mongodb
  • .NET Core MongoDB数据仓储和工作单元模式封装