GateWay具体的使用!!!

ops/2024/10/19 7:35:19/

一、全局Token过滤器

在Spring Cloud Gateway中,实现全局过滤器的目的是对所有进入系统的请求或响应进行统一处理,比如添加日志、鉴权等。下面是如何创建一个全局过滤器的基本步骤:

步骤1: 创建过滤器类

首先,你需要创建一个实现了GatewayFilter接口或者继承AbstractGatewayFilterFactory类的过滤器类。这里以实现GatewayFilter接口为例,创建一个全局token过滤器。

/** Copyright (c) 2020, 2024,  All rights reserved.**/
package com.by.filter;import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.jwt.JWTValidator;
import cn.hutool.jwt.signers.JWTSignerUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
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.util.List;/*** <p>Project: spring-could-alibaba-root - TokenFilter</p>* <p>Powered by scl On 2024-04-26 17:41:24</p>* <p>描述:<p>** @author 孙臣龙 [1846080280@qq.com]* @version 1.0* @since 17*/
@Component
@Slf4j
public class TokenFilter implements GlobalFilter {@Value("${cn.smart.tokenx.key}")private String key;//设置白名单private static List<String> whiteList = CollUtil.newArrayList("/api/user/login", "/api/user/register");@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();ServerHttpResponse response = exchange.getResponse();//判断如果包含白名单中的内容就放行RequestPath path = request.getPath();if (whiteList.contains(path)) {return chain.filter(exchange);}//从请求头中获取tokenList<String> tokens = request.getHeaders().get("token");if (ObjUtil.isEmpty(tokens)) {//设置状态码log.debug("token为空");response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//获取tokenString token = tokens.get(0);if (ObjUtil.isEmpty(token)) {log.debug("token为空");response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}//全面增强Boolean b = false;try {JWTValidator.of(token).validateAlgorithm(JWTSignerUtil.hs256(key.getBytes())).validateDate();b = true;} catch (Exception e) {e.printStackTrace();}if (!b) {log.debug("token无效");response.setStatusCode(HttpStatus.UNAUTHORIZED);return response.setComplete();}return chain.filter(exchange);}
}

步骤2: 注册全局过滤器

为了让Spring Cloud Gateway应用识别并使用这个过滤器,你通常需要在配置类中注册它。但是,由于我们使用了@Component注解,Spring会自动扫描并注册该Bean。

使用@Component或下面代码,二选一。

@Configuration
public class FilterConfig {@Beanpublic TokenFilter tokenFilter() {return new TokenFilter();}
}

二、局部过滤器接口耗时

1.找规律

局部过滤器命名规则 XXXGatewayFilterFactory, 必须以GatewayFilterFactory结尾。

/*  注意名称约定
*   AddRequestHeaderGatewayFilterFactory    配置的时候写的是 AddRequestHeader
*   AddRequestParameterGatewayFilterFactory 配置的时候写的是 AddRequestParameter
*   LogTimeGatewayFilterFactory   配置的时候写什么? LogTime
* */spring.cloud.gateway.routes[0].filters[0] = LogTime=moreThen,500

2.接口耗时过滤器

/** Copyright (c) 2020, 2024,  All rights reserved.**/
package com.by.filter;import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractNameValueGatewayFilterFactory;
import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory;
import org.springframework.cloud.gateway.support.GatewayToStringStyler;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;/*** <p>Project: spring-could-alibaba-root - LogTimeGatewayFilterFactory</p>* <p>Powered by scl On 2024-04-26 20:01:04</p>* <p>描述:<p>** @author 孙臣龙 [1846080280@qq.com]* @version 1.0* @since 17*/
@Component
@Slf4j
//局部过滤器命名规则 XXXGatewayFilterFactory, 必须以GatewayFilterFactory结尾。还需要配置文件中进行配置
public class LogTimeGatewayFilterFactory extends AbstractNameValueGatewayFilterFactory {public LogTimeGatewayFilterFactory() {}public GatewayFilter apply(final AbstractNameValueGatewayFilterFactory.NameValueConfig config) {return new GatewayFilter() {public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();//获取配置文件中设置的参数String value = ServerWebExchangeUtils.expand(exchange, config.getValue());//将参数转换为int类型Integer time = Integer.valueOf(value);//设置开始时间long startTime = System.currentTimeMillis();//执行过滤器,并且记录请求耗时,通过调用then方法(类似于vue的then方法),记录请求耗时return chain.filter(exchange).then(Mono.fromRunnable(() -> {long endTime = System.currentTimeMillis();long costTime = endTime - startTime;if (costTime  > time*1000) {log.debug("请求地址:" + request.getPath() + ",请求耗时:" + costTime + "ms");}}));}public String toString() {return GatewayToStringStyler.filterToStringCreator(LogTimeGatewayFilterFactory.this).append(config.getName(), config.getValue()).toString();}};}
}

3.如何使用

三、全链路跟踪TraceId日志

1.创建全局过滤器,在请求头上带入traceId参数,穿透到下游服务.

/** Copyright (c) 2020, 2024,  All rights reserved.**/
package com.by.filter;import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.List;/*** <p>Project: spring-could-alibaba-root - TraceIdFilter</p>* <p>Powered by scl On 2024-04-26 21:10:19</p>* <p>描述:<p>** @author 孙臣龙 [1846080280@qq.com]* @version 1.0* @since 17*/
@Component
public class TraceIdFilter implements GlobalFilter {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {//获取请求头ServerHttpRequest request = exchange.getRequest();//判断请求头中有没有traceIdList<String> list = request.getHeaders().get("traceId");//如果存在就不做处理if (ObjectUtil.isNotEmpty(list)){return chain.filter(exchange);}//不存在就生成一个traceIdString treaId= IdUtil.simpleUUID();//在请求头中添加一个traceIdServerHttpRequest request1 = request.mutate().header("tracedId", treaId).build();//因为请求头发生了变化,所以需要重新构建一个ServerWebExchangeServerWebExchange exchange1 = exchange.mutate().request(request1).build();return chain.filter(exchange1);}
}

2.MDC原理

当请求来时生成一个traceId放在ThreadLocal里,然后打印时去取就行了。但在不改动原有输出语句的前提下自然需要日志框架的支持了。

MDC 介绍​ MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。MDC 可以看成是一个与当前线程绑定的Map,可以往其中添加键值对。MDC 中包含的内容可以被同一线程中执行的代码所访问。当前线程的子线程会继承其父线程中的 MDC 的内容。当需要记录日志时,只需要从 MDC 中获取所需的信息即可。MDC 的内容则由程序在适当的时候保存进去。对于一个 Web 应用来说,通常是在请求被处理的最开始保存这些数据。

简而言之,MDC就是日志框架提供的一个InheritableThreadLocal,项目代码中可以将键值对放入其中,然后使用指定方式取出打印即可。

3.下游服务如何使用全链路跟踪Id

3.1在你要跟踪的模块中配置TraceId 过滤器

/** Copyright (c) 2020, 2024,  All rights reserved.**/
package com.by.filter;import cn.hutool.core.util.IdUtil;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/*** <p>Project: spring-could-alibaba-root - TraceIdFliter</p>* <p>Powered by scl On 2024-04-26 21:20:15</p>* <p>描述:<p>** @author 孙臣龙 [1846080280@qq.com]* @version 1.0* @since 17*/
@WebFilter
public class TraceIdFliter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) request;String traceId = httpRequest.getHeader("traceId");if (StringUtils.isEmpty(traceId)) {traceId = IdUtil.fastSimpleUUID();}MDC.put("traceId", traceId);try {chain.doFilter(request, response);} finally {MDC.clear();}}
}

3.2 启动类开启ServletComponentScan扫描。

@SpringBootApplication@ServletComponentScan
public class OpenApp {public static void main(String[] args) {SpringApplication.run(OpenApp.class, args);}}

3.3 配置文件配置日志输出格式

##日志输出格式
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss.SSS} %clr(%-5level) %clr([%X{traceId}]) %clr(${PID:-}) --- %clr(%logger{50}) - %m%n


4.Openfeign扩展

@Component
public class OpenFeignRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {String traceId = MDC.get(TraceIdFilter.MDC_TRACE_ID);requestTemplate.header(TraceIdFilter.MDC_TRACE_ID, traceId);}
}


5.附(Kibana日志图标)




http://www.ppmy.cn/ops/25314.html

相关文章

华为静音模式指定联系人来电响铃

华为静音模式指定联系人来电响铃 本人7年水果转华为&#xff0c;手机常年静音但是还是想收到指定人来电的。水果这个地方做的是很方便的&#xff0c;直接添加紧急联系人&#xff0c;什么声音都没有&#xff0c;只有指定人的电话铃声 直接上结论&#xff0c;华为是不支持直接这样…

论文阅读_股票预测强化学习_StockFormer

1 StockFormer PLAINTEXT 1 2 3 4 5 6 7中文名称&#xff1a;StockFormer: 混合交易机与预测编码 英文名称&#xff1a;StockFormer: Learning Hybrid Trading Machines with Predictive Coding 作者&#xff1a;Siyu Gao, Yunbo Wang∗, and Xiaokang Yang 机构&#xff1a;M…

牛客NC143 矩阵乘法【中等 矩阵 C++/Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/bf358c3ac73e491585943bac94e309b0 思路 矩阵算法在图像处理、神经网络、模式识别等领域有着广泛的用途。在矩阵乘法中&#xff0c;A矩阵和B矩阵可以做乘法运算必须满足A矩阵的列的数量等于B矩阵的行的数量。运算…

数位dp练习

[SCOI2009] windy 数 题目背景 windy 定义了一种 windy 数。 题目描述 不含前导零且相邻两个数字之差至少为 2 2 2 的正整数被称为 windy 数。windy 想知道&#xff0c;在 a a a 和 b b b 之间&#xff0c;包括 a a a 和 b b b &#xff0c;总共有多少个 windy 数&…

linux驱动-CCF-1 provider 注册时钟

CCF: common clock frameword provider 注册时钟分析 1. 待注册 时钟数据 #define _REGISTER(f, s, ...) { .clk_register (bcm2835_clk_register)f, \.supported s, \.data __VA_ARGS__ } #define REGISTER_CLK(s, ...) _REGISTER(&bcm2835_register_clock, \s, …

Redis(七) zset有序集合类型

文章目录 前言命令ZADDZCARDZCOUNTZRANGEZREVRANGEZRANGEBYSCOREZPOPMAXZPOPMIN两个阻塞版本的POP命令BZPOPMAX BZPOPMINZRANKZREVRANKZSCOREZREMZREMRANGEBYRANKZREMRANGEBYSCOREZINCRBY集合间操作ZINTERSTOREZUNIONSTORE 命令小结 内部编码使用场景 前言 对于有序集合这个名…

Big Data 平障录

Hive Hive 生成带压缩的格式&#xff0c;需要如此设置 SET parquet.compressionSNAPPY;yarn.scheduler.fair.assignmultiple 相关jira&#xff1a;https://issues.apache.org/jira/browse/YARN-5035 yarn.scheduler.fair.assignmultiple是YARN Fair Scheduler的一个配置参数…

vue 配合 video.js 实现视频播放

1. 导入 video.js 包 npm install video.js -S npm install videojs-flash -S 2. 代码实现 <template><div><videoid"my-video"class"video-js"controlspreload"auto"width"640"height"264":poster&quo…