当前位置: 首页 > news >正文

手动搭建gateway,项目集成gateway实现Token效果

目录

  • 背景
  • 步骤
    • 1、首先创建springboot项目
    • 2、引入依赖
    • 3、配置文件!!!!!(超级重要!!!根据自己的需要进行配置)
    • 4、相关类
    • 我们在服务中进行的白名单中接口的操作如下
  • 测试
    • 存:
    • 拿:
  • 总结

背景

现在想要进行token校验,故引入gateway服务。
首先阅读官网,知道概念:Gateway官网详解

步骤

1、首先创建springboot项目

看整体的目录结构
在这里插入图片描述

2、引入依赖

 <dependencies><!--gateway的依赖--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId></dependency><!--nacos注册与发现--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId></dependency><!--nacos配置中心来做配置管理--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId></dependency><dependency><groupId>com.tfjybj</groupId><artifactId>fewCode-common-redis</artifactId><version>1.0-SNAPSHOT</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId></dependency></dependencies>

3、配置文件!!!!!(超级重要!!!根据自己的需要进行配置)

server:port: 8088servlet:context-path: /apispring:cloud:gateway:discovery:locator:enabled: trueroutes:- id: login_routeuri: lb://fewCode-provider-login#uri: http://localhost:8001/predicates:- Path=/login/**,/Curriculum/**,/classes/**filters:- RewritePath=/(?<segment>.*),/$\{segment}
leyou:filter:  #需要进行过滤的白名单allowPaths:- /login/checkLogin- /login/user- /login/userLogin- /upload/filetokenExpire: 1440

这份配置是用于Spring Cloud Gateway的配置文件,用于构建API网关。让我来解释一下每个部分的含义:

服务器配置:

服务器监听端口为8088。
Servlet的上下文路径设置为"/api",意味着所有API的端点都将具有这个前缀。
Spring Cloud Gateway配置:

服务发现定位器:启用,这意味着网关将使用服务发现来查找后端服务的路由。在动态的微服务环境中非常有用。
路由:路由配置指定了网关如何将传入的请求路由到后端服务。在这里,定义了一个路由:
id: login_route - 这是该路由的唯一标识符。
uri: lb://fewCode-provider-login - 后端服务的URI,用于处理具有负载均衡器(lb)的请求。服务名为"fewCode-provider-login",网关将使用服务发现来定位该服务。
predicates: 定义了应用此路由的条件。在这里,该路由将用于以"/login/“、”/Curriculum/“或”/classes/"开头的路径的请求。
filters: 对请求应用的过滤器,在将其转发到后端服务之前。在这里,使用了一个RewritePath过滤器,用于删除路径末尾的斜杠。
自定义配置:

leyou:这似乎是一些与"leyou"相关的自定义配置,用于特定的过滤逻辑。
filter:这是一个允许白名单路径的配置。
allowPaths:列出的路径将无需任何额外过滤而被允许。这些路径的请求不会受到任何额外的检查。
tokenExpire:设置令牌过期的时间限制(以分钟为单位),这里设置为1440分钟(24小时)。
总体而言,这份配置将Spring Cloud Gateway配置成将传入的请求路由到名为"fewCode-provider-login"的后端服务,前提是请求路径以"/login/“、”/Curriculum/“或”/classes/"开头。同时,它提供了一个白名单,允许无需任何额外过滤的路径。

4、相关类

package com.tfjybj.gateway.config;import com.tfjybj.gateway.filter.AuthorizeFilter;
import com.tfjybj.gateway.filter.RenewFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class FilterConfig {@Beanpublic AuthorizeFilter authGatewayFilter() {//配置拦截器参数//order:序号,设置拦截器执行顺序,AuthGatewayFilter为1return new AuthorizeFilter(0);}@Beanpublic RenewFilter renewFilter(){// 续约Tokenreturn new RenewFilter(5);}}
package com.tfjybj.gateway.config;import com.tfjybj.gateway.util.FilterProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** 请求白名单**/
@Component
public class IgnorePath {@Autowiredprivate FilterProperties filterProperties;public boolean isAllowPath(String path) {//遍历白名单for (String allowPath : filterProperties.getAllowPaths()) {//判断是否允许if(path.startsWith(allowPath)){return true;}}return  false;}}
package com.tfjybj.gateway.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;@Configuration
public class LapCorsConfiguration {@Beanpublic CorsWebFilter corsWebFilter(){UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();CorsConfiguration corsConfiguration = new CorsConfiguration();//1、配置跨域corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");corsConfiguration.addAllowedOrigin("*");corsConfiguration.setAllowCredentials(true);source.registerCorsConfiguration("/**",corsConfiguration);return new CorsWebFilter(source);}
}
package com.tfjybj.gateway.filter;import com.alibaba.fastjson.JSON;import com.tfjybj.gateway.config.IgnorePath;
import com.tfjybj.gateway.result.ResultMsgEnum;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.HashMap;public class AuthorizeFilter implements GlobalFilter, Ordered {private static final Logger log = LogManager.getLogger();@Autowiredprivate StringRedisTemplate redisTemplate;@Autowiredprivate IgnorePath ignorePath;private final int order;public AuthorizeFilter(int order) {this.order = order;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();//获取请求的url路径String path = request.getURI().getPath();boolean flag=ignorePath.isAllowPath(path);if (flag) {log.info("请求在白名单中,metaverse.filter: {}",path);return chain.filter(exchange);} else {//获取token值String authorization = headers.getFirst("Authorization");log.info("Authorization值{}", authorization);authorization = authorization.split("Bearer ")[1];//判断redis中是否有tokenBoolean aBoolean = redisTemplate.hasKey("fewCode:userinfo:" + authorization);if (aBoolean){return chain.filter(exchange);}else {//声明变量ServerHttpResponse response = exchange.getResponse();HashMap map = new HashMap();String resp;DataBuffer bodyDataBuffer;//设置响应头response.setStatusCode(HttpStatus.FORBIDDEN);map.put("code", "403");map.put("message", ResultMsgEnum.AUTH_FAILED.getMsg());resp = JSON.toJSONString(map);bodyDataBuffer = response.bufferFactory().wrap(resp.getBytes());response.getHeaders().add("Content-Type","application/json;charset=UTF-8");return response.writeWith(Mono.just(bodyDataBuffer));}}}@Overridepublic int getOrder() {return this.order;}}
package com.tfjybj.gateway.filter;import com.tfjybj.gateway.config.IgnorePath;
import com.tfjybj.gateway.util.FilterProperties;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;import java.util.concurrent.TimeUnit;/*** token续约的逻辑**/
public class RenewFilter implements GlobalFilter, Ordered {private static final Logger log = LogManager.getLogger();private final int order;@Autowiredprivate StringRedisTemplate stringRedisTemplate;public RenewFilter(int order) {this.order = order;}@Autowiredprivate IgnorePath ignorePath;@Autowiredprivate FilterProperties filterProperties;@Overridepublic int getOrder() {return this.order;}@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {ServerHttpRequest request = exchange.getRequest();HttpHeaders headers = request.getHeaders();//获取请求的url路径String path = request.getURI().getPath();boolean flag=ignorePath.isAllowPath(path);if (flag) {log.info("请求在白名单中,metaverse.filter: {}", path);return chain.filter(exchange);}//token值String authorization = headers.getFirst("Authorization");authorization = authorization.split("Bearer ")[1];log.info("Authorization值{}", authorization);//TOKEN续活//解析TOKEN//根据uuid,延长用户信息String uuid = authorization;String key = "fewCode:userinfo:" + uuid;stringRedisTemplate.expire(key, filterProperties.getTokenExpire(), TimeUnit.MINUTES);return chain.filter(exchange);}}
package com.tfjybj.gateway.result;public enum ResultMsgEnum {FIND_SUCCESS("查询成功!"),FIND_FAIL("查询失败!"),UPDATE_SUCCESS("更新成功"),UPDATE_FAIL("更新失败"),DELETE_SUCCESS("删除成功"),DELETE_FAIL("删除失败"),SEND_SUCCESS("发送成功"),SEND_FAIL("发送失败"),EXECUTE_SUCCESS("执行成功!"),EXECUTE_FAIL("执行失败!"),AUTH_FAILED("权限认证失败"),AUTH_SUCCESS("权限认证成功");private final String msg;ResultMsgEnum(String msg) {this.msg = msg;}public String getMsg() {return msg;}
}
package com.tfjybj.gateway.util;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;import java.util.List;@Component
@RefreshScope
@ConfigurationProperties(prefix = "leyou.filter")
public class FilterProperties {public void setAllowPaths(List<String> allowPaths) {this.allowPaths = allowPaths;}public List<String> getAllowPaths() {return allowPaths;}private List<String> allowPaths;/*** token过期时间*/private Integer tokenExpire;public Integer getTokenExpire() {return tokenExpire;}public void setTokenExpire(Integer tokenExpire) {this.tokenExpire = tokenExpire;}
}
package com.tfjybj.gateway;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
//@EnableDiscoveryClientpublic class GatewayApplication {public static void main(String[] args) {SpringApplication.run(GatewayApplication.class, args);}}

我们在服务中进行的白名单中接口的操作如下

(主要是根据传过来的信息生成token,然后以键值对的形式存入redis中,方便后续通过redis根据token拿人的信息):

RestController
@RequestMapping("/login")
public class LoginController {@Autowiredprivate Actor actorInfo;@ApiOperation("学生登录验证")@RequestMapping(value="checkLogin",method= RequestMethod.POST)@Transactional(rollbackFor = Exception.class)public Actor checkLoginInfo(@RequestBody Actor actor){return actorInfo.notifyStudentCheckLoginInfo(actor);}
}
public Actor notifyStudentCheckLoginInfo(Actor student){Actor actor;for (Actor studentInfo:allStudent){actor=studentInfo.checkLoginInfo(student);if (!ObjectUtils.isEmpty(actor)){//生成UUIDString uuid = CreateUUID.createUUID();//存入redissaveRedis(uuid, actor);//生成token,封装到请求头putHeader(uuid);return actor;}}return null;}
public class CreateUUID {public CreateUUID() {}public static String createUUID() {String preUuid = UUID.randomUUID().toString();String newUUID = preUuid.replace("-", "");return newUUID;}
}
   private void saveRedis(String uuid, Object userInfo) {//拼接key,user信息序列化,存入redis,过期时间在nacos中设置String key = "fewCode:userinfo:" + uuid;String userJson = JSONObject.toJSONString(userInfo);redisTemplate.opsForValue().set(key, userJson);redisTemplate.expire(key, 1440, TimeUnit.MINUTES);}
   private void putHeader(String token) {ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletResponse response = sra.getResponse();response.setHeader("Authorization", token);}

测试

存:

在这里插入图片描述

在这里插入图片描述
将断点打到这里,可以观察到我们要请求的服务IP+端口号还有url地址,如下
相当手动访问

在这里插入图片描述

调通后存入redis中如下

在这里插入图片描述

拿:

然后拿着根据token获取信息

在这里插入图片描述

在这里插入图片描述

package com.tfjybj.login.service.impl;import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;@Service
public class AnalysisTokenService {@Autowiredprivate StringRedisTemplate redisTemplate;/*** 获取当前登陆人id** @return*/public String getUserId() {JSONObject userData = getUserData();return userData.get("id").toString();}/*** 获取用户code** @return*/public String getUserAccount() {JSONObject userData = getUserData();return userData.get("account").toString();}/*** 获取当前登陆人name** @return*/public String getUserName() {JSONObject userData = getUserData();return userData.get("name").toString();}public JSONObject getUserData() {//从请求头获取tokenServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();String token = sra.getRequest().getHeader("Authorization");token = token.split("Bearer ")[1];//解析tokenJSONObject userJson = this.analysisToken(token);return userJson;}public JSONObject analysisToken  (String token){//解析tokenString key= "fewCode:userinfo:"+token;String userInfoStr = redisTemplate.opsForValue().get(key);JSONObject userJson = JSONObject.parseObject(userInfoStr);
//        String data = jsonObject.get("data").toString();
//        JSONObject userJson = JSONObject.parseObject(data);return userJson;}}

总结

1、搞懂gateway是干嘛的
2、知道配置文件中各个参数是什么

相关文章:

手动搭建gateway,项目集成gateway实现Token效果

目录 背景步骤1、首先创建springboot项目2、引入依赖3、配置文件&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff08;超级重要&#xff01;&#xff01;&#xff01;根据自己的需要进行配置&#xff09;4、相关类我们在服务中进行的白名单中接口的操作如…...

linux下SVN服务器搭建

在本教程中&#xff0c;我们将介绍如何在Linux系统下搭建Subversion&#xff08;SVN&#xff09;服务器。Subversion是一种流行的版本控制系统&#xff0c;它允许多个人在同一项目上进行协作&#xff0c;同时避免了他们各自的更改发生冲突。 安装SVN 在大多数Linux发行版中&am…...

技术等级 TRL 定义

“不同环境、不同目标下TRL表述不一样” 技术等级 TRL 定义 TRL1 基本原理提出和发现 TRL2 技术应用研究 TRL3 完成概念验证&#xff0c;如叶栅试验、燃烧室头部试验等 TRL4 完成模拟部件试验&#xff0e;如压气机性能试验&#xff0c;燃烧室扇形试验 TRL5 完…...

DHorse v1.3.0 发布,基于k8s的发布平台

综述 DHorse是一个简单易用、以应用为中心的云原生DevOps系统&#xff0c;具有持续集成、持续部署、微服务治理等功能&#xff0c;无需安装依赖Docker、Maven、Node等环境即可发布Java、Vue、React应用&#xff0c;主要特点&#xff1a;部署简单、操作简洁、功能快速。 新增特…...

Redis - 缓存的双写一致性

概念&#xff1a; 当修改了数据库的数据也要同时更新缓存的数据&#xff0c;缓存和数据库的数据要保持一致 那为什么会有不一致的情况呢&#xff1f; 如果不追求一致性&#xff0c;正常有两种做法 先修改数据库 后删除旧的缓存先删除旧的缓存 再修改数据库 我们以先删除旧的…...

opencv03-Mat矩阵API的使用

opencv03-Mat矩阵API的使用 构造方法(具体介绍看API文档) int main() {Mat m1 Mat(200, 100, CV_8UC1);imshow("o1", m1);Mat m2 Mat(Size(100, 200), CV_8UC1);imshow("o2", m2);Mat m3 Mat(200, 100, CV_8UC3, Scalar(255, 0, 0));imshow("o3&…...

2023届浙江大学MPA提面A资格经验总结分享

本人是去年报考的浙大MPA项目&#xff0c;并通过提面获得了A资格&#xff0c;新一年浙大MPA项目提前批面试已经开始了&#xff0c;受达立易考周老师邀请来分享下我的提面经验&#xff0c;希望我的经验能对还在迷茫中的小伙伴有所帮助。 点开提面通知&#xff0c;首先看到…...

BugKu CTF(杂项篇MISC)—想要种子吗

BugKu CTF(杂项篇MISC)—想要种子吗 提 示: 描 述:flag{} 题目下载后是一张图片&#xff0c;打开如下。 一、工具 十六进制编辑器010 editor kali系统文件分离工具binwalk或者foremost 维吉尼亚密码 STEGHIDE图片隐写工具 文章所需的软件下载地址 ARCHPR压缩包密码破解…...

类之间的关系

1、类关系 继承、实现、依赖、组合、聚合 继承&#xff1a;一个类继承另一个类&#xff1b; 实现&#xff1a;一个类实现另一个接口&#xff1b; 依赖&#xff1a;一个类作为另一个的局部变量&#xff0c;方法的参数&#xff0c;临时对象等&#xff1b; 组合&#xff1a;一个类…...

【蓝图】p40-p43对象引用、变量有效性、实现键盘控制物体自转、简单点名系统

p40-p43对象引用、变量有效性、实现键盘控制物体自转、简单点名系统 p40对象引用、变量有效性p41实现键盘控制物体自转创建bool值控制旋转实现通过键盘控制自转 p42p43简单点名系统Get All Actors Of Class&#xff08;获得场景中所有该类的actor演员&#xff09;getFor Each L…...

vscode设置远程登录和免密登录

首先&#xff0c;我们去官网下载VScode 安装过程比较简单&#xff0c;大家自行安装即可&#xff0c;注意建议安装在除C盘外的其他盘中。 安装完成后&#xff0c;打开我们下载好的VScode&#xff0c;点击左侧的Extensions选项&#xff0c;搜索Remote&#xff0c;Install第一项R…...

今日头条面试真题及答案,软件测试工程师面试秘籍

试题1&#xff0e;在浏览器地址栏里输入一个网址&#xff0c;接下来会发生什么&#xff1f; 答案&#xff1a;发生的操作如下。 &#xff08;1&#xff09;浏览器查找该网址的IP地址。 &#xff08;2&#xff09;浏览器根据解析得到的IP地址向Web服务器发送一个HTTP请求。 &am…...

JavaScript Windows 浏览器对象模型

Window 对象 BOM 的核心就是 window 对象所有浏览器都支持 window 对象。它表示浏览器窗口。所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。全局变量是 window 对象的属性。全局函数是 window 对象的方法。HTML DOM 的 document 也是 window 对象的属…...

【uniapp 获取缓存及清除缓存】

小程序及H5 获取缓存&#xff1a; 使用uniapp中的wx.getStorageInfoSync()方法可以获取当前小程序或H5应用的本地缓存信息&#xff0c;如下所示&#xff1a; let storageInfo uni.getStorageInfoSync() console.log(storageInfo)其中&#xff0c;storageInfo是一个对象&…...

【vim 学习系列文章 2 - vim 常用插件配置】

文章目录 1.1 vim 常用插件1.1.1 vim 插件 Pathogen 管理1.1.2 vim 常用插件推荐1.1.3 vim Leaderf1.1.4 vim ripgrep 工具1.1.5 vim Leaderf 配合 rg1.1.6 vim autocmd 配置 1.2 其它类型文件 vimrc 配置1.2.1 System Verilog vimrc 配置 上篇文章&#xff1a;vim 学习系列文章…...

【外卖系统】修改菜品

需求分析 在菜品管理列表页面点击修改按钮&#xff0c;跳转到修改页面&#xff0c;在修改页面回显菜品相关信息并进行修改&#xff0c;在最后点击确定按钮完成修改操作 代码设计 页面发送ajax请求&#xff0c;请求服务端获取分类数据&#xff0c;用于菜品分类下拉框中数据显…...

【暑期每日一练】 day11

目录 选择题 &#xff08;1&#xff09; 解析&#xff1a; &#xff08;2&#xff09; 解析&#xff1a; &#xff08;3&#xff09; 解析&#xff1a; &#xff08;4&#xff09; 解析&#xff1a; &#xff08;5&#xff09; 解析&#xff1a; 编程题 题一 描…...

神经概率语言模型

本文主要参考《A Neural Probabilistic Language Model》这是一篇很重要的语言模型论文,发表于2003年。主要贡献如下: 提出了一种基于神经网络的语言模型&#xff0c;是较早将神经网络应用于语言模型领域的工作之一&#xff0c;具有里程碑意义。采用神经网络模型预测下一个单词…...

什么是shadow DOM?

Shadow DOM&#xff08;影子DOM&#xff09;是一种用于在Web组件中封装HTML、CSS和JavaScript的技术。它是Web组件的一个重要特性&#xff0c;旨在将组件的结构、样式和行为封装在一个独立的、隔离的DOM树中&#xff0c;从而与主文档的DOM树相互隔离。 传统的Web开发中&#x…...

我的 365 天创作纪念日

✅作者简介&#xff1a;人工智能专业本科在读&#xff0c;喜欢计算机与编程&#xff0c;写博客记录自己的学习历程。 &#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&…...

spark-sql : “java.lang.NoSuchFieldError: out“ 异常解决

异常现象 at java.lang.reflect.Method.invoke(Method.java:498)at org.apache.spark.deploy.JavaMainApplication.start(SparkApplication.scala:52)at org.apache.spark.deploy.SparkSubmit.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:847)at org.apac…...

Node.js入门笔记(包含源代码)以及详细解析

Node.js 入门笔记源码 01、如何在终端中执行js 文件 目标&#xff1a;将下面的代码语句在中断中执行 代码演示&#xff1a; console.log(Hello World)for (let i 0;i < 3;i) {console.log(6)}方法&#xff1a;在文件上右击打开在终端中执行&#xff0c;然后输入node空格 输…...

windows自动化点击大麦app抢购、捡漏,仅支持windows11操作系统

文章目录 必要条件程序运行必要条件 确保windows11版本操作系统,如果不是可以通过镜像升级为windows11如果已经是windows11操作系统,确保更新到最新版本 修改系统所在时区,将国家或地区改为美国 开启虚拟化 勾选Hyper-V,如果没有则不需要勾选 勾选虚拟机平台 勾选完毕,点…...

vue 拦截 v-html 中 a 标签 href 跳转

记录 template 中 给需要 拦截的 代码片段加上click 方法 click“targetNodeNameClick” <p class"message-content message-content-text" v-html"replaceURLWithHTMLLinks(getText(message))" click"targetNodeNameClick"></p>然…...

分布式id、系统id、业务id以及主键之间的关系

推荐 连分布式ID都理解不了&#xff0c;你是刚培训出来冒充面试官的吧 1 分布式id、系统id、业务id以及主键之间的关系 分布式ID、系统ID、业务ID和主键的关系&#xff1a; 分布式ID&#xff1a;在分布式系统中&#xff0c;由于存在多个独立的节点&#xff0c;为了保证每个节…...

设计模式七:适配器模式(Adapter Pattern)

适配器模式&#xff08;Adapter Pattern&#xff09;是一种结构型设计模式&#xff0c;用于将一个类的接口转换成客户端所期望的另一个接口。它允许不兼容的接口能够协同工作。 适配器模式涉及角色&#xff1a; 目标接口&#xff08;Target Interface&#xff09;&#xff1a…...

数据结构---队列

(一)队列之基础补充 队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。 —— 百科 「队列 Queue」是一种…...

chatGPT在软件测试中应用方式有哪些?

ChatGPT可以在软件测试中以以下方式应用&#xff1a; 1. 自动化对话测试&#xff1a;ChatGPT可以用于自动化对话测试&#xff0c;模拟用户与软件系统进行实时对话。它可以扮演用户的角色&#xff0c;向系统发送各种类型的指令和请求&#xff0c;并验证系统的响应是否符合预期。…...

chatgpt 接口使用(一)

使用api实现功能 参考链接&#xff1a;https://platform.openai.com/examples 安装库&#xff1a; pip3 install openai 例如&#xff1a; import os import openaiopenai.api_key os.getenv("OPENAI_API_KEY") response openai.ChatCompletion.create(model&q…...

【个人笔记】Linux 服务管理两种方式service和systemctl

service命令与systemctl 命令 service 命令与传统的 SysVinit 和 Upstart 初始化系统相关。较早期的 Linux 发行版&#xff08;如早期的 Ubuntu、Red Hat 等&#xff09;使用了这些初始化系统。service 命令用于启动、停止、重启和查询系统服务的状态。虽然许多现代 Linux 发行…...