• 基于spring gateway 的静态资源缓存实现


    由于子项目比较多,子项目都是通过嵌套的方式实现的。就会导致子页面加载比较慢,影响客户体验

    实现思路(AI搜的--!):

    1、通过spring boot缓存实现静态资源缓存

    2、在gateway过滤器,对静态资源进行缓存

    直接上代码:

    1. <dependency>
    2. <groupId>org.springframework.bootgroupId>
    3. <artifactId>spring-boot-starter-cacheartifactId>
    4. dependency>
    1. package com.xxx.filter;
    2. import lombok.extern.slf4j.Slf4j;
    3. import org.springframework.cache.Cache;
    4. import org.springframework.cache.CacheManager;
    5. import org.springframework.cache.support.SimpleValueWrapper;
    6. import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    7. import org.springframework.cloud.gateway.filter.GlobalFilter;
    8. import org.springframework.core.Ordered;
    9. import org.springframework.core.io.buffer.DataBuffer;
    10. import org.springframework.http.HttpHeaders;
    11. import org.springframework.http.MediaType;
    12. import org.springframework.http.server.reactive.ServerHttpRequest;
    13. import org.springframework.http.server.reactive.ServerHttpResponse;
    14. import org.springframework.stereotype.Component;
    15. import org.springframework.web.reactive.function.client.WebClient;
    16. import org.springframework.web.server.ServerWebExchange;
    17. import reactor.core.publisher.Mono;
    18. import java.net.URI;
    19. import java.util.ArrayList;
    20. import java.util.Collections;
    21. import java.util.List;
    22. import java.util.regex.Matcher;
    23. import java.util.regex.Pattern;
    24. /**
    25. * @author Wang
    26. * 创建时间: 2023/11/15 10:19
    27. * 功能描述:静态资源缓存
    28. */
    29. @Slf4j
    30. @Component
    31. public class StaticResourceFilter implements GlobalFilter, Ordered {
    32. private static final String STATIC_RESOURCE_PATTERN = "\\.(html|css|js|png|jpg|jpeg|gif|woff2|woff)$";
    33. private final WebClient webClient;
    34. private final CacheManager cacheManager;
    35. List synchronizedList = Collections.synchronizedList(new ArrayList<>());
    36. public StaticResourceFilter(WebClient webClient, CacheManager cacheManager) {
    37. this.webClient = webClient;
    38. this.cacheManager = cacheManager;
    39. }
    40. @Override
    41. public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    42. ServerHttpRequest request = exchange.getRequest();
    43. URI uriInfo = request.getURI();
    44. String staticResourcePath = getUrl(uriInfo);
    45. if (isStaticResource(staticResourcePath) && !synchronizedList.contains(staticResourcePath)) {
    46. //Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
    47. String cacheKey = request.getURI().toString();
    48. Cache cache = cacheManager.getCache("staticResources");
    49. // 尝试从缓存中获取静态资源
    50. Object cachedResource = cache.get(cacheKey);
    51. if (cachedResource != null) {
    52. if (cachedResource instanceof SimpleValueWrapper) {
    53. cachedResource = ((SimpleValueWrapper) cachedResource).get();
    54. }
    55. // 如果缓存中存在,直接返回缓存的资源
    56. ServerHttpResponse response = exchange.getResponse();
    57. HttpHeaders headers = response.getHeaders();
    58. String fileSuffix = staticResourcePath.replaceAll(".*(\\.[a-zA-Z0-9]+)$", "$1");
    59. // 根据文件后缀设置MIME类型
    60. switch (fileSuffix) {
    61. case ".html":
    62. headers.setContentType(MediaType.TEXT_HTML);
    63. break;
    64. case ".js":
    65. headers.set(HttpHeaders.CONTENT_TYPE, "application/javascript");
    66. break;
    67. case ".css":
    68. headers.set(HttpHeaders.CONTENT_TYPE, "text/css");
    69. break;
    70. case ".png":
    71. headers.setContentType(MediaType.IMAGE_PNG);
    72. break;
    73. case ".jpg":
    74. case ".jpeg":
    75. headers.setContentType(MediaType.IMAGE_JPEG);
    76. break;
    77. case ".woff":
    78. headers.set(HttpHeaders.CONTENT_TYPE, "application/font-woff");
    79. break;
    80. case ".woff2":
    81. headers.set(HttpHeaders.CONTENT_TYPE, "application/font-woff2");
    82. break;
    83. case ".ttf":
    84. headers.set(HttpHeaders.CONTENT_TYPE, "application/x-font-ttf");
    85. break;
    86. case ".eot":
    87. headers.set(HttpHeaders.CONTENT_TYPE, "application/vnd.ms-fontobject");
    88. break;
    89. default:
    90. headers.setContentType(MediaType.ALL);
    91. break;
    92. }
    93. // 这里假设缓存的内容是字节数组,您可以根据实际情况进行调整
    94. DataBuffer dataBuffer = response.bufferFactory().wrap((byte[]) cachedResource);
    95. return response.writeWith(Mono.just(dataBuffer));
    96. }
    97. // 如果缓存不存在,则继续请求下游服务获取资源,并将其缓存起来
    98. return chain.filter(exchange).then(Mono.fromRunnable(() -> {
    99. getResourceFromDownstream(staticResourcePath, cacheKey, cache);
    100. }));
    101. }
    102. // 继续处理其他过滤器或请求
    103. return chain.filter(exchange);
    104. }
    105. @Override
    106. public int getOrder() {
    107. return Ordered.HIGHEST_PRECEDENCE;
    108. }
    109. /**
    110. * 根据请求路径判断是否为静态资源请求
    111. *
    112. * @param staticResourcePath 请求路径
    113. */
    114. private boolean isStaticResource(String staticResourcePath) {
    115. Pattern pattern = Pattern.compile(STATIC_RESOURCE_PATTERN);
    116. Matcher matcher = pattern.matcher(staticResourcePath);
    117. return matcher.find();
    118. }
    119. /**
    120. * 请求下游服务静态资源的方法,这里只是一个示例,您需要根据实际情况实现此方法
    121. *
    122. * @param cache 缓存
    123. * @param staticResourcePath URL
    124. * @param cacheKey 缓存Key
    125. */
    126. private void getResourceFromDownstream(String staticResourcePath, String cacheKey, Cache cache) {
    127. synchronizedList.add(staticResourcePath);
    128. Mono<byte[]> mono = webClient.get().uri(staticResourcePath).retrieve().bodyToMono(byte[].class);
    129. // 处理响应数据
    130. mono.subscribe(res -> {
    131. synchronizedList.remove(staticResourcePath);
    132. cache.put(cacheKey, res);
    133. }, error -> {
    134. log.error("请求下游服务静态资源失败:{},\n错误详情:{}", staticResourcePath, error.toString());
    135. });
    136. }
    137. /**
    138. * 获取静态资源地址
    139. *
    140. * @param uri uri
    141. * @return 静态资源地址
    142. */
    143. private String getUrl(URI uri) {
    144. String path = uri.getPath();
    145. String host = uri.getHost();
    146. int port = uri.getPort();
    147. // 下游服务的地址是
    148. String downstreamUrl = String.format("http://%s:%s%s", host, port, path);
    149. return downstreamUrl;
    150. }
    151. }

  • 相关阅读:
    element table表格行列合并span-method,根据数据动态行列合并
    6-6漏洞利用-SSH安全防御
    百元开放式耳机哪款好一点耐用、百元耳放推荐
    javaScript 使用indexOf 撸一下模糊查询
    深度学习基础知识 学习率调度器的用法解析
    30、三维表面重建-Convolutional Occupancy Network
    物联网主机E6000引领工业自动化的新篇章
    【Java SE】数组
    进程地址空间
    vue中excel的编辑、导入、导出
  • 原文地址:https://blog.csdn.net/cocoManager/article/details/134421013