GateWay具体的使用!!!

embedded/2024/9/23 9:36:43/

一、全局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/embedded/25514.html

相关文章

记录一些容易遗忘的东西

文章目录 native、sync 修饰符this.$nextTick native、sync 修饰符 native &#xff1a;在对子组件使用 click 的时候若不使用该修饰符&#xff0c;那么就不能执行点击事件&#xff0c;会被判断为子向父组件传的值sync &#xff1a; 类似于 v-model 的响应式修饰符&#xff0c…

day06 51单片机-点阵led

1 点阵LED 1.1 需求描述 本案例介绍如何使用点阵LED显示一排由左上到右下的斜线。 1.2 硬件设计 1.2.1 硬件原理图 点阵内部的原理图: 点阵LED的原理也非常简单,就是LED点灯。例如,我们想要让13列(阳极端)9行(阴极端)的LED点亮,需要13为高电平,9为低电平。注意对于…

【架构】后端项目如何分层及分层领域模型简化

文章目录 一. 如何分层1. 阿里规范2. 具体案例分析 二. 分层领域模型的转换1. 阿里规范2. 模型种类简化分析 三. 小结 本文描述后端项目中如何进行分层&#xff0c;以及分层领域模型简化 一. 如何分层 1. 阿里规范 阿里的编码规范中约束分层逻辑如下: 开放接口层&#xff1a…

Linux下基于Electron的ZeroTier客户端GUI

Linux下基于Electron的ZeroTier客户端GUI 起因 在使用Zerotier组网的时候&#xff0c;我发现官方客户端GUI只有Windows版本和MacOS版本的&#xff0c;在Linux下加入网络等操作依然要靠命令实现&#xff0c;因此我干脆自己动手写了个GUI&#xff0c;其原理还是通过调用命令实现…

vue的v-model、v-if、v-for用react语法实现

在React中&#xff0c;没有直接对应于Vue中的v-model、v-if和v-for的指令&#xff0c;但你可以使用React的特性和组件来实现类似的功能。 1. v-model 在Vue中&#xff0c;v-model用于在表单元素和组件之间创建双向数据绑定。在React中&#xff0c;你可以使用受控组件&#xf…

Java使用SpringBoot和EasyExcel 实现动态数据导出实战

Java使用SpringBoot和EasyExcel 实现动态数据导出实战 1、前言2、【资源地址】3、代码示例(demo)4、目前Java实现数据导出为Excel方式5、依赖6、总结 1、前言 工作中有用到将数据导出为Excel的场景&#xff0c;在此记录下。在日常开发中&#xff0c;Excel文件处理是一项常见的…

深度学习之基于YOLOv5的山羊行为识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 基于YOLOv5的山羊行为识别系统是一个结合了深度学习和目标检测技术的项目&#xff0c;旨在通过图像或视频实现对山羊…

【Diffusion实战】训练一个diffusion模型生成蝴蝶图像(Pytorch代码详解)

上一篇Diffusion实战是确确实实一步一步走的公式&#xff0c;这回采用一个更方便的库&#xff1a;diffusers&#xff0c;来实现Diffusion模型训练。 Diffusion实战篇&#xff1a;   【Diffusion实战】训练一个diffusion模型生成S曲线&#xff08;Pytorch代码详解&#xff09;…