Spring Boot

Spring Cloud Gateway重写请求

2024-06-13  本文已影响0人  EasyNetCN

在Spring Cloud中,有时候需要对前端直接调用的微服务,进行请求内容重组,这时候可以通过自定义org.springframework.cloud.gateway.filter.GlobalFilter,org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction,来满足需求。
下面的例子,是前端通过Gateway调用后端的文件服务,获取上传OSS的一些必要信息。通过重组,可以简化和规范使用。

自定义RewriteFunction


import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

import org.apache.commons.lang3.StringUtils;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.gateway.filter.factory.rewrite.RewriteFunction;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import reactor.core.publisher.Mono;

@Component
public class FileServiceRequestRewriteFunction implements RewriteFunction<byte[], byte[]> {
    private static final Logger logger = LoggerFactory.getLogger(FileServiceRequestRewriteFunction.class);

    private Environment environment;
    private ObjectMapper objectMapper;
    private FileServiceProperties fileServiceProperties;

    public FileServiceRequestRewriteFunction(Environment environment, ObjectMapper objectMapper,
            FileServiceProperties fileServiceProperties) {
        this.environment = environment;
        this.objectMapper = objectMapper;
        this.fileServiceProperties = fileServiceProperties;
    }

    @Override
    public Publisher<byte[]> apply(ServerWebExchange t, byte[] u) {
        UploadTokenRequest uploadTokenRequest = new UploadTokenRequest();

        try {
            uploadTokenRequest = objectMapper.readValue(u, UploadTokenRequest.class);
        } catch (IOException e) {
            logger.error("转换异常", e);

            return Mono.just(u);
        }

        var ossUploadFile = new OssUploadFile();

        BeanUtils.copyProperties(uploadTokenRequest, ossUploadFile);

        ossUploadFile.bucket = fileServiceProperties.getTypeBuckets().getOrDefault(uploadTokenRequest.getType(),
                fileServiceProperties.getDefaultBucket());

        ossUploadFile.prefix = getPrefix(uploadTokenRequest.getType(), uploadTokenRequest.getPrefix());

        try {
            return Mono.just(objectMapper.writeValueAsBytes(ossUploadFile));
        } catch (JsonProcessingException e) {
            logger.error("转换异常", e);

            return Mono.just(u);
        }
    }

    private String getActiveProfile() {
        var profiles = environment.getActiveProfiles();

        return profiles.length > 0 ? profiles[0] : "";
    }

    private String getPrefix(String type, String prefix) {
        var activeProfile = getActiveProfile();
        var sb = new StringBuilder();

        if (StringUtils.isNotBlank(activeProfile) && !activeProfile.equalsIgnoreCase("prod")) {
            sb.append(activeProfile.toLowerCase());
        }

        if (StringUtils.isNotBlank(type)) {
            if (!sb.isEmpty()) {
                sb.append("/");
            }

            sb.append(type.toLowerCase());
        }

        if (StringUtils.isNotBlank(prefix)) {
            if (!sb.isEmpty()) {
                sb.append("/");
            }

            sb.append(prefix);
        } else {
            if (!sb.isEmpty()) {
                sb.append("/");
            }

            sb.append(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd")));
        }

        return sb.toString();
    }

    static class UploadTokenRequest {
        private String type;
        private String bucket;
        private String prefix;
        private String fileKey;
        private String sourceFile;
        private Long sourceFileSize;
        private String sourceFileType;
        private Integer useSourceFilename;
        private Long expiredInSec;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getBucket() {
            return bucket;
        }

        public void setBucket(String bucket) {
            this.bucket = bucket;
        }

        public String getPrefix() {
            return prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getFileKey() {
            return fileKey;
        }

        public void setFileKey(String fileKey) {
            this.fileKey = fileKey;
        }

        public String getSourceFile() {
            return sourceFile;
        }

        public void setSourceFile(String sourceFile) {
            this.sourceFile = sourceFile;
        }

        public Long getSourceFileSize() {
            return sourceFileSize;
        }

        public void setSourceFileSize(Long sourceFileSize) {
            this.sourceFileSize = sourceFileSize;
        }

        public String getSourceFileType() {
            return sourceFileType;
        }

        public void setSourceFileType(String sourceFileType) {
            this.sourceFileType = sourceFileType;
        }

        public Integer getUseSourceFilename() {
            return useSourceFilename;
        }

        public void setUseSourceFilename(Integer useSourceFilename) {
            this.useSourceFilename = useSourceFilename;
        }

        public Long getExpiredInSec() {
            return expiredInSec;
        }

        public void setExpiredInSec(Long expiredInSec) {
            this.expiredInSec = expiredInSec;
        }
    }

    static class OssUploadFile {
        private String bucket;
        private String prefix;
        private String fileKey;
        private String sourceFile;
        private Long sourceFileSize;
        private String sourceFileType;
        private Integer useSourceFilename;
        private Long expiredInSec;

        public String getBucket() {
            return bucket;
        }

        public void setBucket(String bucket) {
            this.bucket = bucket;
        }

        public String getPrefix() {
            return prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getFileKey() {
            return fileKey;
        }

        public void setFileKey(String fileKey) {
            this.fileKey = fileKey;
        }

        public String getSourceFile() {
            return sourceFile;
        }

        public void setSourceFile(String sourceFile) {
            this.sourceFile = sourceFile;
        }

        public Long getSourceFileSize() {
            return sourceFileSize;
        }

        public void setSourceFileSize(Long sourceFileSize) {
            this.sourceFileSize = sourceFileSize;
        }

        public String getSourceFileType() {
            return sourceFileType;
        }

        public void setSourceFileType(String sourceFileType) {
            this.sourceFileType = sourceFileType;
        }

        public Integer getUseSourceFilename() {
            return useSourceFilename;
        }

        public void setUseSourceFilename(Integer useSourceFilename) {
            this.useSourceFilename = useSourceFilename;
        }

        public Long getExpiredInSec() {
            return expiredInSec;
        }

        public void setExpiredInSec(Long expiredInSec) {
            this.expiredInSec = expiredInSec;
        }
    }
}

自定义GlobalFilter


import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory;
import org.springframework.cloud.gateway.route.Route;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;

/**
 * 文件服务全局过滤器
 */
@Component
public class FileServiceGatewayGlobalFilter implements GlobalFilter {
    private ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory;
    private FileServiceProperties fileServiceProperties;
    private FileServiceRequestRewriteFunction fileServiceRequestRewriteFunction;

    public FileServiceGatewayGlobalFilter(ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory,
            FileServiceProperties fileServiceProperties,
            FileServiceRequestRewriteFunction fileServiceRequestRewriteFunction) {
        this.modifyRequestBodyGatewayFilterFactory = modifyRequestBodyGatewayFilterFactory;
        this.fileServiceProperties = fileServiceProperties;
        this.fileServiceRequestRewriteFunction = fileServiceRequestRewriteFunction;
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        Route route = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);

        if (route != null && route.getUri() != null && route.getUri().getHost().equalsIgnoreCase("file-service")) {

            var requestPath = exchange.getRequest().getURI().getPath();

            if (requestPath.equalsIgnoreCase(fileServiceProperties.getUploadTokenPath())) {
                return modifyRequestBodyGatewayFilterFactory.apply(new ModifyRequestBodyGatewayFilterFactory()
                        .newConfig().setRewriteFunction(byte[].class, byte[].class, fileServiceRequestRewriteFunction))
                        .filter(exchange, chain);

            }
        }

        return chain.filter(exchange);
    }

    static class UploadTokenRequest {
        private String type;
        private String bucket;
        private String prefix;
        private String fileKey;
        private String sourceFile;
        private Long sourceFileSize;
        private String sourceFileType;
        private Integer useSourceFilename;
        private Long expiredInSec;

        public String getType() {
            return type;
        }

        public void setType(String type) {
            this.type = type;
        }

        public String getBucket() {
            return bucket;
        }

        public void setBucket(String bucket) {
            this.bucket = bucket;
        }

        public String getPrefix() {
            return prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getFileKey() {
            return fileKey;
        }

        public void setFileKey(String fileKey) {
            this.fileKey = fileKey;
        }

        public String getSourceFile() {
            return sourceFile;
        }

        public void setSourceFile(String sourceFile) {
            this.sourceFile = sourceFile;
        }

        public Long getSourceFileSize() {
            return sourceFileSize;
        }

        public void setSourceFileSize(Long sourceFileSize) {
            this.sourceFileSize = sourceFileSize;
        }

        public String getSourceFileType() {
            return sourceFileType;
        }

        public void setSourceFileType(String sourceFileType) {
            this.sourceFileType = sourceFileType;
        }

        public Integer getUseSourceFilename() {
            return useSourceFilename;
        }

        public void setUseSourceFilename(Integer useSourceFilename) {
            this.useSourceFilename = useSourceFilename;
        }

        public Long getExpiredInSec() {
            return expiredInSec;
        }

        public void setExpiredInSec(Long expiredInSec) {
            this.expiredInSec = expiredInSec;
        }
    }

    static class OssUploadFile {
        private String bucket;
        private String prefix;
        private String fileKey;
        private String sourceFile;
        private Long sourceFileSize;
        private String sourceFileType;
        private Integer useSourceFilename;
        private Long expiredInSec;

        public String getBucket() {
            return bucket;
        }

        public void setBucket(String bucket) {
            this.bucket = bucket;
        }

        public String getPrefix() {
            return prefix;
        }

        public void setPrefix(String prefix) {
            this.prefix = prefix;
        }

        public String getFileKey() {
            return fileKey;
        }

        public void setFileKey(String fileKey) {
            this.fileKey = fileKey;
        }

        public String getSourceFile() {
            return sourceFile;
        }

        public void setSourceFile(String sourceFile) {
            this.sourceFile = sourceFile;
        }

        public Long getSourceFileSize() {
            return sourceFileSize;
        }

        public void setSourceFileSize(Long sourceFileSize) {
            this.sourceFileSize = sourceFileSize;
        }

        public String getSourceFileType() {
            return sourceFileType;
        }

        public void setSourceFileType(String sourceFileType) {
            this.sourceFileType = sourceFileType;
        }

        public Integer getUseSourceFilename() {
            return useSourceFilename;
        }

        public void setUseSourceFilename(Integer useSourceFilename) {
            this.useSourceFilename = useSourceFilename;
        }

        public Long getExpiredInSec() {
            return expiredInSec;
        }

        public void setExpiredInSec(Long expiredInSec) {
            this.expiredInSec = expiredInSec;
        }
    }
}

文件服务配置


import java.util.Map;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "file-service", ignoreUnknownFields = true)
public class FileServiceProperties {
    private String uploadTokenPath;

    private String defaultBucket;

    private Map<String, String> typeBuckets;

    public String getUploadTokenPath() {
        return uploadTokenPath;
    }

    public void setUploadTokenPath(String uploadTokenPath) {
        this.uploadTokenPath = uploadTokenPath;
    }

    public String getDefaultBucket() {
        return defaultBucket;
    }

    public void setDefaultBucket(String defaultBucket) {
        this.defaultBucket = defaultBucket;
    }

    public Map<String, String> getTypeBuckets() {
        return typeBuckets;
    }

    public void setTypeBuckets(Map<String, String> typeBuckets) {
        this.typeBuckets = typeBuckets;
    }
}
上一篇 下一篇

猜你喜欢

热点阅读