spring cloud Gateway 学习
2020-04-13 本文已影响0人
_大叔_
学习第一步先看官网介绍,了解个大概也行啊 官网地址
一、起飞
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
</dependencies>
注意spring boot 和 spring cloud 版本必须一致,否则会有如下报错:
java.lang.NoSuchMethodError: reactor.netty.http.client.HttpClient.chunkedTransfer(Z)Lreactor/netty/http/client/HttpClient;
版本对应查看这里 https://github.com/spring-projects/spring-cloud/wiki
二、配置文件
spring:
application:
name: gateway
cloud:
gateway:
routes: #路由
# 当前路由转发的标识,默认式uuid,一般自定义
- id: user_router
# 请求最终转发的地址
uri: http://localhost:8900
# 路由的优先级,数字越小优先级越高
order: 1
# 断言(条件判断,返回值为boolean,代表转发请求要满足的条件)
predicates:
# 当请求路径满足Path指定的规则,才会转发
- Path=/user-server/**
# 过滤器 请求传递过程中,对请求进行做一些手脚
filters:
# 在请求转发之前 去掉 predicates 里的 Path 指定路径 如 /user/** 去掉 /user
- StripPrefix=1
predicates 规则有很多种,我现在这种式根据路径匹配,比如如下,是根据时间段来限定请求
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
而 filter 也很简单了,也就是在请求的时候我们可以添加一些东西,或者去掉一些东西,而我写的 - StripPrefix=1 意思就是把 predicates 匹配的 user-server 在转发前去掉,否则我们正常请求是 localhost:8080/user/addUser,实际就变成 localhost:8080/user-server/user/addUser 这样就会404.
三、全局 filter 实现
@Configuration
public class CustomizeGlobalFilter {
@Resource
private NacosDiscoveryProperties nacosDiscoveryProperties;
@Bean
public NacosNamingService nacosNamingService() {
return new NacosNamingService(nacosDiscoveryProperties.getServerAddr());
}
@Bean
public GlobalFilter tokenFilter() {
return new TokenFilter();
}
}
@Slf4j
public class TokenFilter implements GlobalFilter, Ordered {
@Resource
NacosNamingService nacosNamingService;
@Override
@SuppressWarnings("Duplicates")
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.debug("test");
return chain.filter(exchange);
}
@Override
public int getOrder() {
return -1;
}
}
四、全局异常
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.reactive.error.DefaultErrorWebExceptionHandler;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.context.ApplicationContext;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.server.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author big uncle
* @date 2020/12/14 15:09
* @module
**/
public class CustomizeErrorHandler extends DefaultErrorWebExceptionHandler {
public CustomizeErrorHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) {
super(errorAttributes, resourceProperties, errorProperties, applicationContext);
}
@Override
protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) {
// 这里其实可以根据异常类型进行定制化逻辑
Throwable error = super.getError(request);
Map<String, Object> errorAttributes = new HashMap<>(3);
errorAttributes.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
errorAttributes.put("msg", "path = "+ request.path() +"; method = "+request.methodName()+ "; msg = " + error.getMessage());
errorAttributes.put("data", "");
return errorAttributes;
}
@Override
protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse);
}
@Override
protected int getHttpStatus(Map<String, Object> errorAttributes) {
return (Integer)errorAttributes.get("code");
}
}
import com.giant.cloud.error.CustomizeErrorHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.web.ResourceProperties;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.reactive.error.ErrorAttributes;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;
import java.util.Collections;
import java.util.List;
/**
* @author big uncle
* @date 2020/12/14 15:25
* @module
**/
@Configuration
@EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class})
public class ErrorConfig {
private final ServerProperties serverProperties;
private final ApplicationContext applicationContext;
private final ResourceProperties resourceProperties;
private final List<ViewResolver> viewResolvers;
private final ServerCodecConfigurer serverCodecConfigurer;
public ErrorConfig(ServerProperties serverProperties,
ResourceProperties resourceProperties,
ObjectProvider<List<ViewResolver>> viewResolversProvider,
ServerCodecConfigurer serverCodecConfigurer,
ApplicationContext applicationContext) {
this.serverProperties = serverProperties;
this.applicationContext = applicationContext;
this.resourceProperties = resourceProperties;
this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
this.serverCodecConfigurer = serverCodecConfigurer;
}
@Bean
@Order(Ordered.HIGHEST_PRECEDENCE)
public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) {
CustomizeErrorHandler exceptionHandler = new CustomizeErrorHandler(
errorAttributes,
this.resourceProperties,
this.serverProperties.getError(),
this.applicationContext);
exceptionHandler.setViewResolvers(this.viewResolvers);
exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters());
exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders());
return exceptionHandler;
}
}