SpringBoot项目架构实战之“网关zuul搭建“

第三章 网关zuul搭建


前言:

1、主要功能

        zuul主要提供动态路由(内置ribbon实现)和过滤(可以做统一鉴权过滤器、灰度发布过滤器、黑白名单IP过滤器、服务限流过滤器(可以配合Sentinel实现))功能;

2、和Spring Cloud GateWay的区别

        属于两个不同开源组织提供的网关解决方案。spring cloud GateWay使用非阻塞API,内置限流过滤器,支持长连接(比如 websockets),在高并发和后端服务响应慢的场景下比Zuul1的表现要好;zuul无内置限流过滤器,但是可以与Sentinel(是阿里开源的一款高性能的限流框架)集成使用。


一、创建zuul服务module

参考第二章eureka的创建

二、配置文件

1、pom文件配置

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.hq</groupId><artifactId>taxi-online</artifactId><version>0.0.1-SNAPSHOT</version></parent><artifactId>taxi-online-zuul</artifactId><name>taxi-online-zuul</name><description>personal test for zuul</description><url>org.apache</url><packaging>jar</packaging><dependencies><!-- zuul --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId></dependency><!-- eureka-client --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId></dependency></dependencies>
</project>

2、application.yml文件配置

#服务端口
server:port: 9100
#服务名  
spring:application:name: taxi-online-zuul
#服务注册    
eureka:client:service-url:defaultZone: http://localhost:9001/eureka/,http://localhost:9002/eureka/enabled: true # 是否启用Eureka clientinstance:hostname: localhostinstance-id: taxi-online-zuul # 实例id

3、启动类

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@SpringBootApplication
@EnableZuulProxy
@EnableEurekaClient
public class StartSpringCloudZuul {public static void main(String[] args) {SpringApplication.run(StartSpringCloudZuul.class,args);}
}

三、zuul功能

1、动态路由

2、统一鉴权

3、过滤器

4、灰度发布

5、限流

四、底层源码

1、启动原理

类似注册中心:

1)boot启动类

boot启动类上添加@EnableZuulProxy注解;

2)EnableZuulProxy注解

EnableZuulProxy注解中导入ZuulProxyMarkerConfiguration配置类

@EnableCircuitBreaker
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ZuulProxyMarkerConfiguration.class)
public @interface EnableZuulProxy {}
3)ZuulProxyMarkerConfiguration配置类

ZuulProxyMarkerConfiguration配置类往容器添加了一个空的Marker对象,这个对象是作为容器是否添加ZuulProxyAutoConfiguration类的条件,因为ZuulProxyAutoConfiguration类上面加了@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)的注解

@Configuration(proxyBeanMethods = false)
public class ZuulProxyMarkerConfiguration {@Beanpublic Marker zuulProxyMarkerBean() {return new Marker();}class Marker {}}
4)spring.factories文件

zuul包下面的spring.factories文件指定了两个引入类,只要导包就会被引进去(由SpringFactoriesLoader 进行读取)--见下方截图。如果没有这个文件,boot的自动扫描不会扫描这些外部包的类。这两个引入类被注入容器的条件分别是:

@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)

@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)

,分别可以通过在启动类上添加下面注解来引入相应的Marker类:

@EnableZuulProxy

@EnableZuulServer。


@EnableZuulServer、@EnableZuulProxy两个注解的区别:
@EnableZuulServer - 普通Zuul Server,只支持基本的route与filter功能.
@EnableZuulProxy - 普通Zuul Server+服务发现与熔断等功能的增强版,具有反向代理功能。
@EnableZuulProxy简单理解为@EnableZuulServer的增强版,当Zuul与Eureka、Ribbon等组件配合使用时,我们使用@EnableZuulProxy。所以我们做SpringCloud微服务系统一般都是使用@EnableZuulProxy。

5)ZuulServerAutoConfiguration配置类

ZuulServerAutoConfiguration配置类(源码见下方)主要做的事情有:

1、往容器注入了ZuulServlet,该类是zuul的核心类。

2、往容器注入了 一些前置过滤器和后置过滤器。

3、注入ZuulFilterInitializer类并初始化,初始化逻辑中将所有过滤器交给FilterRegistry类进行管理。FilterRegistry类源码如下:

/*** @author mhawthorne*/
public class FilterRegistry {private static final FilterRegistry INSTANCE = new FilterRegistry();public static final FilterRegistry instance() {return INSTANCE;}private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap<String, ZuulFilter>();private FilterRegistry() {}public ZuulFilter remove(String key) {return this.filters.remove(key);}public ZuulFilter get(String key) {return this.filters.get(key);}public void put(String key, ZuulFilter filter) {this.filters.putIfAbsent(key, filter);}public int size() {return this.filters.size();}public Collection<ZuulFilter> getAllFilters() {return this.filters.values();}}

ZuulServerAutoConfiguration源码如下(有删减):

/*** @author Spencer Gibb* @author Dave Syer* @author Biju Kunjummen*/
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({ ZuulProperties.class })
@ConditionalOnClass({ ZuulServlet.class, ZuulServletFilter.class })
@ConditionalOnBean(ZuulServerMarkerConfiguration.Marker.class)
// Make sure to get the ServerProperties from the same place as a normal web app would
// FIXME @Import(ServerPropertiesAutoConfiguration.class)
public class ZuulServerAutoConfiguration {@Bean@ConditionalOnMissingBean(name = "zuulServlet")@ConditionalOnProperty(name = "zuul.use-filter", havingValue = "false",matchIfMissing = true)public ServletRegistrationBean zuulServlet() {ServletRegistrationBean<ZuulServlet> servlet = new ServletRegistrationBean<>(new ZuulServlet(), this.zuulProperties.getServletPattern());// The whole point of exposing this servlet is to provide a route that doesn't// buffer requests.servlet.addInitParameter("buffer-requests", "false");return servlet;}// pre filters@Beanpublic ServletDetectionFilter servletDetectionFilter() {return new ServletDetectionFilter();}@Bean@ConditionalOnMissingBeanpublic FormBodyWrapperFilter formBodyWrapperFilter() {return new FormBodyWrapperFilter();}@Bean@ConditionalOnMissingBeanpublic DebugFilter debugFilter() {return new DebugFilter();}@Bean@ConditionalOnMissingBeanpublic Servlet30WrapperFilter servlet30WrapperFilter() {return new Servlet30WrapperFilter();}// post filters@Beanpublic SendResponseFilter sendResponseFilter(ZuulProperties properties) {return new SendResponseFilter(zuulProperties);}@Beanpublic SendErrorFilter sendErrorFilter() {return new SendErrorFilter();}@Beanpublic SendForwardFilter sendForwardFilter() {return new SendForwardFilter();}//@Configuration(proxyBeanMethods = false)protected static class ZuulFilterConfiguration {@Autowiredprivate Map<String, ZuulFilter> filters;@Beanpublic ZuulFilterInitializer zuulFilterInitializer(CounterFactory counterFactory,TracerFactory tracerFactory) {FilterLoader filterLoader = FilterLoader.getInstance();FilterRegistry filterRegistry = FilterRegistry.instance();return new ZuulFilterInitializer(this.filters, counterFactory, tracerFactory,filterLoader, filterRegistry);}}
}
6)ZuulProxyAutoConfiguration配置类

继承了ZuulServerAutoConfiguration类,是ZuulServerAutoConfiguration的增强版,在ZuulServerAutoConfiguration的基础上增加eureka、ribbon、hystrix等功能。源码如下:

/*** @author Spencer Gibb* @author Dave Syer* @author Biju Kunjummen*/
@Configuration(proxyBeanMethods = false)
@Import({ RibbonCommandFactoryConfiguration.RestClientRibbonConfiguration.class,RibbonCommandFactoryConfiguration.OkHttpRibbonConfiguration.class,RibbonCommandFactoryConfiguration.HttpClientRibbonConfiguration.class,HttpClientConfiguration.class })
@ConditionalOnBean(ZuulProxyMarkerConfiguration.Marker.class)
public class ZuulProxyAutoConfiguration extends ZuulServerAutoConfiguration {// pre filters@Bean@ConditionalOnMissingBean(PreDecorationFilter.class)public PreDecorationFilter preDecorationFilter(RouteLocator routeLocator,ProxyRequestHelper proxyRequestHelper) {return new PreDecorationFilter(routeLocator,this.server.getServlet().getContextPath(), this.zuulProperties,proxyRequestHelper);}// route filters@Bean@ConditionalOnMissingBean(RibbonRoutingFilter.class)public RibbonRoutingFilter ribbonRoutingFilter(ProxyRequestHelper helper,RibbonCommandFactory<?> ribbonCommandFactory) {RibbonRoutingFilter filter = new RibbonRoutingFilter(helper, ribbonCommandFactory,this.requestCustomizers);return filter;}@Bean@ConditionalOnMissingBean({ SimpleHostRoutingFilter.class,CloseableHttpClient.class })public SimpleHostRoutingFilter simpleHostRoutingFilter(ProxyRequestHelper helper,ZuulProperties zuulProperties,ApacheHttpClientConnectionManagerFactory connectionManagerFactory,ApacheHttpClientFactory httpClientFactory) {return new SimpleHostRoutingFilter(helper, zuulProperties,connectionManagerFactory, httpClientFactory);}@Bean@ConditionalOnMissingBean({ SimpleHostRoutingFilter.class })public SimpleHostRoutingFilter simpleHostRoutingFilter2(ProxyRequestHelper helper,ZuulProperties zuulProperties, CloseableHttpClient httpClient) {return new SimpleHostRoutingFilter(helper, zuulProperties, httpClient);}@Bean@ConditionalOnMissingBean(ServiceRouteMapper.class)public ServiceRouteMapper serviceRouteMapper() {return new SimpleServiceRouteMapper();}@Configuration(proxyBeanMethods = false)@ConditionalOnMissingClass("org.springframework.boot.actuate.health.Health")protected static class NoActuatorConfiguration {@Beanpublic ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {ProxyRequestHelper helper = new ProxyRequestHelper(zuulProperties);return helper;}}@Configuration(proxyBeanMethods = false)@ConditionalOnClass(Health.class)protected static class EndpointConfiguration {@Autowired(required = false)private HttpTraceRepository traces;@Bean@ConditionalOnAvailableEndpointpublic RoutesEndpoint routesEndpoint(RouteLocator routeLocator) {return new RoutesEndpoint(routeLocator);}@ConditionalOnAvailableEndpoint@Beanpublic FiltersEndpoint filtersEndpoint() {FilterRegistry filterRegistry = FilterRegistry.instance();return new FiltersEndpoint(filterRegistry);}@Beanpublic ProxyRequestHelper proxyRequestHelper(ZuulProperties zuulProperties) {TraceProxyRequestHelper helper = new TraceProxyRequestHelper(zuulProperties);if (this.traces != null) {helper.setTraces(this.traces);}return helper;}}}

2、核心类ZuulServlet

1)作用

调度不同阶段的filters,处理异常。所有的Request都要经过ZuulServlet的处理。三个核心的方法preRoute(),route(), postRoute(),zuul对request处理逻辑都在这三个方法里。源码如下:

public class ZuulServlet extends HttpServlet {private static final long serialVersionUID = -3374242278843351500L;private ZuulRunner zuulRunner;@Overridepublic void init(ServletConfig config) throws ServletException {super.init(config);String bufferReqsStr = config.getInitParameter("buffer-requests");boolean bufferReqs = bufferReqsStr != null && bufferReqsStr.equals("true") ? true : false;zuulRunner = new ZuulRunner(bufferReqs);}@Overridepublic void service(javax.servlet.ServletRequest servletRequest, javax.servlet.ServletResponse servletResponse) throws ServletException, IOException {try {init((HttpServletRequest) servletRequest, (HttpServletResponse) servletResponse);// Marks this request as having passed through the "Zuul engine", as opposed to servlets// explicitly bound in web.xml, for which requests will not have the same data attachedRequestContext context = RequestContext.getCurrentContext();context.setZuulEngineRan();try {preRoute();} catch (ZuulException e) {error(e);postRoute();return;}try {route();} catch (ZuulException e) {error(e);postRoute();return;}try {postRoute();} catch (ZuulException e) {error(e);return;}} catch (Throwable e) {error(new ZuulException(e, 500, "UNHANDLED_EXCEPTION_" + e.getClass().getName()));} finally {RequestContext.getCurrentContext().unset();}}/*** executes "post" ZuulFilters** @throws ZuulException*/void postRoute() throws ZuulException {zuulRunner.postRoute();}/*** executes "route" filters** @throws ZuulException*/void route() throws ZuulException {zuulRunner.route();}/*** executes "pre" filters** @throws ZuulException*/void preRoute() throws ZuulException {zuulRunner.preRoute();}/*** initializes request** @param servletRequest* @param servletResponse*/void init(HttpServletRequest servletRequest, HttpServletResponse servletResponse) {zuulRunner.init(servletRequest, servletResponse);}/*** sets error context info and executes "error" filters** @param e*/void error(ZuulException e) {RequestContext.getCurrentContext().setThrowable(e);zuulRunner.error();}
}
2)调用链路:

以preRoute()为例:

1、ZuulServlet——》ZuulRunner,源码见四-2-1);

2、ZuulRunner——》FilterProcessor,源码如下:

public void preRoute() throws ZuulException {FilterProcessor.getInstance().preRoute();}

3、FilterProcessor调自己的runFilters方法,涉及调用其他类:

FilterProcessor——》FilterLoader,源码见下方4

实际执行过滤器逻辑是在调用自己processZuulFilter方法中的下方的代码逻辑。

ZuulFilterResult result = filter.runFilter();(runFilter里面调用了子类的run方法)

public void preRoute() throws ZuulException {try {runFilters("pre");} catch (ZuulException e) {throw e;} catch (Throwable e) {throw new ZuulException(e, 500, "UNCAUGHT_EXCEPTION_IN_PRE_FILTER_" + e.getClass().getName());}}/*** runs all filters of the filterType sType/ Use this method within filters to run custom filters by type** @param sType the filterType.* @return* @throws Throwable throws up an arbitrary exception*/public Object runFilters(String sType) throws Throwable {if (RequestContext.getCurrentContext().debugRouting()) {Debug.addRoutingDebug("Invoking {" + sType + "} type filters");}boolean bResult = false;List<ZuulFilter> list = FilterLoader.getInstance().getFiltersByType(sType);if (list != null) {for (int i = 0; i < list.size(); i++) {ZuulFilter zuulFilter = list.get(i);Object result = processZuulFilter(zuulFilter);if (result != null && result instanceof Boolean) {bResult |= ((Boolean) result);}}}return bResult;}public Object processZuulFilter(ZuulFilter filter) throws ZuulException {RequestContext ctx = RequestContext.getCurrentContext();boolean bDebug = ctx.debugRouting();final String metricPrefix = "zuul.filter-";long execTime = 0;String filterName = "";try {long ltime = System.currentTimeMillis();filterName = filter.getClass().getSimpleName();RequestContext copy = null;Object o = null;Throwable t = null;if (bDebug) {Debug.addRoutingDebug("Filter " + filter.filterType() + " " + filter.filterOrder() + " " + filterName);copy = ctx.copy();}ZuulFilterResult result = filter.runFilter();ExecutionStatus s = result.getStatus();execTime = System.currentTimeMillis() - ltime;switch (s) {case FAILED:t = result.getException();ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);break;case SUCCESS:o = result.getResult();ctx.addFilterExecutionSummary(filterName, ExecutionStatus.SUCCESS.name(), execTime);if (bDebug) {Debug.addRoutingDebug("Filter {" + filterName + " TYPE:" + filter.filterType() + " ORDER:" + filter.filterOrder() + "} Execution time = " + execTime + "ms");Debug.compareContextState(filterName, copy);}break;default:break;}if (t != null) throw t;usageNotifier.notify(filter, s);return o;} catch (Throwable e) {if (bDebug) {Debug.addRoutingDebug("Running Filter failed " + filterName + " type:" + filter.filterType() + " order:" + filter.filterOrder() + " " + e.getMessage());}usageNotifier.notify(filter, ExecutionStatus.FAILED);if (e instanceof ZuulException) {throw (ZuulException) e;} else {ZuulException ex = new ZuulException(e, "Filter threw Exception", 500, filter.filterType() + ":" + filterName);ctx.addFilterExecutionSummary(filterName, ExecutionStatus.FAILED.name(), execTime);throw ex;}}}

4、FilterLoader——》filterRegistry,通过filterRegistry拿到所有的过滤器并筛选返回符合要求类型的集合并按优先级排序,放入缓存。

 /*** Returns a list of filters by the filterType specified** @param filterType* @return a List<ZuulFilter>*/public List<ZuulFilter> getFiltersByType(String filterType) {List<ZuulFilter> list = hashFiltersByType.get(filterType);if (list != null) return list;list = new ArrayList<ZuulFilter>();Collection<ZuulFilter> filters = filterRegistry.getAllFilters();for (Iterator<ZuulFilter> iterator = filters.iterator(); iterator.hasNext(); ) {ZuulFilter filter = iterator.next();if (filter.filterType().equals(filterType)) {list.add(filter);}}Collections.sort(list); // sort by priorityhashFiltersByType.putIfAbsent(filterType, list);return list;}

5、FilterRegistry调用自己的getAllFilters方法返回所有的过滤器

private final ConcurrentHashMap<String, ZuulFilter> filters = new ConcurrentHashMap<String, ZuulFilter>();
public Collection<ZuulFilter> getAllFilters() {return this.filters.values();}

3、顶级抽象父类ZuulFilter

所有的过滤器都应继承该抽象类,重写shouldFilter、filterType、filterOrder、run方法。

shouldFilter:该过滤器是否生效  返回true:有效;false:无效

filterType:指定过滤器类型,FilterConstants包含下面图中几种类型:filterOrder:在过滤器链中的顺序,返回值越小越靠前;

run:过滤器的逻辑。

public abstract class ZuulFilter implements IZuulFilter, Comparable<ZuulFilter> {abstract boolean shouldFilter();abstract Object run() throws ZuulException;abstract public String filterType();/*** filterOrder() must also be defined for a filter. Filters may have the same  filterOrder if precedence is not* important for a filter. filterOrders do not need to be sequential.** @return the int order of a filter*/abstract public int filterOrder();public int compareTo(ZuulFilter filter) {return Integer.compare(this.filterOrder(), filter.filterOrder());}
}

4、过滤器热加载

参考下方博客:

zuul 1.x 源码解析 (结合本人过去2年工作经历整理,超详细)_zuulproxyautoconfiguration.predecorationfilter-CSDN博客文章浏览阅读428次,点赞6次,收藏4次。zuul 1.x 源码解析,全程断点调试,超详细(结合本人过去2年工作经历,花了1周时间整理并记录)_zuulproxyautoconfiguration.predecorationfilterhttps://blog.csdn.net/qq_22270363/article/details/132052278

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/44653.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学会创建虚拟网卡

此电脑-----管理 一直点击下一页 选择网络适配器 选择Microsoft----Microsoft KM-TEST环回适配器 然后点击下一页 完成的界面如下&#xff1a; 手动改IP

Git分支结构

目录 1. 线性分支结构 2. 分叉与合并结构 3. 分支与标签的关系 4. 并行开发与分支管理策略 测试&#xff08;本机系统为Rocky_linux9.4&#xff09; 合并失败解决 删除分支 删除本地分支 删除远程分支 Git 中的分支结构是版本控制中非常重要的概念之一&#xff0c;它描…

政安晨:【Keras机器学习示例演绎】(五十四)—— 使用神经决策森林进行分类

目录 导言 数据集 设置 准备数据 定义数据集元数据 为训练和验证创建 tf_data.Dataset 对象 创建模型输入 输入特征编码 深度神经决策树 深度神经决策森林 实验 1&#xff1a;训练决策树模型 实验 2&#xff1a;训练森林模型 政安晨的个人主页&#xff1a;政安晨 欢…

Python | Leetcode Python题解之第228题汇总区间

题目&#xff1a; 题解&#xff1a; class Solution:def summaryRanges(self, nums: List[int]) -> List[str]:def f(i: int, j: int) -> str:return str(nums[i]) if i j else f{nums[i]}->{nums[j]}i 0n len(nums)ans []while i < n:j iwhile j 1 < n …

Codeforces Round #956 (Div. 2) and ByteRace 2024 E. I Love Balls(概率期望)

题目 思路来源 官方题解 题解 特殊球不会改变普通球的顺序&#xff0c;所以都是alice拿一半里较多的部分 n-k1一半向上取整就是(n-k2)/2&#xff0c;同理n-k个一般向上取整(n-k1)/2 每个特殊球独立地来看&#xff0c;在每个空隙的概率相同 所以分别统计特殊球和非特殊球的…

LLM+Agent技术

&#x1f4a1; Agent可以理解为某种能自主理解、规划决策、执行复杂任务的智能体。Agent 是让 LLM 具备目标实现的能力&#xff0c;并通过自我激励循环来实现这个目标。它可以是并行的&#xff08;同时使用多个提示&#xff0c;试图解决同一个目标&#xff09;和单向的&#xf…

14-63 剑和诗人37 - 分布式系统中的数据访问设计

​​ 在分布式系统中,跨服务和数据库提供统一、可靠的数据访问至关重要,但又极具挑战性。微服务和数据库的拓扑结构为分布、缓存、复制和同步带来了复杂性。 让我们探索有助于解决这些复杂性并简化构建强大、高性能分布式系统的常见数据访问模式。 概述 我们将通过示例介绍…

探索AI数字人的开源解决方案

引言 随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;AI数字人&#xff08;或虚拟人&#xff09;正逐渐走进我们的生活&#xff0c;从虚拟助手到虚拟主播&#xff0c;再到虚拟客服&#xff0c;AI数字人在各个领域展现出巨大的潜力。开源解决方案的出现&…

解码生命语言:Transformer模型在基因序列分析的突破性应用

解码生命语言&#xff1a;Transformer模型在基因序列分析的突破性应用 基因序列分析是现代生物学和医学研究的基石&#xff0c;它涉及对DNA或RNA序列的识别、比较和解释。随着深度学习技术的兴起&#xff0c;特别是Transformer模型的出现&#xff0c;基因序列分析领域迎来了新…

[vite] Pre-transform error: Cannot find package pnpm路径过长导致运行报错

下了套vue3的代码&#xff0c;执行pnpm install初始化&#xff0c;使用vite启动&#xff0c;启动后访问就会报错 报错信息 ERROR 16:40:53 [vite] Pre-transform error: Cannot find package E:\work\VSCodeProjectWork\jeecg\xxxxxxxxx-next\xxxxxxxxx-next-jeecgBoot-vue3\…

AC修炼计划(AtCoder Regular Contest 180) A~C

A - ABA and BAB A - ABA and BAB (atcoder.jp) 这道题我一开始想复杂了&#xff0c;一直在想怎么dp&#xff0c;没注意到其实是个很简单的规律题。 我们可以发现我们住需要统计一下类似ABABA这样不同字母相互交替的所有子段的长度&#xff0c;而每个字段的的情况有&#xff…

Postman中的API安全堡垒:全面安全性测试指南

&#x1f6e1;️ Postman中的API安全堡垒&#xff1a;全面安全性测试指南 在当今的数字化世界中&#xff0c;API安全性是保护数据和系统不可或缺的一环。Postman作为API开发和测试的领先工具&#xff0c;提供了多种功能来帮助开发者进行API安全性测试。本文将深入探讨如何在Po…

交互式AI的新纪元:Transformer模型的革新应用

交互式AI的新纪元&#xff1a;Transformer模型的革新应用 随着人工智能技术的不断进步&#xff0c;交互式人工智能&#xff08;AI&#xff09;逐渐成为提升用户体验的关键技术。Transformer模型&#xff0c;以其卓越的处理序列数据的能力&#xff0c;已成为推动交互式AI发展的…

利用 AI 解放双手:把“贾维斯”带进现实 | 开源专题 No.64

Significant-Gravitas/AutoGPT Stars: 160k License: MIT AutoGPT 是开源 AI 代理生态系统的核心工具包。 提供构建、测试和委托 AI 代理的工具。AutoGPT 处于 AI 创新前沿&#xff0c;提供文档、贡献指南以及快速开始创建自己的代理。包含强大的组件如 Forge 和 Benchmark&…

【教程】Hexo 部署到 Github Page 后,自定义域名失效的问题

目录 前言&问题描述解决方案细节 前言&问题描述 近期给 Github Page 上托管的静态网站映射了自定义域名&#xff08;aiproducthome.top&#xff09;&#xff0c;之后发现每次更新并部署 hexo 到 Github Page &#xff08;hexo d&#xff09;后就会出现自定义域名失效的…

探索SQL Server查询优化的奥秘:数据库查询优化器深度解析

探索SQL Server查询优化的奥秘&#xff1a;数据库查询优化器深度解析 在数据库管理的世界里&#xff0c;查询优化器是确保查询效率的关键组件。SQL Server的查询优化器采用先进的算法&#xff0c;将用户的SQL查询转换成高效的执行计划。本文将深入探讨SQL Server查询优化器的工…

高效利用iCloud:全面指南与技术深度解析

引言 在数字化时代&#xff0c;数据的同步、备份和跨设备协作变得尤为重要。苹果公司的iCloud服务凭借其强大的云存储和同步功能&#xff0c;为用户提供了一个无缝的数据管理解决方案。本文将全面介绍如何高效利用iCloud&#xff0c;帮助用户更好地管理数据、提升工作效率&…

Python如何进行游戏开发?

使用Python进行游戏开发可以通过以下几个步骤来实现。Python有多个游戏开发框架和库&#xff0c;最常用的是Pygame。下面是一个简要的指南&#xff0c;介绍如何使用Pygame进行游戏开发。 安装Pygame 首先&#xff0c;你需要安装Pygame库。你可以使用pip进行安装&#xff1a; …

前端如何去看蓝湖

首先加入团队&#xff0c;在内容中我们可以看到点击图片&#xff0c;右边出现的图 包含了像素甚至有代码&#xff0c;我们可以参考这个代码。 那么在使用之前我们需要调整好像素&#xff0c;例如我们的像素宽为375&#xff0c;不用去管高&#xff0c;然后这个宽度我们可以去自…

QT——Excel实现自绘区域选择边框

文章目录 一、自绘区域边框1.1、效果展示2.2、问题整理2.2.1、重绘单元格选择区2.2.2、选择区域的大小 一、自绘区域边框 1.1、效果展示 单选 多选 2.2、问题整理 2.2.1、重绘单元格选择区 误区: 继承QStyledItemDelegate重写paint,测试发现只能在单元格内绘制。 通过继…