创建一个工程名为 spring-cloud-alibaba-dependencies
的项目,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><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.1.8.RELEASE</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.chanshiyu</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>1.0.0-SNAPSHOT</version><packaging>pom</packaging><name>spring-cloud-alibaba-dependencies</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!-- Spring Settings --><spring-cloud.version>Greenwich.SR2</spring-cloud.version><spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.SR2</version><type>${spring-cloud.version}</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></dependencies></dependencyManagement><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.chanshiyu.nacosprovider.NacosProviderApplication</mainClass></configuration></plugin></plugins></build></project>
服务注册与发现使用 Nacas,直接启动即可。
Nacos 官网
创建一个工程名为 spring-cloud-alibaba-nacos-provider
的项目,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><parent><groupId>com.chanshiyu</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../spring-cloud-alibaba-dependencies/pom.xml</relativePath></parent><artifactId>spring-cloud-alibaba-nacos-provider</artifactId><version>1.0.0-SNAPSHOT</version><name>spring-cloud-alibaba-nacos-provider</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.chanshiyu.nacosprovider.NacosProviderApplication</mainClass></configuration></plugin></plugins></build></project>
通过 @EnableDiscoveryClient
注解表明是一个 Nacos 客户端,该注解是 Spring Cloud 提供的原生注解。
@SpringBootApplication@EnableDiscoveryClientpublic class NacosProviderApplication {public static void main(String[] args) {SpringApplication.run(NacosProviderApplication.class, args);}}
spring:application:name: nacos-providercloud:nacos:discovery:server-addr: 127.0.0.1:8848server:port: 8081management:endpoints:web:exposure:include: '*'
@RestControllerpublic class NacosProviderController {@Value("${server.port}")private String port;@GetMapping("/echo/{message}")public String echo(@PathVariable String message) {return String.format("Your message is %s and port is %s", message, port);}}
使用 LoadBalanceClient
和 RestTemplate
结合的方式来访问。创建一个工程名为 spring-cloud-alibaba-nacos-consumer
的项目,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><parent><groupId>com.chanshiyu</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../spring-cloud-alibaba-dependencies/pom.xml</relativePath></parent><artifactId>spring-cloud-alibaba-nacos-consumer</artifactId><version>1.0.0-SNAPSHOT</version><name>spring-cloud-alibaba-nacos-consumer</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.chanshiyu.nacosconsumer.NacosConsumerApplication</mainClass></configuration></plugin></plugins></build></project>
@SpringBootApplication@EnableDiscoveryClientpublic class NacosConsumerApplication {public static void main(String[] args) {SpringApplication.run(NacosConsumerApplication.class, args);}}
spring:application:name: nacos-consumercloud:nacos:discovery:server-addr: 127.0.0.1:8848server:port: 9091management:endpoints:web:exposure:include: '*'
@Configurationpublic class NacosConsumerConfiguration {@Beanpublic RestTemplate restTemplate() {return new RestTemplate();}}
@RestControllerpublic class NacosConsumerController {@Autowiredprivate LoadBalancerClient loadBalancerClient;@Autowiredprivate RestTemplate restTemplate;@Value("${spring.application.name}")private String appName;@GetMapping("/echo/app/name")public String echo() {// 使用 LoadBalanceClient 和 RestTemolate 结合的方式来访问ServiceInstance serviceInstance = loadBalancerClient.choose("nacos-provider");String url = String.format("http://%s:%s/echo/%s", serviceInstance.getHost(), serviceInstance.getPort(), appName);return restTemplate.getForObject(url, String.class);}}
创建一个工程名为 spring-cloud-alibaba-nacos-consumer-feign
的项目,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><parent><groupId>com.chanshiyu</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../spring-cloud-alibaba-dependencies/pom.xml</relativePath></parent><artifactId>spring-cloud-alibaba-nacos-consumer-feign</artifactId><version>1.0.0-SNAPSHOT</version><name>spring-cloud-alibaba-nacos-consumer-feign</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><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-openfeign</artifactId><version>RELEASE</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>RELEASE</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.chanshiyu.nacosconsumerfeign.NacosConsumerFeignApplication</mainClass></configuration></plugin></plugins></build></project>
通过 @EnableFeignClients
注解开启 Feign 功能:
@SpringBootApplication@EnableDiscoveryClient@EnableFeignClientspublic class NacosConsumerFeignApplication {public static void main(String[] args) {SpringApplication.run(NacosConsumerFeignApplication.class, args);}}
spring:application:name: nacos-consumer-feigncloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:port: 8720dashboard: localhost:8080server:port: 9092feign:sentinel:enabled: truemanagement:endpoints:web:exposure:include: '*'
创建 Service:
@FeignClient(value = "nacos-provider")public interface NacosProviderService {@GetMapping("/echo/{message}")public String echo(@PathVariable String message);}
创建 Controller:
@RestControllerpublic class NacosProviderController {@Autowiredprivate NacosProviderService nacosProviderService;@GetMapping("/echo/{message}")public String echo(@PathVariable String message) {return nacosProviderService.echo(message);}}
阿里巴巴开源了 Sentinel 组件,实现了熔断器模式,Spring Cloud 对这一组件进行了整合。
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency>
feign:sentinel:enabled: true
@Componentpublic class NacosProviderFallback implements NacosProviderService {@Overridepublic String echo(String message) {return "请求失败!";}}
@FeignClient(value = "nacos-provider", fallback = NacosProviderFallback.class)public interface NacosProviderService {@GetMapping("/echo/{message}")public String echo(@PathVariable String message);}
启动 sentinel
控制台。修改 application.yml
,添加 sentinel
配置:
spring:application:name: nacos-consumer-feigncloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:port: 8720dashboard: localhost:8080
创建一个工程名为 spring-cloud-alibaba-nacos-gateway
的项目,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><parent><groupId>com.chanshiyu</groupId><artifactId>spring-cloud-alibaba-dependencies</artifactId><version>1.0.0-SNAPSHOT</version><relativePath>../spring-cloud-alibaba-dependencies/pom.xml</relativePath></parent><artifactId>spring-cloud-alibaba-gateway</artifactId><version>1.0.0-SNAPSHOT</version><name>spring-cloud-alibaba-gateway</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency><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-openfeign</artifactId><version>RELEASE</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>RELEASE</version></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId><version>RELEASE</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><mainClass>com.chanshiyu.gateway.GatewayApplication</mainClass></configuration></plugin></plugins></build></project>
需要注意:
Spring Cloud Gateway 不使用 Web
作为服务器,而是 使用 WebFlux
作为服务器,Gateway 项目已经依赖了 starter-webflux
,所以这里 千万不要依赖 starter-web
由于过滤器等功能依然需要 Servlet 支持,故这里还需要依赖 javax.servlet:javax.servlet-api
@SpringBootApplication@EnableDiscoveryClient@EnableFeignClientspublic class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}}
spring:application:name: spring-gatewaycloud:# 使用 Naoos 作为服务注册发现nacos:discovery:server-addr: 127.0.0.1:8848# 使用 Sentinel 作为熔断器sentinel:transport:port: 8721dashboard: localhost:8080# 路由网关配置gateway:# 设置与服务注册发现组件结合,这样可以采用服务名的路由策略discovery:locator:enabled: true# 配置路由规则routes:# 采用自定义路由 ID(有固定用法,不同的 id 有不同的功能,详见:https://cloud.spring.io/spring-cloud-gateway/2.0.x/single/spring-cloud-gateway.html#gateway-route-filters)- id: NACOS-CONSUMER# 采用 LoadBalanceClient 方式请求,以 lb:// 开头,后面的是注册在 Nacos 上的服务名uri: lb://nacos-consumer# Predicate 翻译过来是“谓词”的意思,必须,主要作用是匹配用户的请求,有很多种用法predicates:# Method 方法谓词,这里是匹配 GET 和 POST 请求- Method=GET,POST- id: NACOS-CONSUMER-FEIGNuri: lb://nacos-consumer-feignpredicates:- Method=GET,POSTserver:port: 9000feign:sentinel:enabled: truemanagement:endpoints:web:exposure:include: '*'logging:level:org.springframework.cloud.gateway: debug
@Componentpublic class AuthFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {String token = exchange.getRequest().getQueryParams().getFirst("token");if (token == null || token.isEmpty()) {ServerHttpResponse response = exchange.getResponse();// 封装错误信息Map<String, Object> responseData = Maps.newHashMap();responseData.put("code", 401);responseData.put("message", "非法请求");responseData.put("cause", "Token is empty");try {// 将信息转换为 JSONObjectMapper objectMapper = new ObjectMapper();byte[] data = objectMapper.writeValueAsBytes(responseData);// 输出错误信息到页面DataBuffer buffer = response.bufferFactory().wrap(data);response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");return response.writeWith(Mono.just(buffer));} catch (JsonProcessingException e) {e.printStackTrace();}}// 传递给下一个过滤器return chain.filter(exchange);}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE;}}