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

SpringCloud Alibaba - Sentinel 限流规则(案例 + JMeter 测试分析)

目录

一、Sentinel 限流规则

1.1、簇点链路

1.2、流控模式

1.2.1、直接流控模式

1.2.2、关联流控模式

a)在 OrderController 中新建两个端点.

b)在 Sentinel 控制台中对订单查询端点进行流控

c)使用 JMeter 进行测试

d)分析结果

1.2.3、链路流控模式

a)在 OrderService 中添加 queryGoods 方法(不用实现业务).

b)在 OrderController 中创建两个端点,分别是 /order/query 和 /order/save

c)给 queryGoods 设置限流规则

d)使用 JMeter 进行测试

1.3、流控效果

1.3.1、快速失败

1.3.2、warm up

a)设置限流规则

b)使用 JMeter 进行测试

c)分析结果

1.3.3、排队等待

a)配置流控规则

b)使用 JMeter 进行测试

c)分析结果

1.3.4、热点参数限流

a)给热点参数限流对象加上 @SentinelResource 注解

c)使用 JMeter 进行测试

d)分析测试结果


一、Sentinel 限流规则


1.1、簇点链路

在 Sentinel 控制台中有这样一个选项.

 簇点链路,就是项目内的调用链路.

在 SpringMVC 中,请求先在 Controller 中路由到对应的方法,然后在方法中调用 Sevice 中的方法,最后调用对应的 Mapper 接口,这个过程就是一个调用链路. 

链路中被监控的每一个接口就是一个资源(RequestMapping 就是资源路由),默认情况下,会监控 SpringMVC 的每一个端点(也就是 Controller 中的每一个资源),因此 SpringMVC 中每一个端点就是调用链中的一个资源.

流量、熔断等都是针对簇点链路中的资源来设置的.

1.2、流控模式

1.2.1、直接流控模式

在访问 /order/{orderId} 后,打开 Sentinle 控制台,选择 “簇点链路” 就可以看到下图.

点击资源 /order/{orderId} 后面的流控按钮,就会弹出表单,之后就可以添加限流规则.

这里我们先来看一下,直接流控模式(打开高级选项后,即可看到默认选中)

  • 针对来源:默认为 default,也就是对所有的请求有效,这里一般不做修改.
  • 阈值类型:这里就是用 qps 即可,也就是每秒处理请求的最大个数.
  • 单机阈值:设置每秒处理请求的最大个数.
  • 流量模式:这里有三种,当前我们先看第一种,就是统计当前资源的请求,如果超过单机阈值,就进行限流.
  • 流控效果:快速失败是默认,是指到达阈值后,新请求会立刻被拒绝并抛出 FlowException 异常. 

这里设置单机阈值为 5.

然后通过 JMeter 测试工具实现每秒中发送 10 个请求,总共持续 2s.

设置 Http 请求

启动脚本,观察运行结果,可以看到差不多是每 5 条成功,5条失败.

在 Sentinel 中就可以观察到QPS 的通过和拒绝情况.

1.2.2、关联流控模式

关联模式:用来统计与当前资源相关的另一个资源,触发阈值时,对当前资源进行限流.

举个例子,你在淘宝上买东西,完成支付以后会进行修改订单状态的业务,与此同时,你还要查看订单,但是 查询 和 修改 都会争抢数据库的锁,产生竞争.  根据业务需求是,优先进行更新订单业务,之后进行用户查询业务,因此当修改订单业务触发阈值时,就需要对查询订单业务进行限流.

可以看出,关联流控模式的适用场景满足以下条件:

  • 两个资源有竞争关系.
  • 一个优先级高,一个优先级低.

这里用一个案例来演示:在 OrderController 中创建两个端点,/order/query 和 /order/update ,不用实现业务,接着配置流控规则,当 /order/update 资源被访问的 QPS 超过 5 时,对 /order/query 请求限流.

具体实现步骤如下:

a)在 OrderController 中新建两个端点.

创建 /order/query 和 /order/update 端点.

    @RequestMapping("/query")public String queryOrder() {return "订单查询成功!";}@RequestMapping("update")public String updateOrder() {return "订单修改成功!";}

b)在 Sentinel 控制台中对订单查询端点进行流控

单机阈值设置为 5,流控模式选择 “关联”,关联资源就是 /order/update.

也就是说,当 /order/update 达到阈值以后,再发送 /order/query 请求就会抛出异常.

c)使用 JMeter 进行测试

设置每秒发送 10 个请求,总共发 1000 个请求.

这里对 /order/update 发送请求即可.

d)分析结果

JMeter 运行期间,手动发送一个 /order/query 请求,会发现请求失败.

这是因为此时 /order/update 已经超出阈值,此时再发送 /order/query 请求,那么两个请求的总数加起来肯定也是超过阈值的,因此由于设定了 “流控效果” 为快速失败,所以这里抛出异常.

1.2.3、链路流控模式

链路模式:只针对从指定链路访问到当前指定资源的请求做统计,如果超过阈值,则对当前链路进行限流.

例如现在有两条请求链路:

  • /test1 -> /tools
  • /test2 -> /tools

如果只希望统计从 /test2 进入 /tools 请求,那么一旦超过阈值(假设阈值为 5),只对此线路进行限流,则可以进行如下配置:

这里用一个案例来演示: 现有 查询订单 和 创建订单 业务,两者都需要进行查询商品业务.  需求是指针对 查询订单 -> 查询商品 的请求进行统计并设置流控(阈值为 2).

具体实现步骤如下:

a)在 OrderService 中添加 queryGoods 方法(不用实现业务).

用来表示两个 查询订单 和 创建订单 两个业务都要访问的 查询商品业务.

    @SentinelResource("goods") //设置资源名称public void queryGoods() {//使用 err 是为了高亮显示,方便观察日志信息System.err.println("查询订单成功!");}

 注意!!!

1. Sentinel 默认值只标记 Controller 中方法为资源,如果想要标记其他方法,需要使用 @SentinelResource 注解来标识资源名.

2. 另外!Sentinel 默认只对 Controller 中的方法做 context 整合,导致链路模式的流控失效,需要 application.yml 中添加如下配置:

spring:cloud:sentinel:web-context-unify: false # 关闭context整合

触发两个端点,就可以看到在 “簇点链路” 中 goods 为两个端点资源的子资源,如下

b)在 OrderController 中创建两个端点,分别是 /order/query 和 /order/save

两个端点中都需要调用 Order Service 中的 queryGoods 方法.

    @RequestMapping("/query")public String queryOrder() {orderService.queryGoods();return "订单查询成功!";}@RequestMapping("/save")public String saveOrder() {orderService.queryGoods();return "保存订单成功!";}

c)给 queryGoods 设置限流规则

针对从 /order/query -> queryGoods 此链路进行限流,阈值为 2.

d)使用 JMeter 进行测试

使用 JMeter 对两个端点都进行 每秒发送 4 个请求.

可以看到在 /order/save -> goods 这个链路中请求都成功了.

而 /order/query -> goods 这条链路中,被流控模式限制.

在控制台上也可以看到 goods 的 qps 拒绝情况(每 8 个 qps 中有 2 个被拒绝,拒绝的就是 /order/query 这条链路超过阈值的请求). 

1.3、流控效果

1.3.1、快速失败

快速失败:达到阈值以后,新的请求会立即拒绝并抛出 FlowException 异常,是默认的处理方式

这种方式在演示 流控模式 中都用是这个效果,这里就不再赘述了.

1.3.2、warm up

warm up:预热模式,对超出阈值的请求同样是拒绝并抛出异常. 但是这种模式的阈值会动态变化,从一个比较小的值逐渐增加到设置的最大阈值(这里的预热时间是需要进行设置的).

请求阈值的初始值是 设置的最大阈值 / coldFactor ,而 coldFactor 默认值是 3.

例如我设置 qps 的最大阈值为 10,预热时间是 5秒,那么初始的阈值就是 10 / 3,取整后就是 3,之后再 5秒 以后逐渐增长到 10.

这里我通过一个案例来演示:给 /order/{orderId} 这个资源设置限流,最大 qps 为 10,使用 warm up 效果,预热时常为 5 秒.

具体步骤如下:

a)设置限流规则

b)使用 JMeter 进行测试

c)分析结果

在控制台中可以看到,刚开始的 qps 只通过 3(初始阈值计算后得到的)符合预期,之后 5 秒中内,qps 通过数目逐渐上升,直到 qps 通过数目 = 10 以后稳定下来.

1.3.3、排队等待

排队等待这种方式,当请求超过 qps 阈值之后,不会直接抛出异常,而是让多出来的请求先进入到一个队列中进行排队,然后按照阈值允许的时间间隔依次执行,如果队列中所有的请求处理时间加起来刚好等于等待时间,那么,此时新来的请求就会被拒绝.

例如,设置 qps = 5,意味着每 200ms 处理一个队列中的请求. 如果设置 超时时间 为 2000ms,那么意味着队列中如果有 10 个请求,就会把时间占满,此时如果再来新的请求,就会被拒绝.

这里用一个案例来演示:给 /order/{orderId} 这个资源设置限流,最大 qps 为 10,利用排队的流控效果,超时时间设置为 5s.

a)配置流控规则

b)使用 JMeter 进行测试

c)分析结果

该开始的时候,都处理成功了是因为新加入的请求都会先进入队列,并且队头的请求也被处理掉了。

而后来的由于请求来的速度大于队列处理的速度,因此队列终有一日会占满超时时间,因此出现了拒绝 qps 的情况.

最后请求请求发完了,队列不停的再处理请求,就不会超过超时时间,因此最后的 qps 全部为通过.

1.3.4、热点参数限流

之前的限流是统计访问某个资源的所有请求,判断是否超过 qps 阈值,而热点参数限流是统计 参数值 相同的请求,是否超过 qps 阈值.

例如,对 hot 这个资源的 0 号参数(第一个参数)做统计,每 1 秒相同参数的请求数不能超过 5,如下图.

另外,在热点参数限流的高级选项中,还可以对部分参数进行外额限制

参数类型:参数索引指向的参数是什么数据类型(只支持 Java 数据类型).

参数值:传入的参数值.

限流阈值:窗口时长内,qps 的最大阈值.

例如,如果参数值是 100,则每秒允许的 qps 为 10,如下图.

这里我用一个案例来演示:给 /order/{orderId} 这个资源添加热点参数限流,规则如下:

  • 默认的热点参数规则是每 1 秒请求量不超过 2.
  • 给 102 这个参数设置例外:每 1 秒请求量不超过 4.
  • 给 103 这个参数设置例外:每 1 秒请求量不超过 10.

具体实现步骤如下:

a)给热点参数限流对象加上 @SentinelResource 注解

注意:热点参数限流对默认的 SpringMVC资源无效,因此需要加上 @SentinelResource 指定资源并命名.

    @SentinelResource("hot")@GetMapping("{orderId}")public Order queryOrderByUserId(@PathVariable("orderId") Long orderId) {// 根据id查询订单并返回return orderService.queryOrderById(orderId);}

b)配置限流规则

c)使用 JMeter 进行测试

发送路径有三个,如下:

d)分析测试结果

可以看到 101 这个请求,按照默认的限流规则, qps = 2 ,如下.

102 这个请求,按照高级设置,例外配置 qps =  4,如下.

103 这个请求,按照高级设置,例外配置 qps = 10.  因为每秒请求数为 5 个,因此请求全部通过.

在 hot 资源监控中也可以看到,每次 11 ,拒绝 4.

是因为通过的只有 101 请求默认规则的 2 个,加上 102 请求例外设置的 4 个,再加上 103 请求例外设置的 5 个,总共加起来成功就是 11 个.

相关文章:

SpringCloud Alibaba - Sentinel 限流规则(案例 + JMeter 测试分析)

目录 一、Sentinel 限流规则 1.1、簇点链路 1.2、流控模式 1.2.1、直接流控模式 1.2.2、关联流控模式 a)在 OrderController 中新建两个端点. b)在 Sentinel 控制台中对订单查询端点进行流控 c)使用 JMeter 进行测试 d)分…...

uniapp 条件编译 APP 、 H5 、 小程序

一、#ifdef、#ifndef、 #endif三者的区别、 标识作用#ifdef仅在某个平台上使用#ifndef在除了这个平台的其他平台上使用(非此平台使用)#endif结束条件编译 二、平台标识 标识平台APP-PLUS5AppMP微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序MP-WEIXIN微…...

深度学习——权重衰减(weight_decay)

深度学习——权重衰减(weight_decay) 文章目录 前言一、权重衰减1.1. 范数与权重衰减1.2. 高维线性回归1.3. 从零开始实现1.3.1.初始化模型参数1.3.2. 定义L₂范数惩罚1.3.3. 定义训练代码实现1.3.4. 不管正则化直接训练1.3.5. 使用权重衰减 1.4. 简洁实现 总结 前言…...

nignx如何部署让前端不用清缓存就可以部署

在Nginx中,可以使用以下方法来部署前端应用程序,使前端用户无需清空缓存即可进行部署: 1、使用版本号:在前端应用程序的构建过程中,可以添加一个独特的版本号到应用程序的名称中。每次部署时,将版本号更新…...

CSS3实现动画加载效果

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>加载效果</title><link rel"style…...

springboot定时任务Scheduled使用和弊端分析

1.springboot定时任务Scheduled使用说明: (1)创建定时任务类 import com.one.utils.DateUtil; import org.springframework.beans.factory.annotation.Autowired; import...

openGauss学习笔记-93 openGauss 数据库管理-访问外部数据库-oracle_fdw

文章目录 openGauss学习笔记-93 openGauss 数据库管理-访问外部数据库-oracle_fdw93.1 编译oracle_fdw93.2 使用oracle_fdw93.3 常见问题93.4 注意事项 openGauss学习笔记-93 openGauss 数据库管理-访问外部数据库-oracle_fdw openGauss的fdw实现的功能是各个openGauss数据库及…...

【Git】Git下载安装环境配置 下载速度慢的解决方案

这里写自定义目录标题 介绍一、下载官网下载镜像站 二、安装安装成功 三、Git三种界面介绍Git cmd界面展示git bash界面展示git GUI界面展示 四、环境配置配置流程1、打开环境变量界面2、添加环境变量 /删除环境变量3、在变量中找到Git\cmd的值就表示配置成功4、没有找到点击新…...

常见源协议介绍

开源协议&#xff08;Open Source License&#xff09;是一种法律文档&#xff0c;用于规定如何使用、修改和分发开源软件和其他开源项目的规则和条件。这些协议允许创作者或组织将其创造的代码或作品以开放源代码的形式共享给他人&#xff0c;以促进协作、创新和知识共享。常见…...

大数据概述(林子雨慕课课程)

文章目录 1. 大数据概述1.1 大数据概念和影响1.2 大数据的应用1.3 大数据的关键技术1.4 大数据与云计算和物联网的关系云计算物联网 1. 大数据概述 大数据的四大特点&#xff1a;大量化、快速化、多样化、价值密度低 1.1 大数据概念和影响 大数据摩尔定律 大数据由结构化和非…...

ES6 class类关键字super

super关键字 在 JavaSCript 中&#xff0c;能通过 extends 关键字去继承父类 super 关键字在子类中有以下用法&#xff1a; 当成函数调用 super() 作为 "属性查询" super.prop 和 super[expr] super() super 作为函数调用时&#xff0c;代表父类的构造函数。 ES6 要求…...

C++并发与多线程(4) | 传递临时对象作为线程参数的一些问题Ⅰ

一、陷阱1 写一个传递临时对象作为线程参数的示例: #include <iostream> #include <vector> #include <thread> using namespace std;void myprint(const int& i, char* pmybuf) {cout << i << endl;cout << pmybuf << endl;r…...

CentOS Integration SIG 正式成立

导读CentOS 董事会已批准成立 CentOS Integration Special Interest Group (SIG)。该小组旨在帮助那些在 Red Hat Enterprise Linux (RHEL) 或特别是其上游 CentOS Stream 上构建产品和服务的人员&#xff0c;验证其能否在未来版本中继续运行。 红帽 RHEL CI 工程师 Aleksandr…...

智能AI系统源码ChatGPT系统源码+详细搭建部署教程+AI绘画系统+已支持OpenAI GPT全模型+国内AI全模型

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统&#xff0c;支持OpenAI GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如何搭建部署AI创作Chat…...

软考程序员考试大纲(2023)

文章目录 前言一、考试说明1.考试目标2.考试要求3&#xff0e;考试科目设置 二、考试范围考试科目1&#xff1a;计算机与软件工程基本知识1&#xff0e;计算机科学基础2&#xff0e;计算机系统基础知识3&#xff0e;系统开发和运行知识4&#xff0e;网络与信息安全基础知识5&am…...

【重拾C语言】七、指针(一)指针与变量、指针操作、指向指针的指针

目录 前言 七、指针 7.1 指针与变量 7.1.1 指针类型和指针变量 7.1.2 指针所指变量 7.1.3 空指针、无效指针 7.2 指针操作 7.2.1 指针的算术运算 7.2.2 指针的比较 7.2.3 指针的递增和递减 7.3 指向指针的指针 前言 指针是C语言中一个重要的概念正确灵活运用指针 可…...

Kafka源码简要分析

目录 一、生产者的初始化流程 二、生产者到缓冲队列的流程 三、Sender拉取数据到Kafka流程 四、消费者初始化 五、主题订阅原理 六、消费者抓取数据原理 七、消费者组初始化 八、消费者组消费流程 九、提交offset原理 一、生产者的初始化流程 首先获取事务id和客户端…...

react 按住ctrl键,点击时会出现菜单的问题修复

问题描述&#xff1a;我需要按住crtl键&#xff0c;然后鼠标点击后做一些逻辑操作&#xff0c;但是出现如下问题 问题一&#xff1a;按住ctrl键后&#xff0c;点击时不触发click事件&#xff0c;只触发 mousedown和mouseup事件。 问题二&#xff1a;按住ctrl键点击时出现菜单…...

【虚拟机栈】

文章目录 1. 虚拟机栈概述2. 局部变量表(Local Variables)3. 操作数栈4. 动态链接4.1 方法的调用&#xff1a;解析与分配 5. 方法返回地址6. 栈的相关面试题 1. 虚拟机栈概述 每个线程在创建时都会创建一个虚拟机栈&#xff0c;其内部保存一个个的栈帧&#xff08;Stack Frame…...

Linux系列讲解 —— 【fsck】检查并修复Linux文件系统

当文件系统出现损坏时&#xff0c;例如文件无法查看&#xff0c;删除等&#xff0c;可以使用 fsck&#xff08;File System Consistency Check&#xff09;进行修复。但是需要注意fsck在修复时&#xff0c;如果检查出某个文件有问题&#xff0c;可能会向用户请求删除。所以&…...

gitlab突然提示我要输入密码了。

用了很长时间的一个gitlab库&#xff0c;今天提交代码的时候突然提示我输入密码了&#xff0c;并且用户还是gitxx.xx.xx.xx的&#xff0c;瞬间懵逼。 想想原因&#xff0c;可能是因为我不久前设置了本地对另外一个git库的远程访问&#xff0c;用的是ssh&#xff0c;操作过程中可…...

业务测试常见问题(一)

如何多维度的分析一个需求&#xff1f; 功能维度&#xff1a;需求中所描述的功能是否实现&#xff0c;与用户的需求是否一致&#xff0c;是否完整符合用户的需求等。 安全性维度&#xff1a;是否有安全漏洞&#xff0c;是否存在未授权访问漏洞等&#xff0c;以保证系统的安全性…...

IntelliJ IDEA失焦自动重启服务的解决方法

IDEA 热部署特性 热部署&#xff0c;即应用正属于运行状态时&#xff0c;我们对应用源码进行了修改更新&#xff0c;在不重新启动应用的情况下&#xff0c;可以能够自动的把更新的内容重新进行编译并部署到服务器上&#xff0c;使修改立即生效。 现象 在使用 IntelliJ IDEA运…...

终端准入控制系统,保障企业内网安全的关键防线

随着网络技术的不断发展&#xff0c;企业面临的安全威胁也越来越多。终端作为承载企业业务的媒介&#xff0c;对内网资产安全有着重要影响。确保内网终端&#xff08;如PC、BYOD、IoT等&#xff09;能够得到统一管理&#xff0c;对保护内网安全很有必要。终端准入控制作为一种有…...

mysql-执行计划

1. 执行计划表概述 id相同表示加载表的顺序是从上到下。 id不同id值越大&#xff0c;优先级越高&#xff0c;越先被执行。id有相同&#xff0c;也有不同&#xff0c;同时存在。 id相同的可以认为是一组&#xff0c;从上往下顺序执行&#xff1b;在所有的组中&#xff0c;id的值…...

金蝶云星空和旺店通·企业奇门接口打通对接实战

金蝶云星空和旺店通企业奇门接口打通对接实战 接入系统&#xff1a;金蝶云星空 金蝶K/3Cloud&#xff08;金蝶云星空&#xff09;是移动互联网时代的新型ERP&#xff0c;是基于WEB2.0与云技术的新时代企业管理服务平台。金蝶K/3Cloud围绕着“生态、人人、体验”&#xff0c;旨在…...

在服务器上使用nginx改变前端项目请求的url

location /app-dev {rewrite ^/app-dev/(.*) /$1 break;proxy_pass http://152.136.36.251:9999;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr; } location /请求后缀 { rewrite ^/app-dev/(.*) /$1 break; proxy_pass 想要的请求后端的url; …...

【学习笔记】莫比乌斯反演

退役OIer回来受虐啦 一些定义 μ ( x ) { 1 x > 1 ( − 1 ) n x ∏ i 1 n P i 0 o t h e r w i s e \mu(x) \begin{cases} 1 & x > 1 \\ (-1)^n & x \prod _ {i1} ^ {n} P_{i}\\ 0 & otherwise \end{cases} μ(x)⎩ ⎨ ⎧​1(−1)n0​x>1x∏i1n​Pi…...

一款构建Python命令行应用的开源库

1 简介 当我们编写 Python 程序时&#xff0c;我们经常需要与用户进行交互&#xff0c;接收输入并输出结果。Python 提供了许多方法来实现这一点&#xff0c;其中一个非常方便的方法是使用 typer 库。typer 是一个用于构建命令行应用程序的 Python 库&#xff0c;它使得创建命令…...

10-Node.js模块化

01.模块化简介 目标 了解模块化概念和好处&#xff0c;以及 CommonJS 标准语法导出和导入 讲解 在 Node.js 中每个文件都被当做是一个独立的模块&#xff0c;模块内定义的变量和函数都是独立作用域的&#xff0c;因为 Node.js 在执行模块代码时&#xff0c;将使用如下所示的…...

网站面试通知表格怎么做/360建站和凡科哪个好

Percona Server 刚在 2013 DeveloperWeek Best of Tech award 中赢得最具创新的 SQL 技术奖。 我们很骄傲的接受了这个奖项&#xff0c;该奖项的评选是由独立的评审小组选出&#xff0c;非常感谢你们对 Percona Server 的投票。 Percona 为 MySQL 数据库服务器进行了改进&#…...

教育网站开发用例图/seo诊断方法步骤

jna jni我最近偶然发现了一个不错的框架&#xff0c;如果您不得不使用本机代码的话&#xff0c;您会喜欢的。 在此框架之前&#xff0c;如果需要调用本机代码&#xff0c;则可以使用JNI 。 JNI使用了一个经过验证的但复杂且容易出错的过程。 首先&#xff0c;您像往常一样编写J…...

宁波奢华做网站排名/seo外包

Java 实例 - 获取异常的堆栈信息以下实例演示了使用异常类的 printStack() 方法来获取堆栈信息&#xff1a;/*author by w3cschool.ccMain.java*/public class Main{public static void main (String args[]){int array[]{20,20,40};int num115,num210;int result10;try{result…...

一个公司能备案多个网站吗/搜索引擎实训心得体会

int main(int argc , char *argv[])//测试调用函数 {const char *env_init[] {"USERunkown","PATHmypath",NULL};pid_t pid;if( (pid fork()) < 0 )err_sys("fork error");else if(pid 0)//这个很牛逼的样子哦,还可以这样玩,在子函数里面调…...

免费建站软件排行榜/网址大全下载到桌面

注解注入失败有很多种情况&#xff0c;我这里列举其中一种 我直接删掉了SpringBootApplication()括号中的代码&#xff0c;直接就解决了 你可以看看你的启动注解中是否添加了别的代码 我这个比较偏&#xff0c;希望不会有人用到 你的问题可能也会和我相似&#xff0c;启动注…...

家装公司网站建设网站/百度识图在线入口

学习适配器有一段时间了,现在对BaseAdapter的优化和要是项目中用到的适配其很多的话,完全可以建立一个SimpleBaseAdapter(继承自BaseAdapter),方便扩展. 主布局代码: 1 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"2 xmlns:tool…...