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

这篇具有很好参考价值的文章主要介绍了基于spring gateway 的静态资源缓存实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

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

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

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

直接上代码:文章来源地址https://www.toymoban.com/news/detail-774737.html

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

    @Override
    public 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);
    }

    @Override
    public 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 的静态资源缓存实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第七章 : Spring cloud 网关中心 Gateway (静态路由)

    第七章 : Spring cloud 网关中心 Gateway (静态路由) 前言 本章知识点:本章将会介绍什么是Spring Cloud Gateway、为什么会出现Spring Cloud Gateway,以及Spring Cloud Gateway的工作原理和实战用法,以及Spring Cloud Gateway 路由概念以及基于nacos注册中心Spring Cloud Gateway 静态路由的实战。 什么

    2024年02月02日
    浏览(56)
  • Spring Boot静态资源映射

    在 Web 应用中会涉及到大量的静态资源,例如 JS、CSS 和 HTML 等。我们知道,Spring MVC 导入静态资源文件时,需要配置静态资源的映射;但在 SpringBoot 中则不再需要进行此项配置,因为 SpringBoot 已经默认完成了这一工作。 Spring Boot 默认为我们提供了 3 种静态资源映射规则: We

    2023年04月24日
    浏览(38)
  • 38、springboot为 spring mvc 提供的静态资源管理,覆盖和添加静态资源目录

    ▲ 默认的四个静态资源目录: /META-INF/resources /resources /static /public ▲ ResourceProperties.java类的源代码,可看到CLASSPATH_RESOURCE_LOCATIONS常量的定义: CLASSPATH_RESOURCE_LOCATIONS = new String[]{“classpath:/META-INF/resources/”, “classpath:/resources/”, “classpath:/static/”, “classpath:/public/”}; 这意味

    2024年02月11日
    浏览(43)
  • Spring Boot 配置静态资源路径

    在Spring Boot 2.7.2版本中,查看默认静态资源路径,在 WebProperties.class 中如下 可以看到默认资源路径有4个。 使用 Spring Initializr 新建Spring Boot项目,自带 static 目录,直接将前端资源文件放到该目录下,启动项目,访问 http://localhost:端口号/资源目录/名称.html 即可; 例如,有一个

    2023年04月15日
    浏览(34)
  • Spring Boot 访问静态资源css/js

    我们用 Spring Boot 搭建 Web 应用时(如搭建一个博客),经常需要在 Html 中访问一些静态资源,比如: css 样式; js 脚本; favicon.ico 图标等; 而在 Spring Boot 中如果没有做任何配置,是无法直接访问静态资源的,通常会报 404 错误 Spring Boot 访问静态资源,默认有两个默认目录:

    2024年02月08日
    浏览(47)
  • Spring Data Redis + RabbitMQ - 基于 string 实现缓存、计数功能(同步数据)

    目录 一、Spring Data Redis 1.1、缓存功能 1.1.1、分析 1.1.2、案例实现 1.1.3、效果演示 1.2、计数功能(Redis + RabbitMQ) 1.2.1、分析 1.2.2、案例实现 1.1.1、分析 使用 redis 作为缓存, MySQL 作为数据库组成的架构 整体思路: 应用服务器访问数据的时候,先查询 Redis,如果 Redis 上存在该

    2024年02月05日
    浏览(36)
  • Spring Data Redis + RabbitMQ - 基于 string + hash 实现缓存,计数(高内聚)

    目录 一、Spring Data Redis 1.1、缓存功能(分析) 1.2、案例实现 hash 类型存储缓存相比于 string 类型就有更多的更合适的使用场景. 例如,我有以下这样一个 UserInfo 信息  假设这样一个场景就是:

    2024年02月05日
    浏览(45)
  • Spring boot之WEB 开发-静态资源访问--自定义转换器--处理JSON--内容协商

    在线文档: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.developing-web-applications 1. 只要静态资源放在类路径下: /static 、/public 、/resources 、/META-INF/resources可以被直接访问- 对应文件WebProperties.java 2. 常见静态资源:JS、CSS 、图片(.jpg .png .gif .bmp .svg)、字体

    2024年02月09日
    浏览(57)
  • Minio + Nginx 实现静态资源对外访问

            公司交付项目,文件服务java + minio实现文件基本功能。其中包含文件上传与下载与在线预览,由于文件下载功能实现方式问题(web直接调用文件预览接口,有minio直接返回可预览路径二次请求实现文件下载)。         在公司局域网内没有问题,到客户环境文件无法

    2024年02月08日
    浏览(54)
  • Spring MVC学习随笔-控制器(Controller)开发详解:控制器跳转与作用域(二)视图模板、静态资源访问

    学习视频:孙哥说SpringMVC:结合Thymeleaf,重塑你的MVC世界!|前所未有的Web开发探索之旅 衔接上文Spring MVC学习随笔-控制器(Controller)开发详解:控制器跳转与作用域(一) SpingMVC中request作用域的处理 代码 Model、ModelMap相关细节分析 通过Model、ModelMap进行作用域处理,可以解决

    2024年02月05日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包