spring.expression 随笔0 概述
0. 我只是个普通码农,不值得挽留
Spring SpEL表达式的使用
常见的应用场景:分布式锁的切面借助SpEL来构建key
比较另类的的应用场景:动态校验
个人感觉可以用作控制程序的走向,除此之外,spring的一些模块的自动配置类,也会在@Conditional注解中使用SpEL来实现有条件的加载特定的bean.
1. UML
1.1 ExpressionParser
解释器设计模式的体现了
单纯的(非模板表达式)spel表达式将通过 SpelExpressionParser 创建 InternalSpelExpressionParser, 来实现 parseExpression() 的底层逻辑.
// org.springframework.expression.spel.standard.InternalSpelExpressionParser#doParseExpression@Overrideprotected SpelExpression doParseExpression(String expressionString, @Nullable ParserContext context)throws ParseException {try {this.expressionString = expressionString;// 1.对相关的符号进行分词Tokenizer tokenizer = new Tokenizer(expressionString);this.tokenStream = tokenizer.process();this.tokenStreamLength = this.tokenStream.size();this.tokenStreamPointer = 0;this.constructedNodes.clear();// 2.构建 ASTSpelNodeImpl ast = eatExpression();Assert.state(ast != null, "No node");Token t = peekToken();if (t != null) {throw new SpelParseException(t.startPos, SpelMessage.MORE_INPUT, toString(nextToken()));}Assert.isTrue(this.constructedNodes.isEmpty(), "At least one node expected");// 3. 返回创建好的表达式实例return new SpelExpression(expressionString, ast, this.configuration);}catch (InternalParseException ex) {throw ex.getCause();}}
1.2 ParserContext
- 这里前后缀例如:支持模板表达式的实现类
TemplateParserContext
使用了#{
、}
- TemplateAwareExpressionParser(支持模板的ExpressionParser实现类),根据
ParserContext.isTemplate()
来决定处理流程 - 有必要给出模板表达式的定义: 可以理解为多个、多种表达式的组合
// org.springframework.expression.common.TemplateAwareExpressionParser#parseExpression(java.lang.String, org.springframework.expression.ParserContext)@Overridepublic Expression parseExpression(String expressionString, @Nullable ParserContext context) throws ParseException {if (context != null && context.isTemplate()) {return parseTemplate(expressionString, context);}else {return doParseExpression(expressionString, context);}}
1.3 Expression
转换并获取表达式对应的数值
1.4 EvaluateContext
- 支持间接的关联 beanFactory ,来注入spring bean
- 该功能很好的体现了 spring-expression 的独立性
- 支持往该上下文中加入静态方法、java bean
- 与 Expression.getValue() 有较大的关系
2. test-classes
因为要debug beanFactory关联的 parser,便懒得构造applicationContext,直接@SpringbootTest 启动容器了
@DisplayName("Spring Expression Language")
@SpringBootTest
public class SpELTest {@Value("#{testBean.value}")String value;@AutowiredApplicationContext appCtx;SpelExpressionParser parser;StandardEvaluationContext stdEvaCtx;@PostConstructprivate void postConstruct() throws NoSuchMethodException {parser = new SpelExpressionParser();// rootObjectstdEvaCtx = new StandardEvaluationContext(new TestBean("rootValue", null));// variablestdEvaCtx.setVariable("testBean", this.appCtx.getBean("testBean"));Method parseInt = Integer.class.getDeclaredMethod("valueOf", String.class);stdEvaCtx.registerFunction("doValueOf", parseInt);stdEvaCtx.setBeanResolver(new BeanFactoryResolver(this.appCtx));}@DisplayName("注解方式")@Testvoid t0() {// 这个上下文其实就是表达式、变量的容器(缓存)System.err.println(this.value);}@DisplayName("编码方式")@Testvoid t1() {// 不需要 {}// spring security 中也使用编码的方式解析权限注解 @PrePreAuthorizeExpression expression = parser.parseExpression("#testBean.value");System.err.println(expression.getValue(this.stdEvaCtx));}@DisplayName("运算")@Nestedclass Count {@DisplayName("字面量")@Testvoid t0() {// 上下文中找不到这个变量,报错:// spel.SpelEvaluationException: EL1007E: Property or field 'test' cannot be found on null// System.err.println("找不到变量="+parser.parseExpression("test").getValue(String.class));// 字符串System.err.println("字符串1=" + parser.parseExpression("'test'").getValue(String.class));System.err.println("字符串2=" + parser.parseExpression("\"test\"").getValue(String.class));// 数字System.err.println("int=" + parser.parseExpression("1").getValue(Integer.class));System.err.println("long=" + parser.parseExpression("1L").getValue(long.class));System.err.println("float=" + parser.parseExpression("1.1").getValue(Float.class));System.err.println("double=" + parser.parseExpression("1.1E+1").getValue(double.class));System.err.println("hex=" + parser.parseExpression("0xf").getValue(int.class));// 布尔System.err.println("bool=" + parser.parseExpression("false").getValue(boolean.class));// nullSystem.err.println(parser.parseExpression("null").getValue());}@DisplayName("算数")@Testvoid t1() {System.err.println("3+2=" + parser.parseExpression("3+2").getValue(Integer.class));System.err.println("3-2=" + parser.parseExpression("3-2").getValue(Integer.class));System.err.println("3*2=" + parser.parseExpression("3*2").getValue(Integer.class));System.err.println("3/2=" + parser.parseExpression("3/2").getValue(Integer.class));System.err.println("3%2=" + parser.parseExpression("3%2").getValue(Integer.class));System.err.println("3^2=" + parser.parseExpression("3^2").getValue(Integer.class));}@DisplayName("关系运算")@Testvoid t2() {System.err.println("3==2=" + parser.parseExpression("3==2").getValue(Boolean.class));System.err.println("3 == 2=" + parser.parseExpression("3 == 2").getValue(Boolean.class));System.err.println("3 ge 2 =" + parser.parseExpression("3 ge 2").getValue(boolean.class));System.err.println("3 LT 2 = " + parser.parseExpression("3 LT 2").getValue(boolean.class));// SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'NE2'// System.err.println("3NE2 = "+parser.parseExpression("3NE2").getValue(boolean.class));// 并不能返回 int:0、1,会抛出异常System.err.println("2 between {1, 2}=" + parser.parseExpression("2 between {1, 2}").getValue(Boolean.class));// SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'le(<=)'// System.err.println("1<2<=2="+parser.parseExpression("1<2<=3").getValue(Boolean.class));}@DisplayName("逻辑运算")@Testvoid t3() {System.err.println("2>1 and false = " + parser.parseExpression("2>1 and false").getValue(boolean.class));System.err.println("2>1 && false = " + parser.parseExpression("2>1 && false").getValue(Boolean.class));// SpelParseException: EL1041E: After parsing a valid expression, there is still more data in the expression: 'factory_bean_ref(&)'// System.err.println("2>1 & false = "+parser.parseExpression("2>1 & false").getValue(Boolean.class));System.err.println("2>1 or NOT false and (! NOT false || 1==1) = " + parser.parseExpression("2>1 or NOT false and (! NOT false || 1==1)").getValue(Boolean.class));}@DisplayName("三目运算")@Testvoid t4() {System.err.println("3 > 2 ? true : false = " + parser.parseExpression("3 > 2 ? true : false").getValue(boolean.class));}@DisplayName("elivis")@Testvoid t5() {System.err.println("null ?: 'false' = " + parser.parseExpression("null ?: 'false'").getValue(Boolean.class));System.err.println("null ?: 'false' = " + parser.parseExpression("null ?: 'false'").getValue(String.class));}@DisplayName("正则")@Testvoid t6() {System.err.println("" + parser.parseExpression("'123' matches '\\d{3}'").getValue(boolean.class));System.err.println("" + parser.parseExpression("123 matches '\\d{3}'").getValue(Boolean.class));}@DisplayName("instanceof")@Testvoid t7() {System.err.println("'123' instanceof T(String) = " + parser.parseExpression("'123' instanceof T(String)").getValue(Boolean.class));System.err.println("123 instanceof T(String) = " + parser.parseExpression("123 instanceof T(java.lang.String)").getValue(Boolean.class));}}@DisplayName("类型")@Nestedclass Type {@DisplayName("class")@Testvoid t0() {// java.lang 以外的类均需要全限定名System.err.println(parser.parseExpression("T(String)").getValue(Class.class));System.err.println(parser.parseExpression("T(java.util.Map)").getValue(Class.class));// 访问 静态的属性、方法System.err.println(parser.parseExpression("T(Integer).MAX_VALUE").getValue(int.class));System.err.println(parser.parseExpression("T(Integer).parseInt(3)").getValue(Integer.class));}@DisplayName("instance")@Testvoid t1() {// java.lang 包 同理System.err.println(parser.parseExpression("new String('苹果一样的甜')").getValue(String.class));System.err.println(parser.parseExpression("new java.util.Date()").getValue(Date.class));}@DisplayName("reference")@Testvoid t2() {System.err.println("#testBean.value=" + parser.parseExpression("#testBean.value").getValue(stdEvaCtx, String.class));System.err.println("#this.value=" + parser.parseExpression("#this.value").getValue(stdEvaCtx, String.class));System.err.println("#root.value=" + parser.parseExpression("#root.value").getValue(stdEvaCtx, String.class));// rootObject缺省时,访问其属性,不能加#前缀System.err.println("(root属性可以省略#root)value=" + parser.parseExpression("value").getValue(stdEvaCtx, String.class));}@DisplayName("assign")@Testvoid t3() {System.err.println("#testBean.value=newValue --> " + parser.parseExpression("#testBean.value='newValue'").getValue(stdEvaCtx, String.class));System.err.println("#this.value=newThisValue --> " + parser.parseExpression("#this.value='newThisValue'").getValue(stdEvaCtx, String.class));System.err.println("#root.value=newRootValue --> " + parser.parseExpression("#root.value='newRootValue'").getValue(stdEvaCtx, String.class));System.err.println("value=newValue --> " + parser.parseExpression("value='newValue'").getValue(stdEvaCtx, String.class));}@DisplayName("func")@Testvoid t4() {System.err.println(parser.parseExpression("#doValueOf('20').byteValue()").getValue(stdEvaCtx, Byte.class));}@DisplayName("对象属性获取 及 安全导航")@Testvoid t5() {System.err.println(parser.parseExpression("value").getValue(stdEvaCtx, String.class));// Value 可以,Value 不得行(首字母不敏感)System.err.println(parser.parseExpression("Value").getValue(stdEvaCtx, String.class));// 支持groovy的elivis表达式// 安全导航运算符前面的#root可以省略,但后面的#root不可省略System.err.println(parser.parseExpression("#root?.#root").getValue(stdEvaCtx, TestBean.class));System.err.println(parser.parseExpression("value?.#root.value").getValue(stdEvaCtx, String.class));// SpelParseException: Expression [username?.'核弹拉链'] @8: EL1049E: Unexpected data after '.': ''核弹拉链''// SpEL引入了Groovy语言中的安全导航运算符"(对象|属性)?.属性"// 常量显然不得行// System.err.println(parser.parseExpression("username?.'核弹拉链'").getValue(stdEvaCtx, String.class));}@DisplayName("对象方法调用")@Testvoid t6() {System.err.println(parser.parseExpression("value.substring(1, 6).toUpperCase()").getValue(stdEvaCtx, String.class));System.err.println(parser.parseExpression("toString()").getValue(stdEvaCtx, String.class));}@DisplayName("bean引用(BeanFactoryResolver)")@Testvoid t7() {// @BeanName// EvaluationContext.setBeanResolver() 需要借助 beanFactorySystem.err.println(Jsons.NO_OP.stringify(parser.parseExpression("@systemProperties").getValue(stdEvaCtx, Properties.class)));System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("@testBean").getValue(stdEvaCtx, TestBean.class)));}}@DisplayName("集合")@Nestedclass Collect {@DisplayName("内联数组")@Testvoid t0() {System.err.println(Arrays.toString(parser.parseExpression("new int[2]{1, 2}").getValue(int[].class)));System.err.println(Arrays.toString(parser.parseExpression("new String[2][2]").getValue(String[][].class)));// 不支持多维数组创建同时,做初始化System.err.println(Arrays.toString(parser.parseExpression("new String[2][2]{'1','2'},{'3','4'}").getValue(String[][].class)));}@DisplayName("内联集合")@Testvoid t1() {System.err.println(parser.parseExpression("{}").getValue(List.class));// java.util.Collections$UnmodifiableRandomAccessListSystem.err.println(parser.parseExpression("{1, 2,3}").getValue(List.class).getClass().getName());// 此时的 List<List> .class = java.util.ArrayList// 存在非字面量表达式时,集合类型将转为原始类型(可修改的集合)System.err.println(parser.parseExpression("{{1+2,2+4},{3,4+4}}").getValue(List.class).getClass().getName());}@DisplayName("数组、集合、字典元素访问")@Testvoid t2() {System.err.println(parser.parseExpression("[0]").getValue(new int[]{1, 2, 3}, Integer.class));System.err.println(parser.parseExpression("{1, 2, 3}[0]").getValue(int.class));System.err.println(parser.parseExpression("[0]").getValue(Lists.newArrayList(1, 2, 3), int.class));Map<String, Integer> map = Maps.newHashMap();map.put("weng", 4);map.put("chong", 5);map.put("yu", 2);System.err.println(parser.parseExpression("['chong']").getValue(map, int.class));}// 很像 streamApi.peek().collect(toList())@DisplayName("数组、集合、字典 转换")@Testvoid t3() {// array|list|map.![表达式]System.err.println(Arrays.toString(parser.parseExpression("#root.![#this+1]").getValue(new int[]{1, 2, 3}, int[].class)));System.err.println(parser.parseExpression("#root.![#this+1]").getValue(Lists.newArrayList(1, 2, 3), List.class));Map<String, Integer> map = Maps.newHashMap();map.put("weng", 4);map.put("chong", 5);map.put("yu", 2);System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.![#this.key+1]").getValue(map, List.class)));System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.![#this.value+1]").getValue(map, List.class)));// 报错: cannot convert from java.util.ArrayList<?> to java.util.Map<?, ?>// 集合、数组之间可以随意转换// System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.![#this.value+1]").getValue(map, Map.class)));}// 相当于 streamApi.filter.collect(toList)@DisplayName("数组、集合、字典 选择")@Testvoid t4() {// array|list|map.?[表达式]System.err.println(Arrays.toString(parser.parseExpression("#root.?[#this>=2]").getValue(new int[]{1, 2, 3}, int[].class)));System.err.println(Arrays.toString(parser.parseExpression("#root.?[#this>=2]").getValue(Lists.newArrayList(1, 2, 3), int[].class)));Map<String, Integer> map = Maps.newHashMap();map.put("weng", 4);map.put("chong", 5);map.put("yu", 2);// {"weng":4,"yu":2}System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.?[#this.key!='chong']").getValue(map, Map.class)));// 这里转的集合,有些怪异// [{"weng":4,"yu":2}]System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.?[#this.key!='chong']").getValue(map, List.class)));System.err.println(Jsons.NO_OP.stringify(parser.parseExpression("#root.?[#this.value<=2]").getValue(map, Map.class)));}}
}
附上相关的类
@Component("testBean")
@AllArgsConstructor
@NoArgsConstructor
@Data
public class TestBean {@Value("${angel.spel.key}")public String value;private String username;
}
相关文章:
spring.expression 随笔0 概述
0. 我只是个普通码农,不值得挽留 Spring SpEL表达式的使用 常见的应用场景:分布式锁的切面借助SpEL来构建key 比较另类的的应用场景:动态校验 个人感觉可以用作控制程序的走向,除此之外,spring的一些模块的自动配置类,也会在Cond…...
从Cookie到Session: Servlet API中的会话管理详解
文章目录 一. Cookie与Session1. Cookie与Session2. Servlet会话管理操作 二. 登录逻辑的实现 一. Cookie与Session 1. Cookie与Session 首先, 在学习过 HTTP 协议的基础上, 我们需要知道 Cookie 是 HTTP 请求报头中的一个关键字段, 本质上是浏览器在本地存储数据的一种机制,…...
docker数据管理与网络通信
一、管理docker容器中数据 管理Docker 容器中数据主要有两种方式:数据卷(Data Volumes)和数据卷容器( DataVolumes Containers) 。 1、 数据卷 数据卷是一个供容器使用的特殊目录,位于容器中。可将宿主机的目录挂载到数据卷上,对数据卷的修改操作立刻…...
怎么查询电脑的登录记录及密码更改情况?
源头是办公室公用的电脑莫名其妙打不开了,问别人也都不知道密码是多少 因为本来就没设密码啊!(躺倒) 甚至已经想好了如果是50万想攻破电脑,被po抓住要怎么花这笔钱了 是我想太多 当然最后也没解决,莫名…...
《三》TypeScript 中函数的类型
TypeScript 允许指定函数的参数和返回值的类型。 函数声明的类型定义:function 函数名(形参: 形参类型, 形参: 形参类型, ...): 返回值类型 {} function sum(x: number, y: number): number {return x y } sum(1, 2) // 正确 sum(1, 2, 3) // 错误。输入多余的或者…...
深入学习 Mysql 引擎 InnoDB、MyISAM
tip:作为程序员一定学习编程之道,一定要对代码的编写有追求,不能实现就完事了。我们应该让自己写的代码更加优雅,即使这会费时费力。 💕💕 推荐:体系化学习Java(Java面试专题&#…...
【华为OD统一考试B卷 | 100分】阿里巴巴找黄金宝箱(V)(C++ Java JavaScript Python)
题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上,无意中发现了强盗集团的藏宝地,藏宝地有编号从0~N的箱子,每个箱子上面贴有一个数字。 阿里巴巴念出一个咒语数字k(k<N),找出连续k个宝箱数字和的最大值,并输出该最大值。 输入描述 第一行输入一个数字字串,数字之间…...
六步快速搭建个人网站
目录 第一步、选择搭建平台WordPress 第二步、选域名 1)域名在哪买? 2)域名怎么选? 3)以阿里云为例,讲解怎么买域名 第三步、选择服务器 第四步、申请主机、安装WordPress 第五步、选择WordPress模…...
TypeScript 中的 type 关键字有什么用?
创建类型别名 在 TypeScript 中,type 关键字用于创建类型别名(Type Alias)。类型别名可以给一个类型起一个新的名字,使代码更具可读性和可维护性。 类型别名可以用于定义各种类型,包括基本类型、复合类型和自定义类型…...
27 getcwd 的调试
前言 同样是一个 很常用的 glibc 库函数 不管是 用户业务代码 还是 很多类库的代码, 基本上都会用到 获取当前路径 不过 我们这里是从 具体的实现 来看一下 测试用例 就是简单的使用了一下 getcwd rootubuntu:~/Desktop/linux/HelloWorld# cat Test04Getcwd.c #inc…...
使用IDEA使用Git:Git使用指北——实际操作篇
Git使用指北——实际操作 🤖:使用IDEA Git插件实际工作流程 💡 本文从实际使用的角度出发,以IDEA Git插件为基座讲述了如果使用IDEA的Git插件来解决实际开发中的协作开发问题。本文从 远程仓库中拉取项目,在本地分支进行开发&…...
java boot将一组yml配置信息装配在一个对象中
其实将一组yml数据封进一个对象中才是以后的主流开发方式 我们创建一个springboot项目 找到项目中的启动类所在目录 在同目录下创建一个类 名字你们可以随便取 我这里直接叫 dataManager 然后 在yml中定义这样一组数据信息 然后 我们在类中定义三个和这个配置信息相同的字段…...
【裸机开发】链接脚本(.lds文件)的基本语法
目录 一、什么是链接脚本? 二、链接脚本的基本语法格式 1、常用命令 2、内置变量 三、链接脚本的简单案例 一、什么是链接脚本? 一段程序的编译需要经历四个阶段(预处理—编译—汇编—链接),而链接脚本管理的就是…...
Java 进阶 -- 集合(三)
4、实现 实现是用于存储集合的数据对象,它实现了接口部分中描述的接口。本课描述了以下类型的实现: 通用实现是最常用的实现,是为日常使用而设计的。它们在标题为“通用实现”的表格中进行了总结。特殊目的实现是为在特殊情况下使用而设计的࿰…...
【华为OD机试真题 C语言】5、TLV解析 | 机试真题+思路参考+代码解析
文章目录 一、题目🎃题目描述🎃输入输出🎃样例1 二、思路参考三、代码参考🏆C语言 作者:KJ.JK 🍂个人博客首页: KJ.JK 🍂专栏介绍: 华为OD机试真题汇总,定期…...
(七)CSharp-刘铁锰版-事件
一、初步了解事件 定义:单词 Event ,译为“事件” 《牛津词典》中的解释是“a thing that happens,especially something important”通顺的解释就是“能够发生的什么事情” 角色: 使对象或类具备通知能力的成员 (中译&#x…...
【ROS】郭老二博文之:ROS目录
1、ROS2 【ROS】Ubuntu22.04安装ROS2(Humble Hawksbill) 【ROS】ROS2命令行工具详解 【ROS】ROS2中的概念和名词解释 【ROS】ROS2编程示例:话题订阅-发布-C版 【ROS】ROS2编程示例:服务和客户端-C版 【ROS】ROS2编程示例…...
Android应用程序进程的启动过程
Android应用程序进程的启动过程 导语 到这篇文章为止,我们已经简要地了解过了Android系统的启动流程了,其中比较重要的内容有Zygote进程的启动和SystemService以及Launcher的启动,接下来我们将要学习的是Android应用程序的启动过程ÿ…...
【2】Midjourney注册
随着AI技术的问世,2023年可以说是AI爆炸性成长的一年,近期最广为人知的AI服务除了chatgpt外,就是从去年五月就已经问世的AI绘画工具mid journey了。 ▲几个AI工具也代表了人工智能的热门阶段 只要输入一段文字,AI就会根据语意计算…...
第六十八天学习记录:高等数学:导数(宋浩板书)
导数是微积分中的一个概念,描述了函数在某一个点上的变化率。具体地说,函数 f ( x ) f(x) f(x)在 x a xa xa处的导数为 f ′ ( a ) f(a) f′(a),表示当 x x x在 a a a处发生微小的变化 Δ x \Delta x Δx时, f ( x ) f(x) f(x)对…...
unreal 5 实现角色拾取功能
要实现角色拾取功能,我们需要实现蓝图接口功能,蓝图接口主要提供的是蓝图和蓝图之间可以通信,接下来,跟着教程,实现一下角色的拾取功能。 首先,我们要实现一个就是可视区的物品在朝向它的时候,会…...
chatgpt赋能python:如何使用Python升序排列一个列表?
如何使用Python升序排列一个列表? 在Python编程中,我们经常需要对列表进行排序。列表排序是一种常见的操作,可以帮助我们对数据进行分析和管理。在这篇文章中,我们将学习如何使用Python对一个列表进行升序排列。 什么是升序排列…...
Lecture 20 Topic Modelling
目录 Topic ModellingA Brief History of Topic ModelsLDAEvaluationConclusion Topic Modelling makeingsense of text English Wikipedia: 6M articlesTwitter: 500M tweets per dayNew York Times: 15M articlesarXiv: 1M articlesWhat can we do if we want to learn somet…...
ThreadPoolExecutor线程池
文章目录 一、ThreadPool线程池状态二、ThreadPoolExecutor构造方法三、Executors3.1 固定大小线程池3.2 带缓冲线程池3.3 单线程线程池 四、ThreadPoolExecutor4.1 execute(Runnable task)方法使用4.2 submit()方法4.3 invokeAll()4.4 invokeAny()4.5 shutdown()4.6 shutdownN…...
chatgpt赋能python:Python实践:如何升级pip
Python实践:如何升级pip Python作为一门高效的脚本语言,被广泛应用于数据分析、人工智能、Web开发等领域。而pip则是Python的包管理工具,是开发Python应用的必备工具。但是pip在使用过程中,有时候会出现版本不兼容或者出现漏洞等…...
【JavaEE进阶】mybatis
目录: 一、Mybatis是什么 三个映射关系如下图: 二、mybatis的使用(前置工作简单案例) 第一步:导入MAVEN依赖 第二步: 在spring项目当中新建数据源 第三步:新建一个实体类,是和…...
Redis的大key
什么是 redis 的大 key redis 的大 key 不是指存储在 redis 中的某个 key 的大小超过一定的阈值,而是该 key 所对应的 value 过大对于 string 类型来说,一般情况下超过 10KB 则认为是大 key;对于set、zset、hash 等类型来说,一般…...
MMPretrain
title: mmpretrain实战 date: 2023-06-07 16:04:01 tags: [image classification,mmlab] mmpretrain实战 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ccTl9bOl-1686129437336)(null)] 主要讲解了安装,还有使用教程.安装教程直接参考官网.下面讲…...
栈和队列(数据结构刷题)[一]-python
文章目录 前言一、原理介绍二、用栈实现队列1.操作2.思路 三、关于面试考察栈里面的元素在内存中是连续分布的么? 前言 提到栈和队列,大家可能对它们的了解只停留在表面,再深入一点,好像知道又好像不知道的感觉。本文我将从底层实…...
【备战秋招】JAVA集合
集合 前言 一方面, 面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象 的操作,就要 对对象进行存储。 另一方面,使用Array存储对象方面具有一些弊端,而Java 集合就像一种容器,可以动态地把多…...
wordpress 插件 浮动小人/企业培训机构
一:重启xenserver,待启动界面进入到boot时,键入menu.c32二:待出现以下界面是,在5秒内按下tab键:三:按下tab建后,出现启动参数,然后加入single参数:回车&#…...
泉州模板建站平台/优化网站建设
标签(空格分隔): 三省吾身 原文地址:你应当怎样学习C(以及编程) 本人反思自己这些年在学校学得稀里糊涂半灌水。看到这篇文章,感觉收获不少。仿佛有指明自己道路的感觉,当然真正困难的还是坚持学习…...
北京网站建设公司网络营销外包网络建站报价/免费网站模板网
1.Redis 事务是什么 可以一次执行多个命令,本质是一组命令的集合。一个事务中的,所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞。 2.Redis 事务的作用 一个队列中,一次性、顺序性、排他性的执行…...
网站全站模板/正规seo多少钱
我想使用串行com端口进行通信,并且每次调用read函数调用时都想实现超时。int filedesc open("dev/ttyS0", O_RDWR );read( filedesc, buff, len );编辑:我正在使用Linux OS。 如何使用选择函数调用实现?参见linux.die.net/man/2/s…...
周村网站制作首选公司/互联网营销师证书含金量
1 简介这是我的新系列教程PythonDash快速web应用开发的第一期,我们都清楚学习一个新工具需要一定的动力,那么为什么我要专门为Dash制作一个系列教程呢?图1Dash是一个高效简洁的Python框架,建立在Flask、Poltly.js以及React.js的基…...
网站建设企业蛋糕/软文推广经典案例
git add -A和 git add . git add -ugit add . :监控工作区的状态树,运行会把工作时的所有变化提交到暂存区,包括文件内容修改(modified)以及新文件(new),但不包括被删除的文件。git add -u :仅监控已经被add的文件&…...