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

OpenFeign源码

openfeign是通过FeignClientFactoryBean生成动态代理对象的方式实现http客户端无感调用,可以做到像定义接口一样写http客户端调用代码。
配置Feign接口后,我们通常会在SpringBoot项目启动类上标记@EnableFeignClients,这个是生成动态代理对象的入口。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {/*** basePackages 配置的别称*/String[] value() default {};/*** 扫描包路径下有@FeignClient注解的接口*/String[] basePackages() default {};/*** 扫描类对应包下有@FeignClient注解的接口*/Class<?>[] basePackageClasses() default {};/*** 默认配置*/Class<?>[] defaultConfiguration() default {};/*** 直接指定标记了@FeignClient的类*/Class<?>[] clients() default {};}

@EnableFeignClients里面的配置主要是为了找到@FeignClient接口,正常情况下可指定basePackages路径,或者直接不加,会直接扫描启动类及其对应包下面的所有类,去找到所有标记了@FiegnClient的接口。
这里最关键的是@Import(FeignClientsRegistrar.class)引入了FeignClientsRegistrar类。
首先看下FeignClientsRegistrar实现的接口ImportBeanDefinitionRegistrar,Spring IOC在创建bean实例的时候
会调ImportBeanDefinitionRegistrar.registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry)方法,这个方法里面是注册默认配置和注册FeignClient的逻辑。

class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {...@Overridepublic void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {// 注册默认配置registerDefaultConfiguration(metadata, registry);// 注册FeignClientregisterFeignClients(metadata, registry);}
}

继续看registerFeignClients(metadata, registry)方法,前面主要是通过@EnableFeignClients注解配置找到所有的Feign接口生成BeanDefinition,最后遍历根据BeanDefinition一个个注册FeignClient

public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {// 通过@EnableFeignClients的配置找到对应的Feign接口并生成对应的BeanDefinitionLinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());final Class<?>[] clients = attrs == null ? null : (Class<?>[]) attrs.get("clients");if (clients == null || clients.length == 0) {ClassPathScanningCandidateComponentProvider scanner = getScanner();scanner.setResourceLoader(this.resourceLoader);scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));Set<String> basePackages = getBasePackages(metadata);for (String basePackage : basePackages) {candidateComponents.addAll(scanner.findCandidateComponents(basePackage));}}else {for (Class<?> clazz : clients) {candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));}}for (BeanDefinition candidateComponent : candidateComponents) {if (candidateComponent instanceof AnnotatedBeanDefinition) {// verify annotated class is an interfaceAnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());String name = getClientName(attributes);// 注册客户端配置registerClientConfiguration(registry, name, attributes.get("configuration"));// 注册FeignClientregisterFeignClient(registry, annotationMetadata, attributes);}}
}

点进去registerFeignClient(registry, annotationMetadata, attributes),这个方法才是真正的注册逻辑。
可以看到方法里面主要是创建了一个FeignClientFactoryBean工厂bean,最终通过getObject()生成bean实例。

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata,Map<String, Object> attributes) {String className = annotationMetadata.getClassName();Class clazz = ClassUtils.resolveClassName(className, null);ConfigurableBeanFactory beanFactory = registry instanceof ConfigurableBeanFactory? (ConfigurableBeanFactory) registry : null;String contextId = getContextId(beanFactory, attributes);String name = getName(attributes);FeignClientFactoryBean factoryBean = new FeignClientFactoryBean();factoryBean.setBeanFactory(beanFactory);factoryBean.setName(name);factoryBean.setContextId(contextId);factoryBean.setType(clazz);factoryBean.setRefreshableClient(isClientRefreshEnabled());BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(clazz, () -> {factoryBean.setUrl(getUrl(beanFactory, attributes));factoryBean.setPath(getPath(beanFactory, attributes));factoryBean.setDecode404(Boolean.parseBoolean(String.valueOf(attributes.get("decode404"))));Object fallback = attributes.get("fallback");if (fallback != null) {factoryBean.setFallback(fallback instanceof Class ? (Class<?>) fallback: ClassUtils.resolveClassName(fallback.toString(), null));}Object fallbackFactory = attributes.get("fallbackFactory");if (fallbackFactory != null) {factoryBean.setFallbackFactory(fallbackFactory instanceof Class ? (Class<?>) fallbackFactory: ClassUtils.resolveClassName(fallbackFactory.toString(), null));}// 生成bean实例return factoryBean.getObject();});definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);definition.setLazyInit(true);validate(attributes);AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);beanDefinition.setAttribute("feignClientsRegistrarFactoryBean", factoryBean);// has a default, won't be nullboolean primary = (Boolean) attributes.get("primary");beanDefinition.setPrimary(primary);String[] qualifiers = getQualifiers(attributes);if (ObjectUtils.isEmpty(qualifiers)) {qualifiers = new String[] { contextId + "FeignClient" };}BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, qualifiers);BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);registerOptionsBeanDefinition(registry, contextId);
}

进入FeignClientFactoryBean的getObject方法,里面又继续调了getTarget方法。这里有两种情况,一种是指定了url,则会通过给的url封装请求,
如果没有则从注册中心获取服务地址,这里继续看loadBalance(builder, context, new HardCodedTarget<>(type, name, url));

public Object getObject() {return getTarget();
}<T> T getTarget() {FeignContext context = beanFactory != null ? beanFactory.getBean(FeignContext.class): applicationContext.getBean(FeignContext.class);Feign.Builder builder = feign(context);// 如果没有指定具体的url,则通过负载均衡从注册中心获取对应的服务地址信息if (!StringUtils.hasText(url)) {if (LOG.isInfoEnabled()) {LOG.info("For '" + name + "' URL not provided. Will try picking an instance via load-balancing.");}if (!name.startsWith("http")) {url = "http://" + name;}else {url = name;}url += cleanPath();return (T) loadBalance(builder, context, new HardCodedTarget<>(type, name, url));}...
}

继续loadBalance方法解析,这里主要是从FeignContext获取到Client实例和Targeter实例,debug的话这两个实例分别对应的类是
Client -> TraceRetryableFeignBlockingLoadBalancerClient
Targeter -> DefaultTargeter

这两个类都很关键

  1. TraceRetryableFeignBlockingLoadBalancerClient是后续调用feign接口时通过RetryableFeignBlockingLoadBalancerClient获取对应的负载均衡服务实例
  2. DefaultTargeter则是生成动态代理对象
protected <T> T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTarget<T> target) {Client client = getOptional(context, Client.class);if (client != null) {builder.client(client);applyBuildCustomizers(context, builder);Targeter targeter = get(context, Targeter.class);// 点进去看是如何生成代理对象return targeter.target(this, builder, context, target);}throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-loadbalancer?");
}

继续看动态代理对象生成的逻辑,DefaultTargeter的target方法里面,主要调用了feign.target(target)

class DefaultTargeter implements Targeter {@Overridepublic <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,Target.HardCodedTarget<T> target) {return feign.target(target);}}

feign.target先调用了build方法,然后再调newInstance方法。先看builde方法的逻辑,核心是创建了SynchronousMethodHandler.Factory对象,并且返回了ReflectiveFeign对象。
这个工厂对象主要是用来创建SynchronousMethodHandler的,而SynchronousMethodHandler就是feign接口每个方法都会封装一个对应的MethodHandler,里面包含了封装请求,发送请求,解析响应的所有流程。

public <T> T target(Target<T> target) {return build().newInstance(target);
}public Feign build() {super.enrich();SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors,responseInterceptor, logger, logLevel, dismiss404, closeAfterDecode,propagationPolicy, forceDecoding);ParseHandlersByName handlersByName =new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,errorDecoder, synchronousMethodHandlerFactory);return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
}

继续看ReflectiveFeign.newInstance(Target target)方法,通过SpringMvcContract解析了feign接口相关的元信息,
SynchronousMethodHandler.Factory创建了这个类所有方法的MethodHandler,并最终通过InvocationHandlerFactory创建ReflectiveFeign.FeignInvocationHandler,最终返回动态代理对象。

public <T> T newInstance(Target<T> target) {// 通过SpringMvcContract解析了feign接口相关的元信息,创建MethodHandlerMap<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();for (Method method : target.type().getMethods()) {if (method.getDeclaringClass() == Object.class) {continue;} else if (Util.isDefault(method)) {DefaultMethodHandler handler = new DefaultMethodHandler(method);defaultMethodHandlers.add(handler);methodToHandler.put(method, handler);} else {methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));}}// 创建ReflectiveFeign.FeignInvocationHandler,生成动态代理对象InvocationHandler handler = factory.create(target, methodToHandler);T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),new Class<?>[] {target.type()}, handler);for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {defaultMethodHandler.bindTo(proxy);}return proxy;
}

至此所有的feign接口通过FeignInvocationHandler生成了动态代理对象,里面包含了feign接口所有方法的Map<Method, MethodHandler> dispatch。
后续调用feign接口只需要直接注入使用即可。动态代理对象直接对应方法时,最终会调用InvocationHandler的invoke方法。

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("equals".equals(method.getName())) {try {Object otherHandler =args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;return equals(otherHandler);} catch (IllegalArgumentException e) {return false;}} else if ("hashCode".equals(method.getName())) {return hashCode();} else if ("toString".equals(method.getName())) {return toString();}// 通过方法获取到对应的SynchronousMethodHandler执行return dispatch.get(method).invoke(args);
}

在调用feign接口方法时,最终会执行SynchronousMethodHandler的invoke方法。

  1. 封装请求,执行请求,解码
  2. 如果抛RetryableException异常,如果不配置Retryer实例,则默认是不重试
public Object invoke(Object[] argv) throws Throwable {RequestTemplate template = buildTemplateFromArgs.create(argv);Options options = findOptions(argv);Retryer retryer = this.retryer.clone();while (true) {try {// 执行请求并且对响应结果进行解码return executeAndDecode(template, options);} catch (RetryableException e) {try {// 累计重试次数,判断是否继续重试retryer.continueOrPropagate(e);} catch (RetryableException th) {Throwable cause = th.getCause();if (propagationPolicy == UNWRAP && cause != null) {throw cause;} else {throw th;}}if (logLevel != Logger.Level.NONE) {logger.logRetry(metadata.configKey(), logLevel);}continue;}}
}

executeAndDecode方法执行请求并且处理响应结果

Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {Request request = targetRequest(template);if (logLevel != Logger.Level.NONE) {logger.logRequest(metadata.configKey(), logLevel, request);}Response response;long start = System.nanoTime();try {// 发送请求response = client.execute(request, options);// ensure the request is set. TODO: remove in Feign 12response = response.toBuilder().request(request).requestTemplate(template).build();} catch (IOException e) {if (logLevel != Logger.Level.NONE) {logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));}throw errorExecuting(request, e);}long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);if (decoder != null) {return responseInterceptor.aroundDecode(new InvocationContext(decoder, metadata.returnType(), response));}CompletableFuture<Object> resultFuture = new CompletableFuture<>();// 处理响应结果asyncResponseHandler.handleResponse(resultFuture, metadata.configKey(), response,metadata.returnType(), elapsedTime);try {if (!resultFuture.isDone())throw new IllegalStateException("Response handling not done");return resultFuture.join();} catch (CompletionException e) {Throwable cause = e.getCause();if (cause != null)throw cause;throw e;}
}

RetryableFeignBlockingLoadBalancerClient做了三件事

  1. 获取负载均衡服务实例信息
  2. 构建完整请求
  3. 发送请求并得到响应结果
public Response execute(Request request, Request.Options options) throws IOException {final URI originalUri = URI.create(request.url());String serviceId = originalUri.getHost();Assert.state(serviceId != null, "Request URI does not contain a valid hostname: " + originalUri);final LoadBalancedRetryPolicy retryPolicy = loadBalancedRetryFactory.createRetryPolicy(serviceId,loadBalancerClient);RetryTemplate retryTemplate = buildRetryTemplate(serviceId, request, retryPolicy);return retryTemplate.execute(context -> {Request feignRequest = null;ServiceInstance retrievedServiceInstance = null;Set<LoadBalancerLifecycle> supportedLifecycleProcessors = LoadBalancerLifecycleValidator.getSupportedLifecycleProcessors(loadBalancerClientFactory.getInstances(serviceId, LoadBalancerLifecycle.class),RetryableRequestContext.class, ResponseData.class, ServiceInstance.class);String hint = getHint(serviceId);DefaultRequest<RetryableRequestContext> lbRequest = new DefaultRequest<>(new RetryableRequestContext(null, buildRequestData(request), hint));// On retries the policy will choose the server and set it in the context// and extract the server and update the request being madeif (context instanceof LoadBalancedRetryContext) {LoadBalancedRetryContext lbContext = (LoadBalancedRetryContext) context;ServiceInstance serviceInstance = lbContext.getServiceInstance();if (serviceInstance == null) {if (LOG.isDebugEnabled()) {LOG.debug("Service instance retrieved from LoadBalancedRetryContext: was null. "+ "Reattempting service instance selection");}ServiceInstance previousServiceInstance = lbContext.getPreviousServiceInstance();lbRequest.getContext().setPreviousServiceInstance(previousServiceInstance);supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onStart(lbRequest));// 负载均衡client获取到服务实例信息retrievedServiceInstance = loadBalancerClient.choose(serviceId, lbRequest);if (LOG.isDebugEnabled()) {LOG.debug(String.format("Selected service instance: %s", retrievedServiceInstance));}lbContext.setServiceInstance(retrievedServiceInstance);}if (retrievedServiceInstance == null) {if (LOG.isWarnEnabled()) {LOG.warn("Service instance was not resolved, executing the original request");}org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(retrievedServiceInstance);supportedLifecycleProcessors.forEach(lifecycle -> lifecycle.onComplete(new CompletionContext<ResponseData, ServiceInstance, RetryableRequestContext>(CompletionContext.Status.DISCARD, lbRequest, lbResponse)));feignRequest = request;}else {if (LOG.isDebugEnabled()) {LOG.debug(String.format("Using service instance from LoadBalancedRetryContext: %s",retrievedServiceInstance));}// 生成带IP和端口的完整服务地址,并构建feign请求String reconstructedUrl = loadBalancerClient.reconstructURI(retrievedServiceInstance, originalUri).toString();feignRequest = buildRequest(request, reconstructedUrl);}}org.springframework.cloud.client.loadbalancer.Response<ServiceInstance> lbResponse = new DefaultResponse(retrievedServiceInstance);LoadBalancerProperties loadBalancerProperties = loadBalancerClientFactory.getProperties(serviceId);// 执行请求得到结果Response response = LoadBalancerUtils.executeWithLoadBalancerLifecycleProcessing(delegate, options,feignRequest, lbRequest, lbResponse, supportedLifecycleProcessors, retrievedServiceInstance != null,loadBalancerProperties.isUseRawStatusCodeInResponseData());int responseStatus = response.status();if (retryPolicy != null && retryPolicy.retryableStatusCode(responseStatus)) {if (LOG.isDebugEnabled()) {LOG.debug(String.format("Retrying on status code: %d", responseStatus));}byte[] byteArray = response.body() == null ? new byte[] {}: StreamUtils.copyToByteArray(response.body().asInputStream());response.close();throw new LoadBalancerResponseStatusCodeException(serviceId, response, byteArray,URI.create(request.url()));}return response;}, new LoadBalancedRecoveryCallback<Response, Response>() {@Overrideprotected Response createResponse(Response response, URI uri) {return response;}});
}

具体的发送请求流程可以详细debug看下,所有细节列出来可能会显得太冗长。过程涉及了很多工厂模式和委托模式,自己debug以下会更加清楚一些细节。比如发送http的客户端,默认是HttpsURLConnection发送请求,LoadBalancerClientConfiguration默认会创建RoundRobinLoadBalancer轮询负载均衡策略,可以看下spring-cloud-openfeign-core下的META-INF\spring.factories自动装备类,进一步结合项目实际情况还可以自定义Encoder,Decoder,ErrorDecoder等。

相关文章:

OpenFeign源码

openfeign是通过FeignClientFactoryBean生成动态代理对象的方式实现http客户端无感调用&#xff0c;可以做到像定义接口一样写http客户端调用代码。 配置Feign接口后&#xff0c;我们通常会在SpringBoot项目启动类上标记EnableFeignClients&#xff0c;这个是生成动态代理对象的…...

sql server索引优化语句

第一步 建一个测试表 --create table TestUsers --( -- Id int primary key identity(1,1), -- Username varchar(30) not null, -- Password varchar(10) not null, -- CreateDateTime datetime not null --)第二步 插入100w数据 大概1分钟执行时间 ----插入数据…...

深度学习之超分辨率算法——SRGAN

更新版本 实现了生成对抗网络在超分辨率上的使用 更新了损失函数&#xff0c;增加先验函数 SRresnet实现 import torch import torchvision from torch import nnclass ConvBlock(nn.Module):def __init__(self, kernel_size3, stride1, n_inchannels64):super(ConvBlock…...

16.2、网络安全风险评估技术与攻击

目录 网络安全风险评估技术方法与工具 网络安全风险评估技术方法与工具 资产信息收集&#xff0c;可以通过调查表的形式把我们各类的资产信息进行一个统计和收集&#xff0c;掌握被评估对象的重要资产分布&#xff0c;进而分析这些资产关联的业务面临的安全威胁以及存在的安全…...

【项目管理】GDB调试

gdb&#xff08;GNU Debugger&#xff09; 是 Linux 和嵌入式开发中最常用的调试工具之一&#xff0c;可以用来调试 C/C 程序、排查崩溃、分析程序流程等。在嵌入式开发中&#xff0c;gdb 还可以通过远程调试&#xff08;gdbserver&#xff09;调试目标设备上的程序。 这篇文章…...

ChatGPT生成接口测试用例(一)

用ChatGPT做软件测试 接口测试在软件开发生命周期中扮演着至关重要的角色&#xff0c;有助于验证不同模块之间的交互是否正确。若协议消息被恶意修改&#xff0c;系统是否能够恰当处理&#xff0c;以确保系统的功能正常运行&#xff0c;不会出现宕机或者安全问题。 5.1 ChatGP…...

2024 年 IA 技术大爆发深度解析

摘要&#xff1a; 本文旨在深入剖析 2024 年 IA 技术大爆发所引发的多方面反响。通过对产业变革、经济影响、就业市场、社会影响、政策与监管以及未来展望等维度的探讨&#xff0c;揭示 IA 技术在这一关键时期对全球各个层面带来的深刻变革与挑战&#xff0c;并提出相应的思考与…...

如何进行js后台框架搭建(树形菜单,面包屑,全屏功能,刷新功能,监听页面刷新功能)

框架功能是后台高亮不可缺少的功能&#xff0c;基本上所有的后台都需要框架功能&#xff0c;下面是我制作好的一个效果图 下面是我的框架里面功能的具体讲解&#xff0c;还有完整的代码示例 1.声明的变量 // 声明一个用于判断个人信息显示变量 let myes 0; // 声明一个用于切…...

多目标优化常用方法:pareto最优解

生产实际中的许多优化问题大都是多目标问题&#xff0c;举个例子&#xff1a;我们想换一份工资高、压力小、离家近的新工作&#xff0c;这里工资高、压力小、离家近就是我们的目标&#xff0c;显然这是一个多目标问题&#xff0c;那我们肯定想找到这三个目标同时最优的工作&…...

Vue.js实例开发-如何通过Props传递数据

props 是父组件用来传递数据给子组件的一种机制。通过 props&#xff0c;你可以将数据从父组件“传递”到子组件&#xff0c;并在子组件的模板和逻辑中使用这些数据。 1. 定义子组件并接收 props 首先&#xff0c;定义一个子组件&#xff0c;并在该组件中声明它期望接收的 pr…...

由popover框一起的操作demo问题

场景&#xff1a; 当popover框弹出的时候&#xff0c;又有MessageBox 提示&#xff0c;此时关闭MessageBox 提示&#xff0c;popover就关闭了。将popover改为手动激活&#xff0c;可以解决这个问题&#xff0c;但是会引起另外一个问题&#xff0c;之前&#xff08;click触发的时…...

人工智能ACA(四)--机器学习基础

零、参考资料 一篇文章完全搞懂正则化&#xff08;Regularization&#xff09;-CSDN博客 一、 机器学习概述 0. 机器学习的层次结构 学习范式&#xff08;最高层&#xff09; 怎么学 监督学习 无监督学习 半监督学习 强化学习 学习任务&#xff08;中间层&#xff0…...

uniapp图片数据流���� JFIF ��C 转化base64

1&#xff0c;后端返回的是图片数据流&#xff0c;格式如下 &#xfffd;&#xfffd;&#xfffd;&#xfffd; JFIF &#xfffd;&#xfffd;C 如何把这样的文件流转化为base64&#xff0c; btoa 是浏览器提供的函数&#xff0c;但在 小程序 环境中&#xff08;如微信小程序…...

django中cookie与session的使用

一、cookie cookie由服务器生成 &#xff0c;存储在浏览器中的键值对数据,具有不安全性&#xff0c;对应敏感数据应该加密储存在服务端每个域名的cookie相互独立浏览器访问域名为A的url地址&#xff0c;会把A域名下的cookie一起传递到服务器cookie可以设置过期时间 django中设…...

<项目代码>YOLO Visdrone航拍目标识别<目标检测>

项目代码下载链接 &#xff1c;项目代码&#xff1e;YOLO Visdrone航拍目标识别&#xff1c;目标检测&#xff1e;https://download.csdn.net/download/qq_53332949/90163918YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一…...

GhostRace: Exploiting and Mitigating Speculative Race Conditions-记录

文章目录 论文背景Spectre-PHT&#xff08;Transient Execution &#xff09;Concurrency BugsSRC/SCUAF和实验条件 流程Creating an Unbounded UAF WindowCrafting Speculative Race ConditionsExploiting Speculative Race Conditions poc修复flush and reload 论文 https:/…...

OPPO 数据分析面试题及参考答案

如何设计共享单车数据库的各个字段? 对于共享单车的数据库设计,首先考虑用户相关的字段。用户表可以包含用户 ID,这是一个唯一标识符,用于区分不同用户;姓名,记录用户的真实姓名;联系方式,比如手机号码,方便在出现问题时联系用户;注册时间,记录用户何时开始使用共享…...

腾讯云云开发 Copilot 深度探索与实战分享

个人主页&#xff1a;♡喜欢做梦 欢迎 &#x1f44d;点赞 ➕关注 ❤️收藏 &#x1f4ac;评论 目录 一、引言 二、产品介绍 三、产品体验过程 四、整体总结 五、给开发者的复用建议 六、对 AI 辅助开发的前景展望 一、引言 在当今数字化转型加速的时代&#xff0c;…...

Mac M1使用pip3安装报错

1. Mac系统使用pip3安装组件的时候报”外部管理环境”错误&#xff1a; error: externally-managed-environment 2.解决办法 去掉这个提示 1、先查看当前python版本&#xff1a; python3 --version 2、查找EXTERNALLY-MANAGED 文件的位置&#xff08;根据自己当前使用的pytho…...

flask-admin的modelview 实现list列表视图中扩展修改状态按钮

背景&#xff1a; 在flask-admin的模型视图&#xff08;modelview 及其子类&#xff09;中如果不想重构UI视图&#xff0c;那么就不可避免的出现默认视图无法很好满足需求的情况&#xff0c;如默认视图中只有“新增”&#xff0c;“编辑”&#xff0c;“选中的”三个按钮。 材…...

算法训练第二十三天|93. 复原 IP 地址 78. 子集 90. 子集 II

93. 复原 IP 地址--分割 题目 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&…...

imu相机EKF

ethzasl_sensor_fusion/Tutorials/Introductory Tutorial for Multi-Sensor Fusion Framework - ROS Wiki https://github.com/ethz-asl/ethzasl_msf/wiki...

【杂谈】虚拟机与EasyConnect运行巧设:Reqable助力指定应用流量专属化

场景 公司用的是EasyConnect&#xff0c;这个软件非常好用&#xff0c;也非常稳定&#xff0c;但是有个缺点&#xff0c;就是会无条件拦截本机所有流量&#xff0c;而且会加入所有运行的exe程序&#xff0c;实现流量全部走代理。 准备材料 一个windows/Linux 桌面版虚拟机Ea…...

【AI系列】Paddle Speech安装指南

文章目录 环境依赖1. 安装Python1.1 下载Python安装包1.2 安装gcc1.3 安装依赖库1.4 编译和安装Python1.5 配置环境变量 2. 安装PaddlePaddle3. 安装PaddleSpeech4. 运行PaddleSpeech5. 解决常见问题5.1 错误&#xff1a;libssl.so.1.1解决方法&#xff1a; 5.2 错误&#xff1…...

【AI学习】OpenAI推出o3,向AGI迈出关键一步

2024年12月21日&#xff0c;OpenAI在其为期12天发布会活动的最后一天&#xff0c;正式发布了备受期待的o3系列模型&#xff0c;包括o3和o3-mini。 o3 是一个非常强大的模型&#xff0c;在编码、数学以及 ARC-AGI 基准测试等多个基准上超过了 OpenAI 此前的 o1 模型&#xff08…...

深度学习0-前置知识

一、背景 AI最大&#xff0c;它的目的是通过让机器模仿人类进而超越人类&#xff1b; ML次之&#xff0c;它是AI的一个分支&#xff0c;是让机器模仿人类的一种方法。开发人员用大量数据和算法“训练”机器&#xff0c;让机器自行学会如何执行任务&#xff0c;它的成功取决于…...

Elasticsearch-分词器详解

什么是分词器 1、分词器介绍 对文本进行分析处理的一种手段&#xff0c;基本处理逻辑为按照预先制定的分词规则&#xff0c;把原始文档分割成若干更小粒度的词项&#xff0c;粒度大小取决于分词器规则。 常用的中文分词器有ik按照切词的粒度粗细又分为:ik_max_word和ik_smart&…...

Android-相对布局RelativeLayout

相对布局在摆放子视图位置时&#xff0c;按照指定的参考系来摆放子视图的位置&#xff0c;默认以屏幕左上角(0,0)位置作为参考系摆放位置 了解一下接下来都会以代码的方式可视化出来 属性 可选值 说明 layout_alignParentTop true/false 是否让控件相对于父容器顶部对齐 …...

Centos7, 使用yum工具,出现 Could not resolve host: mirrorlist.centos.org

在 CentOS 7 中使用 yum 工具时&#xff0c;如果出现 "Could not resolve host: mirrorlist.centos.org" 的错误&#xff0c;通常是因为默认的镜像源无法访问。以下是一些常用的解决方法&#xff1a; 检查网络连接&#xff1a;首先使用 ping 命令测试网络连接是否正常…...

在Linux中使用`scp`进行远程目录文件复制

在Linux系统中&#xff0c;scp&#xff08;安全复制协议&#xff09;是一个使用SSH&#xff08;安全外壳协议&#xff09;进行文件和目录安全传输的命令。它允许在远程主机之间复制文件和目录&#xff0c;具有很强的安全性&#xff0c;是一种常用的文件传输工具。以下是如何使用…...