最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring cloud gateway(Web MVC)的深入使用

 更新時(shí)間:2026年02月09日 09:59:13   作者:茗冬  
本文詳細(xì)介紹了Spring Cloud Gateway的使用,包括工程搭建、路由配置、自定義過濾器和謂詞的實(shí)現(xiàn)與使用,以及效果驗(yàn)證,感興趣的朋友跟隨小編一起看看吧

一定是spring boot項(xiàng)目,spring cloud gateway基于spring boot

前言

提示:本文所用的是spring cloud gateway web mvc特性
本文提供了對spring cloud gateway網(wǎng)關(guān)的使用案例,并沒有列舉出所有過濾器或謂詞的使用示例,但是包含了從工程搭建及基本使用至概念理解再到一些自定義客制化的使用。為你打開基本使用到深入使用的一扇門。所配關(guān)鍵代碼都有注釋,一定可以為你答疑解惑。

一、前置條件

提示:spring cloud gateway是基于spring boot,項(xiàng)目一定是spring boot項(xiàng)目,一定是spring boot項(xiàng)目
jdk:17
構(gòu)建工具:maven 3.6.3
spring相關(guān)jar:spring-cloud-starter-gateway-server-webmvc 4.3.0(必須),spring boot 3.5.8(被間接依賴至項(xiàng)目中),spring cloud 2025.0.0(作為pom)
參考資料:https://docs.spring.io/spring-cloud-gateway/reference/4.3/spring-cloud-gateway-server-webmvc.html
開發(fā)工具:idea 2021.2

二、工程搭建(創(chuàng)建一個(gè)普通maven工程,添加必要依賴及構(gòu)建工具即可,本案例是一個(gè)maven子工程)

提示:按需可引入spring boot starter parent,直接按需用spring 配套的插件及依賴包,更為方便
父工程pom.xml (僅列出關(guān)鍵依賴)

工程目錄

pom.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>springCloudMicroService</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>gatewayServerWebMvcDemo</artifactId>
    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <!-- 設(shè)置編碼格式,防止maven打包構(gòu)建時(shí)沒有統(tǒng)一編碼格式導(dǎo)致有中文注釋的文件解析異常,影響項(xiàng)目啟動(dòng) -->
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway-server-webmvc</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <!-- spring boot構(gòu)建相關(guān)配置 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <parameters>true</parameters>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>3.5.8</version>
                <configuration>
                    <mainClass>${start-class}</mainClass>
                    <layout>JAR</layout>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <!-- 【很關(guān)鍵】自定義${}占位符,用于將pom文件的變量動(dòng)態(tài)替換到applicaton**.yml的某處
                    例如這里的application.yml文件,使用${spring.profiles.active}取
                    將pom.xml->properties->profile->properties->spring.profiles.active屬性值
                     -->
                    <delimiters>
                        <delimiter>${}</delimiter>
                    </delimiters>
                    <!-- 禁用默認(rèn)的占位符@xxPropertiesName@ -->
                    <useDefaultDelimiters>false</useDefaultDelimiters>
                    <resources>
                        <resource>
                            <directory>src/main/resources</directory>
                            <filtering>true</filtering> <!-- 根據(jù)需要開啟或關(guān)閉 -->
                            <includes>
                                <include>public/**</include>
                                <include>static/**</include>
                                <include>templates/**</include>
                                <include>mapper/**</include>
                                <include>properties/**</include>
                                <include>i18n/**</include>
                                <include>logback*.xml</include>
                                <!-- 包含默認(rèn)的配置文件,這個(gè)配置文件僅有spring.profiles.active屬性,這是不加profiles啟動(dòng)的關(guān)鍵 -->
                                <include>application.yml</include>
                                <!-- 按maven不同的打包參數(shù),打包不同的環(huán)境相關(guān)的配置文件 -->
                                <include>application-${spring.profiles.active}.*</include>
                                <include>log*-${spring.profiles.active}.xml</include>
                            </includes>
                        </resource>
                    </resources>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <!-- profiles 相關(guān)配置 -->
    <profiles>
        <!--
        profile中的<id>div</id>元素值指的是-P 的參數(shù), 如:mvn clean install -P div
        profile中的<properties><spring.profiles.active>dev</spring.profiles.active></properties>中的spring.profiles.active元素及值
        值指的是-D 的參數(shù), 如:mvn clean install -Dspring.profiles.active=dev
        -->
        <profile>
            <!-- 開發(fā)環(huán)境 -->
            <id>dev</id>
            <properties>
                <spring.profiles.active>dev</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
        </profile>
        <!-- 測試環(huán)境 -->
        <profile>
            <id>sit</id>
            <properties>
                <spring.profiles.active>sit</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
        </profile>
        <!-- 生產(chǎn)環(huán)境 -->
        <profile>
            <id>prod</id>
            <properties>
                <spring.profiles.active>prod</spring.profiles.active>
            </properties>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
        </profile>
    </profiles>
</project>

三、功能實(shí)現(xiàn)范圍

  • 配置文件或java編程方式的路由配置
  • 自定義過濾器(filter)、自定義謂詞(predicate)的實(shí)現(xiàn)與使用
  • 路由到本服務(wù)接口(就是用于spring mvc的函數(shù)式端點(diǎn)的使用)

四、需要路由訪問的服務(wù)(應(yīng)用)準(zhǔn)備

網(wǎng)關(guān)自身(服務(wù)/應(yīng)用):http://localhost:8888
應(yīng)用一:http://localhost:8081/entitleservice
應(yīng)用二:http://localhost:8082/functonservletpath

五、路由配置(配置文件方式)

提示:兩種路由配置方式二選一,二選一,二選一!??!
默認(rèn)配置文件(application.yml)

server:
  server-name: gatewaymvcdemo
  port: 8888
spring:
  profiles:
#    active: javaconfig
    active: fileconfig

路由配置文件(application-fileconfig.yml)

# 使用配置文件方式配置路由
spring:
  cloud:
    gateway:
      server:
        webmvc:
          routes:
            # 配置路由到function demo服務(wù)
            - id: function_demo_route
              uri: http://localhost:8082
              predicates:
                - Method=GET,PUT,DELETE,POST
                - Path=/functionservletpath/**
              filters:
                - AddRequestParameter=code, gateway for functiondemo
                - AddRequestHeader=function-Request-Id,function_header_value
            - id: entitle_route
              uri: http://localhost:8081
              predicates:
                - Method=GET,PUT,DELETE,POST
                - Path=/entitleservice/info/**,/entitleservice/gatewayInfo/**,/entitleservice/user/**,/entitleservice/role/**
                - predicateHeaderExists=custom_header
              filters:
                - AddRequestParameter=code, gate way for entitleservice
                - AddRequestHeader=entitle-Request-Id,entitle_header_value
                - instrumentForFilter=req_header,rep_header

六、路由配置(java編程方式)

提示:兩種路由配置方式二選一,二選一,二選一!?。?!
默認(rèn)配置文件(application.yml)

server:
  server-name: gatewaymvcdemo
  port: 8888
spring:
  profiles:
    active: javaconfig

路由配置文件(application-javaconfig.yml)
提示:路由配置文件為空,因使用java編程方式配置
java配置文件(ApplicationRoutingConfig.java)

package com.mrhan.config;
import com.mrhan.service.GatewayHandler;
import com.mrhan.service.UserHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.function.*;
import java.time.ZonedDateTime;
import java.util.function.BiFunction;
import java.util.function.Function;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.*;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;
import static org.springframework.cloud.gateway.server.mvc.predicate.GatewayRequestPredicates.*;
import static org.springframework.web.servlet.function.RequestPredicates.accept;
/**
 * @author Mr han
 * @date 2025/12/6
 * @description 路由配置,此處配置了路由后,application.yml中配置的路由將無效,兩種配置只能存在一種,不能并存
 * 同等效果配置文件方式配置@see application.yml,自定義的filter和predicate在兩種配置方式都能夠生效
 *
 *
*/
@Configuration(proxyBeanMethods = false)
@Profile("javaconfig")
public class ApplicationRoutingConfig {
    private static final Logger log = LoggerFactory.getLogger(ApplicationRoutingConfig.class);
    /**
     *
     * @return
     * @date 2025/12/17
     * @description 使用java代碼方式配置路由,等價(jià)于@see application.yml文件配置方式
     *
     */
    @Bean
    public RouterFunction<ServerResponse> customRoutes(GatewayHandler gatewayHandler) {
        // @formatter:off
        return route("path_route")
                .GET("/gateway/getRole", accept(MediaType.TEXT_HTML),gatewayHandler::getRole)
                .POST("/gateway/updateRole/{roleId}", accept(MediaType.APPLICATION_JSON), gatewayHandler::updateRole)
                .before(request -> {
                    String path = request.requestPath().value();
                    log.error("=========開始進(jìn)入本服務(wù)請求:{}=========",path);
                    return request;
                })
                // 添加請求之后的函數(shù)處理器
                .after((request,response) -> {
                    log.error("==========本服務(wù)請求處理完畢:{},響應(yīng)的狀態(tài)碼:",request.requestPath().value(),response.statusCode());
                    return response;
                })
                .build().and(route("entitle_route")
                    .route(path("/entitleservice/**").and(SampleRequestPredicates.predicateHeaderExists("entitle_header")), http())
                    .before(uri("http://localhost:8081"))
                    .before(addRequestParameter("code","Java gateway for entitlementservice"))
                    .before(addRequestHeader("java_config_header","java config value"))
                    .filter(SampleHandlerFilterFunctions.instrumentForFilter("req_header","rep_header"))
                .build().and(route("function_demo_route")
                    .route(path("/functionservletpath/**").and(SampleRequestPredicates.predicateHeaderExists("function_header")), http())
                    .before(uri("http://localhost:8082"))
                    .before(addRequestParameter("code","Java config gateway for functiondemo"))
                    .before(addRequestHeader("function-Request-Id","function_header_value"))
                .build()));
    }
    /**
     * @author Mr han
     * @date 2025/12/15
     * @description 自定義的predicate 是否包含某個(gè)固定的請求頭,此類的實(shí)現(xiàn)等等同于方法 @see {@link SampleRequestPredicates#predicateHeaderExists(String)}
     *
    */
    private static class CustomHeaderExists implements RequestPredicate {
        // 請求頭名稱
        private static final String HEADER_NAME = "custom_header";
        /**
         *
         * @return
         * @date 2025/12/15
         * @description 需要包含custom_header請求頭
         *
         */
        @Override
        public boolean test(ServerRequest request) {
            return request.headers().asHttpHeaders().containsKey(HEADER_NAME);
        }
    }
    /**
     *
     * @return
     * @date 2025/12/15
     * @description 使用函數(shù)式的方法,自定義過濾器,使用函數(shù)式方法實(shí)現(xiàn)過濾器
     * 在自定義的過濾器中可以實(shí)現(xiàn)日志的打印,已經(jīng)權(quán)限的認(rèn)證等邏輯,這里僅僅是增加請求頭及響應(yīng)頭
     * 此方法等同于@see {@link SampleHandlerFilterFunctions#instrumentForFilter(String, String)}
     *
     */
    private static HandlerFilterFunction<ServerResponse, ServerResponse> instrumentWithFilter(String requestHeader,String responseHeader){
        return (request,next) -> {
            ServerRequest modifier = ServerRequest.from(request).header(requestHeader, "hello").build();
            ServerResponse responseHandler = next.handle(modifier);
            responseHandler.headers().add(responseHeader, "world");
            return responseHandler;
        };
    }
    /**
     *
     * @return
     * @date 2025/12/15
     * @description 使用函數(shù)式的方法,定義before方式的過濾器
     *
     */
    private static Function<ServerRequest, ServerRequest> instrumentWithBefore(String requestHeader){
        return request -> {
            return ServerRequest.from(request).header(requestHeader, "before_header_value").build();
        };
    }
    /**
     *
     * @return
     * @date 2025/12/15
     * @description 使用函數(shù)式的方法,定義after方式的過濾器
     *
     */
    private static BiFunction<ServerRequest, ServerResponse, ServerResponse> instrumentWithAfter(String header){
        return (request,response) -> {
            response.headers().add(header, "after_header_value");
            return response;
        };
    }
}

七、自定義過濾器

· 提示:定義的過濾器類按一個(gè)類一個(gè)靜態(tài)方法,多增加幾個(gè)靜態(tài)方法spring也只會(huì)加載第一個(gè)靜態(tài)方法,靜態(tài)方法一定要加@Shotcut注解,不然啟動(dòng)報(bào)錯(cuò),報(bào)錯(cuò)原因分析及解決,將在另一篇關(guān)于gateway疑難雜癥解決的文章中展開。
過濾器定義(SampleHandlerFilterFunctions.java):一個(gè)類一個(gè)靜態(tài)過濾器方法(方法上一定要加上@Shortcut注解),多加了也沒用spring只會(huì)加載第一個(gè)靜態(tài)方法

package com.mrhan.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.server.mvc.common.Configurable;
import org.springframework.cloud.gateway.server.mvc.common.Shortcut;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.function.HandlerFilterFunction;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
import java.util.Objects;
import java.util.function.Function;
/**
 * @author Mr han
 * @date 2025/12/15
 * @description 定義包含所有自定義filter的函數(shù)式過濾器類,供filtersupplier類使用暴露到項(xiàng)目中
 * 一個(gè)類只能定義一個(gè)靜態(tài)方法,spring cloud gateway只注冊一個(gè)靜態(tài)方法
 */
public class SampleHandlerFilterFunctions {
    private static final Logger log = LoggerFactory.getLogger(SampleHandlerFilterFunctions.class);
    @Shortcut
    public static HandlerFilterFunction<ServerResponse, ServerResponse> instrumentForFilter(String reqHeaderName,String repHeaderName) {
        return (request, next) -> {
            log.error("==========進(jìn)入自定義filter處理邏輯,請求頭:{},響應(yīng)頭{}===========",reqHeaderName,repHeaderName);
            ServerRequest modified = ServerRequest.from(request)
                    .header(reqHeaderName, "request header for filter").build();
            ServerResponse response = next.handle(modified);
            response.headers().add(repHeaderName,"response header for filter" );
            return response;
        };
    }

過濾器提供者(CustomFilterSupplier.java):就是一個(gè)繼承了SimpleFilterSupplier類的類而已,重寫了繼承方法

package com.mrhan.config;
import org.springframework.cloud.gateway.server.mvc.filter.SimpleFilterSupplier;
/**
 * @author Mr han
 * @date 2025/12/15
 * @description 創(chuàng)建字對應(yīng)的filterSupplier,用于注冊提供自定義的filter
 */
public class CustomFilterSupplier extends SimpleFilterSupplier {
    public CustomFilterSupplier() {
        super(SampleHandlerFilterFunctions.class);
    }
}

過濾器配置類(FilterConfiguration.java):只是為了將過濾器提供者注冊為Bean

package com.mrhan.config;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
 * @author Mr han
 * @date 2025/12/17
 * @description 注冊自定義的過濾器,用于配置在application.yml文件中,目前使用此配置方式無實(shí)際效果 TODO
*/
@Configuration
@Profile("fileconfig")
public class FilterConfiguration {
    private static final Logger log = LoggerFactory.getLogger(FilterConfiguration.class);
    @PostConstruct
    public void init(){
        log.error("========開始加載FilterConfiguration配置============");
    }
    @Bean
    public CustomFilterSupplier customFilterSupplier() {
        return new CustomFilterSupplier();
    }
}

八、自定義謂詞

提示:定義的謂詞按一個(gè)類一個(gè)靜態(tài)方法,多增加幾個(gè)靜態(tài)方法spring也只會(huì)加載第一個(gè)靜態(tài)方法,靜態(tài)方法一定要加@Shortcut注解,不然啟動(dòng)報(bào)錯(cuò),報(bào)錯(cuò)原因分析及解決,將在另一篇關(guān)于gateway疑難雜癥解決的文章中展開。
謂詞定義(SampleRequestPredicates.java):一個(gè)類一個(gè)靜態(tài)過濾器方法(一定要加上@ShortCut注解),多加了也沒用spring只會(huì)加載第一個(gè)靜態(tài)方法

package com.mrhan.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.server.mvc.common.Configurable;
import org.springframework.cloud.gateway.server.mvc.common.Shortcut;
import org.springframework.web.servlet.function.RequestPredicate;
/**
 * @author Mr han
 * @date 2025/12/15
 * @description 定義包含自定義Predicate的所有實(shí)現(xiàn)的類
 */
public class SampleRequestPredicates {
    private static final Logger log = LoggerFactory.getLogger(SampleRequestPredicates.class);
    /**
     *
     * @return
     * @date 2025/12/15
     * @description 請求頭的判斷(是否包含某個(gè)名稱的請求頭),必須添加@Configurable注解且只能有一個(gè)參數(shù),不然無法生效
     *
     */
    @Shortcut
    public static RequestPredicate predicateHeaderExists(String name) {
        log.error("======進(jìn)入了自定義predicate的處理邏輯所需請求頭:{}==========",name);
        return request -> {
            return request.headers().asHttpHeaders().containsKey(name);
        };
    }
}

謂詞提供者(CustomPredicateSupplier.java):就是一個(gè)實(shí)現(xiàn)了PredicateSupplier接口的類

package com.mrhan.config;
import org.springframework.cloud.gateway.server.mvc.predicate.PredicateSupplier;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
public class CustomPredicateSupplier implements PredicateSupplier {
    @Override
    public Collection<Method> get() {
        return Arrays.asList(SampleRequestPredicates.class.getMethods());
    }
}

謂詞配置類(PredicateConfiguration.java):只是為了將謂詞提供者注冊為Bean

package com.mrhan.config;
import jakarta.annotation.PostConstruct;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.server.mvc.predicate.PredicateSupplier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
/**
 * @author Mr han
 * @date 2025/12/17
 * @description 注冊自定義的predicate,用在application.yml中
*/
@Configuration
@Profile("fileconfig")
public class PredicateConfiguration {
    private static final Logger log = LoggerFactory.getLogger(PredicateConfiguration.class);
    @PostConstruct
    public void init(){
        log.error("========開始加載PredicateConfiguration配置============");
    }
    @Bean
    public CustomPredicateSupplier customPredicateSupplier() {
        return new CustomPredicateSupplier();
    }
}

九、自定義謂詞、自定義過濾器的使用(配置文件或java編程方式)

配置文件方式:格式"靜態(tài)方法名(首字母大寫小寫都可)=參數(shù)值"

java編程方式:直接調(diào)用過濾器或謂詞方法即可

十、效果驗(yàn)證(配置文件方式的路由效果)

未配置指定請求頭:訪問404

配置指定請求頭:驗(yàn)證自定義的過濾器,謂詞等效果

十一、一些疑問、困惑的解釋

  • 配置中的uri是干嘛的?
    解釋:處理轉(zhuǎn)發(fā)過來的請求的服務(wù)器地址
  • 怎么理解網(wǎng)關(guān)?
    解釋:將匹配(含你定義的請求路徑、攜帶了某個(gè)請求頭、請求參數(shù)等)你謂詞(predicate)的請求經(jīng)過一系列處理(過濾器的路徑重寫、添加請求頭、參數(shù)等)后轉(zhuǎn)給你指定的處理器(可能是訪問的服務(wù)地址,可能是你指定處理該請求的一個(gè)方法)做處理,是請求訪問的守門員。

總結(jié)

到此這篇關(guān)于Spring cloud gateway(Web MVC)的使用全集的文章就介紹到這了,更多相關(guān)Spring cloud gateway使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

景德镇市| 凤山县| 汪清县| 吴忠市| 通河县| 伊春市| 封开县| 上虞市| 临汾市| 玉林市| 揭东县| 灵璧县| 永寿县| 定南县| 蒙自县| 安吉县| 视频| 宾川县| 宾川县| 义乌市| 项城市| 芷江| 三穗县| 满洲里市| 名山县| 华宁县| 汕头市| 璧山县| 库尔勒市| 兴宁市| 淄博市| 民权县| 石景山区| 普兰店市| 静海县| 德庆县| 柏乡县| 通道| 永州市| 来凤县| 通辽市|