English 简体中文 繁體中文 한국 사람 日本語 Deutsch русский بالعربية TÜRKÇE português คนไทย french
查看: 2|回复: 0

nacos(七): gateway(单体)

[复制链接]
查看: 2|回复: 0

nacos(七): gateway(单体)

[复制链接]
查看: 2|回复: 0

233

主题

0

回帖

709

积分

高级会员

积分
709
1d95vIKJSn9

233

主题

0

回帖

709

积分

高级会员

积分
709
2025-2-25 12:43:37 | 显示全部楼层 |阅读模式
这篇文章将从gateway的搭建、自动路由匹配、路由数组、跨域和路由过滤器五个方面对gateway项目展开讨论。
1、gateway的搭建
gateway的项目基本的搭建过程与消费者的搭建过程基本一致,细节部分可参考《nacos(四): 创建第一个消费者Conumer(单体)》
搭建完成后,在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 https://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>    <groupId>com.example</groupId>    <version>0.0.1-SNAPSHOT</version>    <artifactId>gateway</artifactId>    <packaging>jar</packaging>    <properties>        <java.version>1.8</java.version>        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>        <spring-boot.version>2.7.6</spring-boot.version>        <spring-cloud-alibaba.version>2021.0.5.0</spring-cloud-alibaba.version>    </properties>    <dependencies>        <!-- 服务发现  -->        <dependency>            <groupId>com.alibaba.cloud</groupId>            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>        </dependency>        <!--消费者-->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-loadbalancer</artifactId>            <version>3.1.5</version>        </dependency>        <!--⽹关-->        <dependency>            <groupId>org.springframework.cloud</groupId>            <artifactId>spring-cloud-starter-gateway</artifactId>        </dependency>        <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-test</artifactId>            <scope>test</scope>        </dependency>    </dependencies>    <dependencyManagement>        <dependencies>            <dependency>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-dependencies</artifactId>                <version>${spring-boot.version}</version>                <type>pom</type>                <scope>import</scope>            </dependency>            <dependency>                <groupId>com.alibaba.cloud</groupId>                <artifactId>spring-cloud-alibaba-dependencies</artifactId>                <version>${spring-cloud-alibaba.version}</version>                <type>pom</type>                <scope>import</scope>            </dependency>            <dependency>                <groupId>org.springframework.cloud</groupId>                <artifactId>spring-cloud-dependencies</artifactId>                <version>2021.0.5</version>                <type>pom</type>                <scope>import</scope>            </dependency>        </dependencies>    </dependencyManagement>    <build>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <version>3.8.1</version>                <configuration>                    <source>1.8</source>                    <target>1.8</target>                    <encoding>UTF-8</encoding>                </configuration>            </plugin>            <plugin>                <groupId>org.springframework.boot</groupId>                <artifactId>spring-boot-maven-plugin</artifactId>                <version>${spring-boot.version}</version>                <configuration>                    <mainClass>com.example.gateway.GatewayApplication</mainClass>                    <skip>false</skip>                </configuration>                <executions>                    <execution>                        <id>repackage</id>                        <goals>                            <goal>repackage</goal>                        </goals>                    </execution>                </executions>            </plugin>        </plugins>    </build></project>
注意:在gateway项目中,不能引入spring mvc或者start web类的关于web的依赖,否则会报错“Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway.”。
另外,gateway的版本也需要进行匹配,在前几篇文章中,我们也一再强调微服务项目对于库的版本要求非常精细。版本稍微不一致可能会报出奇怪的问题,比如”Error processing condition on org.springframework.cloud.gateway.config.GatewayAutoConfiguration.propertiesRouteDefinitionLocator“。
 
接下来,在application.yml中,开启自动路由匹配:
server:  port: 8087spring:  cloud:    nacos:      discovery:        server-addr: 127.0.0.1:8848        username: nacos        password: nacos      config:        server-addr: 127.0.0.1:8848        file-extension: properties        username: nacos        password: nacos    loadbalancer:      nacos:        enabled: true    gateway:      discovery:        locator:          enabled: true  application:    name: gateway
 
最后,我们在启动类上添加@EnableDiscoveryClient注解。
@SpringBootApplication@EnableDiscoveryClientpublic class GatewayApplication {    public static void main(String[] args) {        SpringApplication.run(GatewayApplication.class, args);    }}
 
配置完成后,启动gateway,可以看到nacos的管理后台里gateway已经注册成功。

 
2、路由自动匹配
在文章的第1部分里,application.yml中开启的路的自动匹配功能。
如个例子:
当前在nacos中有一个product1服务,服务提提供了/hello的地址。
通过gateway,我们可以访问http://127.0.0.1:8087/product1/hello,通过gateway访问到product1的hello地址。如下图:

其中:
127.0.0.1:8087:分别是gateway的IP地址和端口号;
product1: 是注册在nacos的里的服务名;
/hello:则是product1服务提供的资源地址。
 
3、路由数组
在application.yml中配置routes配置节,可开启路由数组,如下
server:  port: 8087spring:  cloud:    nacos:      discovery:        server-addr: 127.0.0.1:8848        username: nacos        password: nacos      config:        server-addr: 127.0.0.1:8848        file-extension: properties        username: nacos        password: nacos    loadbalancer:      nacos:        enabled: true    gateway:      discovery:        locator:          enabled: true      routes:        - id: product1_hello          uri: lb://product1    # 指的是从nacos中按照名称获取微服务,并遵循负载均衡策略          order: 1    # 路由优先级 数字越低优先级越高          predicates:    # 断言            - Path= /p1/**   # 当请求路径满⾜Path指定的规则时,才进⾏路由换发          filters:            - StripPrefix=1    # 拼接好url之后去掉1层路径也就是p1        - id: order_route          uri: lb://server-order          order: 1          predicates:            - Path=/order/**          filters:            - StripPrefix=1            - AddRequestHeader=msg,abc  application:    name: gateway
上面的这个配置文件例子中,路由数组里配置了两个路由。各项配置的具体配置的意义,看文件中的注释。其中- StripPrefix=1配置项需要注意。
这一项的意思是,当用户访问http://127.0.0.1:8087/p1/hello,因为/p1/路径触发了第一个路由规则,路由去掉p1这一项,重新拼接为lb://product1/hello去获取访问的结果。
 
断言proeicates还有如果规则可以使用:

 过滤器filters还有如下规则可以使用:

 
4、跨域
可以通过对application.yml的配置进行跨域项的设置,如下:
spring:  cloud:    gateway:      globalcors: # 全局的跨域处理        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题        corsConfigurations:          '[/**]':            allowedOrigins: # 允许哪些⽹站的跨域请求              - "http://localhost:8090"            allowedMethods: # 允许的跨域ajax的请求⽅式              - "GET"              - "POST"              - "DELETE"              - "PUT"              - "OPTIONS"            allowedHeaders: "*" # 允许在请求中携带的头信息            allowCredentials: true # 是否允许携带cookie            maxAge: 360000 # 这次跨域检测的有效期
 
5、路由过滤器
gateway也可以自定义自己的filter,下面用两个例子来说明过如何自定义filter。
示例一:判断请求参数中是否有authorization, authorization参数值是否为admin。如果同时满⾜则放⾏,否则拦截。
@Component@Order(-1) // 用来控制优先级 数字越小优先级越高public class AuthorizeFilter implements GlobalFilter {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        String token = exchange.getRequest().getHeaders().get("authorization").get(0);        if (token.equals("admin")){            //            放行            return chain.filter(exchange);        }        //        拦截 禁止访问        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);        return exchange.getResponse().setComplete();}
示例二:判断请求参数中是否有token,如果没有则拦截并报错。
@Componentpublic class TokenFilter implements GlobalFilter, Ordered {    @Override    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {        ServerHttpRequest req= exchange.getRequest();        ServerHttpResponse resp= exchange.getResponse();        MultiValueMap<String, String> params= req.getQueryParams();        if(!params.containsKey("token")){            //输出错误信息            Map<String, Object> map = new HashMap<>();            map.put("msg", "Not Logged in!!!!");            map.put("code", 4000); /*            //3.3作JSON转换           byte[] bytes = JSON.toJSONString(map).getBytes(StandardCharsets.UTF_8            );            //3.4调用bufferFactory方法,生成DataBuffer对象            DataBuffer buffer = response.bufferFactory().wrap(bytes);*/            //4.调用Mono中的just方法,返回要写给前端的JSON数据            DataBuffer buffer =resp.bufferFactory().wrap("error".getBytes(StandardCharsets.UTF_8));            return resp.writeWith(Mono.just(buffer));        }        return chain.filter(exchange);    }    @Override    public int getOrder() {        return 0;    }}
 
本文关于gateway的内容到这里就结束了,下一篇我们将一起讨论哨兵sentinel的使用: )
 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

233

主题

0

回帖

709

积分

高级会员

积分
709

QQ|智能设备 | 粤ICP备2024353841号-1

GMT+8, 2025-3-11 03:09 , Processed in 8.398084 second(s), 29 queries .

Powered by 智能设备

©2025

|网站地图