Spring Cloud 实战 (三) 服务网关 gateway 蔚落 2022-02-02 23:37 252阅读 0赞 在[Spring Cloud (二) 服务的注册与发现][Spring Cloud _]的基础上 创建一个名为SpringCloud-gateway的项目 在 Maven 中 添加依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-hystrix</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.RELEASE</version> <type>pom</type> <scope>import</scope> <exclusions> </exclusions> </dependency> </dependencies> </dependencyManagement> 然后修改配置文件: server: port: 8080 spring: application: name: gateway cloud: gateway: discovery: locator: enabled: true #表示是否与服务发现组件(register)进行结合,通过serviceId(必须设置成大写)转发到具体的服务实例 默认:false logging: level: org.springframework.cloud.gateway: trace org.springframework.http.server.reactive: debug org.springframework.web.reactive: debug reactor.ipc.netty: debug eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ 创建服务拦截: 新建一个类ApiGlobalFilter并继承GlobalFilter: import org.apache.commons.lang.StringUtils; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.io.buffer.DataBuffer; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @Component public class ApiGlobalFilter implements GlobalFilter { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = exchange.getRequest().getQueryParams().getFirst("token"); if (StringUtils.isBlank(token)) {//验证token值 ServerHttpResponse response = exchange.getResponse(); Map<String,Object> message = new HashMap<>(); message.put("code", 5001); message.put("message", "鉴权失败,无token值"); byte[] bits = message.toString().getBytes(StandardCharsets.UTF_8); DataBuffer buffer = response.bufferFactory().wrap(bits); response.setStatusCode(HttpStatus.UNAUTHORIZED); response.getHeaders().add("Content-Type", "text/json;charset=UTF-8"); return response.writeWith(Mono.just(buffer)); } return chain.filter(exchange); } } 然后访问[http://localhost:8080/SPRINGCLOUD-CLIENT-A/hello/index][http_localhost_8080_SPRINGCLOUD-CLIENT-A_hello_index] 效果图: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjExODI4NA_size_16_color_FFFFFF_t_70] 添加错误拦截:(友好提示) 新建一个类JsonExceptionHandler并且继承DefaultErrorWebExceptionHandler类: 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 作者 : 小布 * @version 创建时间 : 2019年5月8日 上午10:22:23 * @explain 类说明 : 自定义异常处理 返回统一的 JSON 格式 */ public class JsonExceptionHandler extends DefaultErrorWebExceptionHandler { public JsonExceptionHandler(ErrorAttributes errorAttributes, ResourceProperties resourceProperties, ErrorProperties errorProperties, ApplicationContext applicationContext) { super(errorAttributes, resourceProperties, errorProperties, applicationContext); } /** * 获取异常属性 */ @Override protected Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace) { int code = 500; Throwable error = super.getError(request); if (error instanceof org.springframework.cloud.gateway.support.NotFoundException) { code = 404; } return response(code, this.buildMessage(request, error)); } /** * 指定响应处理方法为 JSON 处理的方法 * @param errorAttributes */ @Override protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) { return RouterFunctions.route(RequestPredicates.all(), this::renderErrorResponse); } /** * 根据 code 获取对应的 HttpStatus * @param errorAttributes */ @Override protected HttpStatus getHttpStatus(Map<String, Object> errorAttributes) { int statusCode = (int) errorAttributes.get("code"); return HttpStatus.valueOf(statusCode); } /** * 构建异常信息 * @param request * @param ex * @return */ private String buildMessage(ServerRequest request, Throwable ex) { StringBuilder message = new StringBuilder("Failed to handle request ["); message.append(request.methodName()); message.append(" "); message.append(request.uri()); message.append("]"); if (ex != null) { message.append(": "); message.append(ex.getMessage()); } return message.toString(); } /** * 构建返回的 JSON 数据格式 * @param status 状态码 * @param errorMessage 异常信息 * @return */ public static Map<String, Object> response(int status, String errorMessage) { Map<String, Object> map = new HashMap<>(); map.put("code", status); map.put("message", errorMessage); return map; } } 需要添加以下配置类: import org.springframework.beans.factory.ObjectProvider; import org.springframework.boot.SpringBootConfiguration; 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.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.web.reactive.result.view.ViewResolver; import com.springcloud.exception.JsonExceptionHandler; import java.util.Collections; import java.util.List; /** * @author 作者 : 小布 * @version 创建时间 : 2019年5月8日 上午10:24:00 * @explain 类说明 : JsonExceptionHandler加载到Spring容器中的配置类 */ @SpringBootConfiguration @EnableConfigurationProperties({ServerProperties.class, ResourceProperties.class}) public class ErrorHandlerConfiguration { private final ServerProperties serverProperties; private final ApplicationContext applicationContext; private final ResourceProperties resourceProperties; private final List<ViewResolver> viewResolvers; private final ServerCodecConfigurer serverCodecConfigurer; public ErrorHandlerConfiguration(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; } /** * gateway 启动时执行此方法,将 JsonExceptionHandler 注入到 Spring 容器中 * 以便发生异常时执行自定义的 JsonExceptionHandler * @param errorAttributes * @return */ @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public ErrorWebExceptionHandler errorWebExceptionHandler(ErrorAttributes errorAttributes) { JsonExceptionHandler exceptionHandler = new JsonExceptionHandler( errorAttributes, this.resourceProperties, this.serverProperties.getError(), this.applicationContext); exceptionHandler.setViewResolvers(this.viewResolvers); exceptionHandler.setMessageWriters(this.serverCodecConfigurer.getWriters()); exceptionHandler.setMessageReaders(this.serverCodecConfigurer.getReaders()); return exceptionHandler; } } 效果图: ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjExODI4NA_size_16_color_FFFFFF_t_70 1] [上一篇 Spring Cloud 实战 (二) 服务的注册与发现][Spring Cloud _] [下一篇 Spring Cloud 实战 (四) 服务消费者 feign ][Spring Cloud _ _ _ feign] [git源码地址][git] [Spring Cloud _]: https://blog.csdn.net/weixin_42118284/article/details/89949330 [http_localhost_8080_SPRINGCLOUD-CLIENT-A_hello_index]: http://localhost:8080/SPRINGCLOUD-CLIENT-A/hello/index [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjExODI4NA_size_16_color_FFFFFF_t_70]: /images/20220203/380ffd74d37e44c9ac030319f6b925e3.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjExODI4NA_size_16_color_FFFFFF_t_70 1]: /images/20220203/29aafb2be3f34ec38ad9cf0ef75234d1.png [Spring Cloud _ _ _ feign]: https://blog.csdn.net/weixin_42118284/article/details/89949917 [git]: https://github.com/mars0520/Spring-Cloud
还没有评论,来说两句吧...