https://github.com/zq2599/blog_demos
内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;
名称 | 链接 | 备注 |
---|---|---|
项目主页 | https://github.com/zq2599/blog_demos | 该项目在GitHub上的主页 |
git仓库地址(https) | https://github.com/zq2599/blog_demos.git | 该项目源码的仓库地址,https协议 |
git仓库地址(ssh) | git@github.com:zq2599/blog_demos.git | 该项目源码的仓库地址,ssh协议 |
正式开始前需要再做一点准备工作,整个《Spring Cloud Gateway实战》系列中,所有请求最后都会被路由到provider-hello这个web上去,该服务目前只有一个web接口/hello/str,现在咱们再给它增加一个,后面的实战会用到
新增加的web接口来自LBTest.java,可见非常简单:
package com.bolingcavalry.provider.controller; import com.bolingcavalry.common.Constants; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.text.SimpleDateFormat; import java.util.Date; @RestController @RequestMapping("/lbtest") public class LBTest { private String dateStr(){ return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); } /** * 返回字符串类型 * @return */ @GetMapping("/str") public String helloStr() { return Constants.LB_PREFIX + ", " + dateStr(); } }
package com.bolingcavalry.common; public interface Constants { String HELLO_PREFIX = "Hello World"; String LB_PREFIX = "Load balance"; }
写完代码后,先确保nacos已经启动
在启动provider-hello工程,启动成功后去看nacos,确认已经注册:
玩过Spring Cloud的您自然看出了问题所在:没有注册发现,确实,这样将地址和端口写死在配置文件中是不合适的,咱们先来解决这个问题;
新增名为gateway-by-loadbalance的子工程,其pom.xml中的依赖情况如下,可见重点是spring-cloud-starter-loadbalancer:
<dependencies> <dependency> <groupId>com.bolingcavalry</groupId> <artifactId>common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 路由策略使用lb的方式是,这个依赖一定要有 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <!--nacos:注册中心--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies>
启动类的代码省去了(和前文的一样)
配置信息如下,重点是uri的值lb://provider-hello,用了前缀lb:,后面的provider-hello就是在nacos注册的服务名:
server: #服务端口 port: 8085 spring: application: name: gateway-by-loadbalance cloud: nacos: # 注册中心的配置 discovery: server-addr: 127.0.0.1:8848 gateway: routes: - id: path_route_lb uri: lb://provider-hello predicates: - Path=/lbtest/**
package com.bolingcavalry.gateway; import com.bolingcavalry.common.Constants; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.reactive.server.WebTestClient; import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest @ExtendWith(SpringExtension.class) @AutoConfigureWebTestClient public class HelloTest { @Autowired private WebTestClient webClient; @Test void testLoadBalance() { webClient.get() .uri("/lbtest/str") .accept(MediaType.APPLICATION_JSON) .exchange() // 验证状态 .expectStatus().isOk() // 验证结果,注意结果是字符串格式 .expectBody(String.class).consumeWith(result -> assertTrue(result.getResponseBody().contains(Constants.LB_PREFIX))); } }
将所有配置信息写在application.yml中有个问题:不能远程配置,这在应用数量较多的场景就不方便了,好在nacos提供了远程配置的能力,应用启动后可以从nacos取得自己的配置信息,咱们来试试
新增名为gateway-nacos-config的子工程,其pom.xml中的依赖情况如下,请注意里面的中文注释,每指明了每一个依赖的作用:
<dependencies> <dependency> <groupId>com.bolingcavalry</groupId> <artifactId>common</artifactId> <version>${project.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>io.projectreactor</groupId> <artifactId>reactor-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 使用bootstrap.yml的时候,这个依赖一定要有 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-bootstrap</artifactId> </dependency> <!-- 路由策略使用lb的方式是,这个依赖一定要有 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-loadbalancer</artifactId> </dependency> <!--nacos:配置中心--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <!--nacos:注册中心--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> </dependencies>
spring: application: name: gateway-nacos-config cloud: nacos: config: server-addr: 127.0.0.1:8848 file-extension: yml group: DEFAULT_GROUP
server: port: 8083 spring: cloud: gateway: routes: - id: path_route_addr uri: http://127.0.0.1:8082 predicates: - Path=/hello/** - id: path_route_lb uri: lb://provider-hello predicates: - Path=/lbtest/**
@Test void testHelloPredicates() { webClient.get() .uri("/hello/str") .accept(MediaType.APPLICATION_JSON) .exchange() // 验证状态 .expectStatus().isOk() // 验证结果,注意结果是字符串格式 .expectBody(String.class).consumeWith(result -> assertTrue(result.getResponseBody().contains(Constants.HELLO_PREFIX))); } @Test void testLoadBalance() { webClient.get() .uri("/lbtest/str") .accept(MediaType.APPLICATION_JSON) .exchange() // 验证状态 .expectStatus().isOk() // 验证结果,注意结果是字符串格式 .expectBody(String.class).consumeWith(result -> assertTrue(result.getResponseBody().contains(Constants.LB_PREFIX))); }
前面的几个例子,路由信息都是写在配置文件中的,其实还有一种方式:写代码配置路由,能自己写代码来配置,这灵活性就更强了
新增名为gateway-by-code的子工程,其pom.xml文件参照前面工程的即可
接下来的本例的重点,在配置类中增加一个RouteLocator类型的bean,通过以下代码即可增加一个路由:
package com.bolingcavalry.gateway.cofig; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RouteConfig { @Bean public RouteLocator customizeRoute(RouteLocatorBuilder builder) { return builder .routes() .route( // 第一个参数是路由的唯一身份 "path_route_lb", // 第二个参数是个lambda实现, // 设置了配套条件是按照请求路径匹配,以及转发地址, // 注意lb://表示这是个服务名,要从 r -> r.path("/lbtest/**").uri("lb://provider-hello") ) .build(); } }
server: #服务端口 port: 8084 spring: application: name: gateway-by-code cloud: nacos: discovery: # nacos服务地址 server-addr: 127.0.0.1:8848 gateway: routes: - id: path_route_addr uri: http://127.0.0.1:8082 predicates: - Path=/hello/**
测试类和之前工程的一模一样,就不占用篇幅了,依旧是两个测试方法testHelloPredicates和testLoadBalance
执行单元测试可以顺利通过,证明代码配置路由没有问题:
我是欣宸,期待与您一同畅游Java世界…
https://github.com/zq2599/blog_demos