玩转 SpEL 表达式

本文概览

欢迎阅读本文,其中我们将深入探讨 Spring Expression Language(SpEL)的语法和实际应用。从基础概念到高级用法,我们将在本文中了解如何使用 SpEL 提高代码的灵活性和表达力。无论大家是初学者还是有经验的开发者,本文将为大家提供深入了解 SpEL 的机会,使大家能够在 Spring 项目中更好地利用这一强大的表达式语言。"

文章涉及到的示例代码: guide-spring

语法详解

字面量表达式

SpEL 支持以下字面量表达式:

  • 字符串 (String)
  • 数值: 整数 int or long 类型,十六进制 int or long 类型以及浮点类型 float or double
  • 布尔值: true or false
  • 空对象 : null

示例:

package com.markus.spring.expression.language.reference;import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 8:46 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class LiteralExpressions {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();// 解析 字符串String value = parser.parseExpression("'Hello,Literal Expression'").getValue(String.class);System.out.println(value);// 解析 数值 int long float doubledouble number = parser.parseExpression("4.5").getValue(double.class);System.out.println(number);// 解析 布尔值 true or falseboolean bool = parser.parseExpression("true").getValue(boolean.class);System.out.println(bool);// 解析 空对象 nullObject obj = parser.parseExpression("null").getValue();System.out.println(obj);}
}

执行结果:

image-20240121205442847

属性表达式

在 SpEL 表达式中,我们可以通过 属性名 来获取对应路径的内容,如果涉及到嵌套属性,我们用 ‘.’ 来表示级联关系。

示例:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;/*** @author: markus* @date: 2024/1/21 8:59 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class PropertiesExpression {public static void main(String[] args) {Inventor inventor = InventorBuilder.builder();EvaluationContext context = new StandardEvaluationContext(inventor);ExpressionParser parser = new SpelExpressionParser();String name = parser.parseExpression("name").getValue(context, String.class);System.out.println(name);// nested propertyint length = parser.parseExpression("name.length").getValue(context, int.class);System.out.println(length);}
}

执行结果:

image-20240121210911461

容器表达式

这里的容器用于表示 数组(Array)、集合(List)、字典(Map),我们统一来看下有关于这些内容的 SpEL 表达式都有哪些

Array
  • 索引获取,通过方括号[index]来获取目标索引值
  • 数组构造,包括基本类型构造、复杂类型构造

示例:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.Arrays;/*** @author: markus* @date: 2024/1/21 9:10 PM* @Description: 数组相关的表达式示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class ArraysExpression {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();// arrayInventor[] inventors = {InventorBuilder.builder()};EvaluationContext context = new StandardEvaluationContext(inventors);// index 表达Inventor inventor = parser.parseExpression("[0]").getValue(context, Inventor.class);System.out.println(inventor);// index + nested propertyString name = parser.parseExpression("[0].name").getValue(context, String.class);System.out.println(name);// index + nested property indexinventor.getBooleans().add(true);boolean bool = parser.parseExpression("[0].booleans[0]").getValue(context, boolean.class);System.out.println(bool);// array constructionint[] numbers = parser.parseExpression("new int[]{1,2,3}").getValue(context, int[].class);for (int number : numbers) {System.out.print(number + " ");}System.out.println();// complex type arrays constructorInventor[] complexTypeArrays = parser.parseExpression("new com.markus.spring.expression.language.Inventor[1]").getValue(context, Inventor[].class);complexTypeArrays[0] = InventorBuilder.builder();Arrays.stream(complexTypeArrays).forEach(System.out::println);}
}
List

集合和数组的数据访问以及嵌套属性访问的方式一致,示例可以参考 Array 实现。我们额外补充些有关 List 的示例

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.ArrayList;
import java.util.List;/*** @author: markus* @date: 2024/1/21 9:32 PM* @Description: List 集合有关 SpEL 表达式的示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class ListExpression {public static void main(String[] args) {Inventor inventor = InventorBuilder.builder();List<Inventor> inventors = new ArrayList<>();inventors.add(inventor);EvaluationContext context = new StandardEvaluationContext(inventors);ExpressionParser parser = new SpelExpressionParser();// by [index] get elementInventor inventorFromParser = parser.parseExpression("[0]").getValue(context, Inventor.class);System.out.println(inventorFromParser);// inline list// 1. simple type@SuppressWarnings("unchecked")List<Integer> integers = parser.parseExpression("{1,2,3,4,5}").getValue(context, List.class);System.out.println(integers);// 2. complex type@SuppressWarnings("unchecked")List<Inventor> inventorList = (List<Inventor>) parser.parseExpression("{T(com.markus.spring.expression.language.InventorBuilder).builder()}").getValue(context);System.out.println(inventorList);}
}

执行结果:

image-20240121214945292

Map

Map中的数据访问有些不同,示例如下所示:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @author: markus* @date: 2024/1/21 9:47 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class MapExpression {public static void main(String[] args) {Inventor inventor = InventorBuilder.builder();Map<String, Inventor> map = new HashMap();map.put("markus", inventor);EvaluationContext context = new StandardEvaluationContext(map);ExpressionParser parser = new SpelExpressionParser();// by ['key'] get elementInventor inventorFromParser = parser.parseExpression("['markus']").getValue(context, Inventor.class);System.out.println(inventorFromParser);// nested property accessString name = parser.parseExpression("['markus'].name").getValue(context, String.class);System.out.println(name);// inline map@SuppressWarnings("unchecked")Map<String, Inventor> inventorMap = parser.parseExpression("{'markus':T(com.markus.spring.expression.language.InventorBuilder).builder()}").getValue(context, Map.class);System.out.println(inventorMap);}
}

执行结果:

image-20240121215251099

方法调用表达式

示例如下:

package com.markus.spring.expression.language.reference;import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 9:55 PM* @Description: 方法调用表达式的示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class MethodInvokeExpression {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();String subString = parser.parseExpression("'Hello,SpEL'.substring(0,5)").getValue(String.class);System.out.println(subString);}
}

执行结果:

image-20240121215802467

运算符表达式

SpEL 表达式支持如下运算法:

  • 关系运算符
  • 逻辑运算符
  • 算术运算符
  • 赋值运算符

示例如下:

package com.markus.spring.expression.language.reference;import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 10:00 PM* @Description: 运算符 SpEL 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class OperatorsExpression {/*** more demo please reference https://docs.spring.io/spring-framework/reference/core/expressions/language-ref/operators.html** @param args*/public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();// first : relational operatorsboolean result = parser.parseExpression("2 < 5").getValue(Boolean.class);System.out.println("2 < 5 : " + result);result = parser.parseExpression("2 == 5").getValue(Boolean.class);System.out.println("2 == 5 : " + result);result = parser.parseExpression("1 instanceof T(int)").getValue(Boolean.class);System.out.println("1 instanceof T(int) : " + result);result = parser.parseExpression("1 instanceof T(Integer)").getValue(Boolean.class);System.out.println("1 instanceof T(Integer) : " + result);// second : logical operators// and (&&)// or (||)// not (!)result = parser.parseExpression("true or false").getValue(Boolean.class);System.out.println("true or false : " + result);result = parser.parseExpression("true and false").getValue(Boolean.class);System.out.println("true and false : " + result);result = parser.parseExpression("!true").getValue(Boolean.class);System.out.println("!true : " + result);// third : mathematical operators// + - * / %// Additionint two = parser.parseExpression("1 + 1").getValue(Integer.class);  // 2System.out.println("1 + 1 : " + two);String testString = parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class);  // 'test string'System.out.println("'test' + ' ' + 'string' : " + testString);// Subtractionint four = parser.parseExpression("1 - -3").getValue(Integer.class);  // 4System.out.println("1 - -3 : " + four);double d = parser.parseExpression("1000.00 - 1e4").getValue(Double.class);  // -9000System.out.println("1000.00 - 1e4 : " + d);// Multiplicationint six = parser.parseExpression("-2 * -3").getValue(Integer.class);  // 6System.out.println("-2 * -3 : " + six);double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class);  // 24.0System.out.println("2.0 * 3e0 * 4 : " + twentyFour);// Divisionint minusTwo = parser.parseExpression("6 / -3").getValue(Integer.class);  // -2System.out.println("6 / -3 : " + minusTwo);double oneD = parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class);  // 1.0System.out.println("8.0 / 4e0 / 2 : " + oneD);// Modulusint three = parser.parseExpression("7 % 4").getValue(Integer.class);  // 3System.out.println("7 % 4 : " + three);int one = parser.parseExpression("8 / 5 % 2").getValue(Integer.class);  // 1System.out.println("8 / 5 % 2 : " + one);// Operator precedenceint minusTwentyOne = parser.parseExpression("1+2-3*8").getValue(Integer.class);  // -21System.out.println("1+2-3*8 : " + minusTwentyOne);}
}

执行结果:

image-20240121221455559

类型表达式

我们可以通过 T(xxx) 来表示 Class 的实例,静态方法也可以通过这个方式使用,前面我们已经展示过,即 T(xxx).method(xxx),另外值得注意的是,在java.lang包下的类可以不指定全限定名,直接指定类名。

示例如下:

package com.markus.spring.expression.language.reference;import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 10:25 PM* @Description: 类型 相关的 SpEL 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class TypeExpression {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);System.out.println(dateClass);Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);System.out.println(stringClass);boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);System.out.println(trueValue);}
}

执行结果:

image-20240121222912044

构造器表达式

通过 SpEL 来初始化实例,使用时必须要指定全限定名(包括 java.lang 包下的)

示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 10:31 PM* @Description: 构造器 SpEL 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class ConstructorExpression {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();Inventor einstein = parser.parseExpression("new com.markus.spring.expression.language.Inventor()").getValue(Inventor.class);System.out.println(einstein);}
}

执行结果:

image-20240121223402163

变量表达式

我们可以在 SpEL 中通过使用 #variableName 来获取执行的变量值。另外 变量的表示形式必须按照以下要求(至少有以下1个组成):

  • A-Z 和 a-z
  • 0-9
  • _
  • $

示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.ArrayList;
import java.util.List;/*** @author: markus* @date: 2024/1/21 10:35 PM* @Description: 变量 SpEL 表达式示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class VariableExpression {public static void main(String[] args) {Inventor inventor = InventorBuilder.builder();inventor.getBooleans().add(true);inventor.getBooleans().add(false);EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();context.setVariable("newName", "Luna");ExpressionParser parser = new SpelExpressionParser();parser.parseExpression("name = #newName").getValue(context, inventor);System.out.println(inventor);// #this and #root// #this 总是指向当前表达式中计算的对象// #root 总是指向根对象List<Integer> integers = new ArrayList<>();integers.add(1);integers.add(2);integers.add(3);integers.add(4);integers.add(5);integers.add(6);context.setVariable("integers", integers);String thisExpression = "#integers.?[#this > 3]";@SuppressWarnings("unchecked")List<Integer> gt3List = parser.parseExpression(thisExpression).getValue(context, List.class);gt3List.forEach(integer -> System.out.print(integer + " "));System.out.println();// #rootcontext = new StandardEvaluationContext(inventor);Inventor value = parser.parseExpression("#root").getValue(context, Inventor.class);System.out.println(value);}
}

执行结果:

image-20240121225203424

函数表达式

我们可以向 EvaluationContext中注册函数,并在 SpEL 中使用

示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;import java.lang.reflect.Method;
import java.util.Objects;/*** @author: markus* @date: 2024/1/21 10:54 PM* @Description: 注册方法 并在 SpEL 中使用 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class MethodExpression {// must be static methodpublic static void display(Object obj) {System.out.println(obj);}public static void main(String[] args) throws NoSuchMethodException {Method method = MethodExpression.class.getDeclaredMethod("display", Object.class);EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();context.setVariable("display", method);context.setVariable("inventor", InventorBuilder.builder());ExpressionParser parser = new SpelExpressionParser();parser.parseExpression("#display(#inventor)").getValue(context);}
}

执行结果:

image-20240121225900247

Bean 引用表达式

通过 @xxx 来获取 Spring 容器中的 Bean 实例

示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;/*** @author: markus* @date: 2024/1/21 11:00 PM* @Description: Bean 应用示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class BeanReferenceExpression {public static void main(String[] args) {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/META-INF/expression-in-bean-definitions.xml");BeanFactoryResolver beanFactoryResolver = new BeanFactoryResolver(context.getBeanFactory());StandardEvaluationContext evaluationContext = new StandardEvaluationContext();evaluationContext.setBeanResolver(beanFactoryResolver);ExpressionParser parser = new SpelExpressionParser();String expression = "@inventor";Inventor inventor = parser.parseExpression(expression).getValue(evaluationContext, Inventor.class);System.out.println(inventor);}
}

执行结果:

image-20240121230605479

三元表达式

我们还可以在表达式内部使用三元运算符执行if-then-else条件逻辑。

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 11:07 PM* @Description: 三元表达式 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class TernaryOperatorExpression {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();String falseString = parser.parseExpression("false ? 'trueExp' : 'falseExp'").getValue(String.class);System.out.println("false ? 'trueExp' : 'falseExp' : " + falseString);// The Elvis operator (精简版 三元表达式)String name = parser.parseExpression("name?:'Unknown'").getValue(new Inventor(), String.class);System.out.println(name);  // 'Unknown'}
}

执行结果:

image-20240121230952655

安全指针表达式

为避免出现空指针,我们还可以在 SpEL 中使用 ?.来实现

示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;/*** @author: markus* @date: 2024/1/21 11:11 PM* @Description: 安全指针示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class SafeNavigationOperators {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();Inventor inventor = new Inventor();inventor.setName("markus zhang");context.setVariable("inventor", inventor);String name = parser.parseExpression("#inventor.name?.#inventor.name").getValue(context, String.class);System.out.println(name);  // markus zhanginventor.setName(null);name = parser.parseExpression("#inventor.name?.#inventor.name").getValue(context, String.class);System.out.println(name);  // null - does not throw NullPointerException!!!}
}

执行结果:

image-20240121231640460

集合筛选表达式

Selection是一种强大的表达语言功能,它允许您通过从其条目中进行选择,将源集合转换为另一个集合。选择使用的语法是.?[selectionExpression]。它过滤集合并返回一个包含原始元素子集的新集合。

示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.ArrayList;
import java.util.List;/*** @author: markus* @date: 2024/1/21 11:17 PM* @Description: 集合元素选择 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class CollectionSelectionExpression {public static void main(String[] args) {EvaluationContext context = new StandardEvaluationContext();List<Integer> integers = new ArrayList<>();integers.add(1);integers.add(2);integers.add(3);integers.add(4);integers.add(5);integers.add(6);context.setVariable("integers", integers);ExpressionParser parser = new SpelExpressionParser();@SuppressWarnings("unchecked")List<Integer> list = (List<Integer>) parser.parseExpression("#integers.?[#this == 3 || #this == 4]").getValue(context);list.forEach(ele -> {System.out.print(ele + " ");});}
}

执行结果:

image-20240121232208402

集合子集表达式

集合子集 意为 获取目标集合中某一字段集合,示例如下:

package com.markus.spring.expression.language.reference;import com.markus.spring.expression.language.Inventor;
import com.markus.spring.expression.language.InventorBuilder;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.ArrayList;
import java.util.List;/*** @author: markus* @date: 2024/1/21 11:17 PM* @Description: 集合元素选择 示例* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class CollectionProjectionExpression {public static void main(String[] args) {EvaluationContext context = new StandardEvaluationContext();List<Inventor> inventors = new ArrayList<>();inventors.add(InventorBuilder.builder());inventors.add(InventorBuilder.builder("Luna"));context.setVariable("inventors", inventors);ExpressionParser parser = new SpelExpressionParser();@SuppressWarnings("unchecked")List<String> list = (List<String>) parser.parseExpression("#inventors.![name]").getValue(context);list.forEach(ele -> {System.out.println(ele + " ");});}
}

执行结果:

image-20240121232807466

模板表达式

表达式执行一个模板,并在这个模板中通过 #{} 来占位,示例如下:

package com.markus.spring.expression.language.reference;import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;/*** @author: markus* @date: 2024/1/21 11:29 PM* @Description:* @Blog: https://markuszhang.com* It's my honor to share what I've learned with you!*/
public class TemplateExpression {public static void main(String[] args) {ExpressionParser parser = new SpelExpressionParser();String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}",new TemplateParserContext()).getValue(String.class);System.out.println("random number is #{T(java.lang.Math).random()} : " + randomPhrase);}public static class TemplateParserContext implements ParserContext {public String getExpressionPrefix() {return "#{";}public String getExpressionSuffix() {return "}";}public boolean isTemplate() {return true;}}
}

执行结果:

image-20240121233526828

本文总结

通过本文,我们详细讨论了 SpEL 的语法、特性和应用场景。从简单的字面量表达式到复杂的类型引用,相信大家已经掌握了在 Spring 项目中灵活使用 SpEL 的关键知识。在总结中,不要忘记不断实践和深入研究,以便更好地运用 SpEL 提高代码的可读性和可维护性。感谢您的阅读,希望大家在今后的项目中充分发挥 SpEL 的潜力!"

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

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

相关文章

ACM题解Day2|1.台风, 2.式神考试,3.DNA,4.方程求解

学习目标&#xff1a; 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门 &#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d; ☆*: .&#xff61;. o(≧▽≦)…

Python 算法交易实验67 第一次迭代总结

说明 在这里对第一次迭代&#xff08;2023.7~ 2024.1&#xff09;进行一些回顾和总结&#xff1a; 回顾&#xff1a; 1 实现了0~1的变化2 在信息隔绝的条件下&#xff0c;无控制的操作&#xff0c;导致被套 总结&#xff1a; 思路可行&#xff0c;在春暖花开的时候&#x…

企业Oracle1 数据库管理

Oracle的安装 一、基础表的创建 1.1 切换到scott用户 用sys 账户 登录 解锁scott账户 alter user scott account unlock;conn scott/tiger;发现并不存在scott账户&#xff0c;自己创建一个&#xff1f; 查找资料后发现&#xff0c;scott用户的脚本需要自己执行一下 C:\ap…

三、MySQL库表操作

3.1 SQL语句基础&#xff08;SQL命令&#xff09; 3.1.1 SQL简介 SQL&#xff1a;结构化查询语言(Structured Query Language)&#xff0c;在关系型数据库上执行数据操作&#xff0c;数据检索以及数据维护的标准化语言。使用SQL语句&#xff0c;程序员和数据库管理员可以完成…

Opncv模板匹配 单模板匹配 多模板匹配

目录 问题引入 单模板匹配 ①模板匹配函数: ②查找最值和极值的坐标和值: 整体流程原理介绍 实例代码介绍: 多模板匹配 ①定义阈值 ②zip函数 整体流程原理介绍 实例代码: 问题引入 下面有请我们的陶大郎登场 这张图片是我们的陶大郎,我们接下来将利用陶大郎来介绍…

stm32h7中RTC的BCD模式与BIN模式

RTC的BCD格式与BIN格式 BCD&#xff08;Binary-Coded Decimal&#xff09;和BIN&#xff08;Binary&#xff09;是两种不同的数字表示格式。 BCD格式&#xff1a; BCD是一种用二进制编码表示十进制数字的格式。在BCD格式中&#xff0c;每个十进制数位使用4位二进制数来表示&am…

c++程序的内存模型,new操作符详解

目录 内存四区 程序运行前 代码区 全局区 程序运行后 栈区 堆区 new操作符 创建一个数 创建一个数组 内存四区 不同区域存放不同的数据&#xff0c;赋予不同的生命周期&#xff0c;让我们更加灵活的编程 程序运行前 程序运行前就有代码区和全局区 代码区 程序编…

Windows系统下使用docker-compose安装mysql8和mysql5.7

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7 文章目录 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7MySQL81.新建文件夹2.创建…

《Linux C编程实战》笔记:信号处理函数的返回

信号处理函数可以正常返回&#xff0c;也可以调用其他函数返回到程序的主函数中&#xff0c;而不是从处理程序返回。 setjmp/longjmp 使用longjmp可以跳转到setjmp设置的位置 这两个函数原型如下 #include<setjmp.h> int setjmp(jmp_buf env); void longjmp(jmp_buf …

QQ数据包解密

Windows版qq数据包格式&#xff1a; android版qq数据包格式&#xff1a; 密钥&#xff1a;16个0 算法&#xff1a;tea_crypt算法 pc版qq 0825数据包解密源码&#xff1a; #include "qq.h" #include "qqcrypt.h" #include <WinSock2.h> #include…

构建库函数雏形(以GPIO为例)

构建库函数雏形 进行外设结构体定义构建置位和复位函数进行库函数的自定义 step I&#xff1a; \textbf{step I&#xff1a;} step I&#xff1a; 对端口进行输出数据类型枚举 step II&#xff1a; \textbf{step II&#xff1a;} step II&#xff1a;对端口进行结构化描述 step…

线性代数的学习和整理23:用EXCEL和python 计算向量/矩阵的:内积/点积,外积/叉积

目录 1 乘法 1.1 标量乘法(中小学乘法) 1.1.1 乘法的定义 1.1.2 乘法符合的规律 1.2 向量乘法 1.2.1 向量&#xff1a;有方向和大小的对象 1.2.2 向量的标量乘法 1.2.3 常见的向量乘法及结果 1.2.4 向量的其他乘法及结果 1.2.5 向量的模长&#xff08;长度&#xff0…

第三篇【传奇开心果系列】Vant开发移动应用:财务管理应用

传奇开心果博文系列 系列博文目录Vant开发移动应用系列博文 博文目录一、项目目标二、编程思路三、初步实现示例代码四、扩展思路五、使用Firebase等后端服务来实现用户认证和数据存储示例代码六、用Vant组件库实现收入和支出分类管理的示例代码七、用Vant组件库实现收入和支出…

Redis经典五大类型源码及底层实现

Redis经典五大类型源码及底层实现分析 1、一些题目 redis的zset底层实现&#xff1f;redis的跳表和压缩列表说一下&#xff0c;解决了哪些问题&#xff0c;时间复杂度和空间复杂度如何&#xff1f;redis的zset使用的是什么数据结构&#xff1f; Redis数据类型的底层数据结构…

《WebKit 技术内幕》之五(1): HTML解释器和DOM 模型

第五章 HTML 解释器和 DOM 模型 1.DOM 模型 1.1 DOM标准 DOM &#xff08;Document Object Model&#xff09;的全称是文档对象模型&#xff0c;它可以以一种独立于平台和语言的方式访问和修改一个文档的内容和结构。这里的文档可以是 HTML 文档、XML 文档或者 XHTML 文档。D…

python基本数据类型 - 字典集合

引入 在内存中存储的数据可以是不同的数据类型。比如名字可以使用字符串存储&#xff0c;年龄可以使用数字存储&#xff0c;python有6种基本数据类型&#xff0c;用于各种数据的存储&#xff0c;分别是&#xff1a;numbers(数字类型)、string(字符串)、List(列表)、Tuple(元组…

【笔记】Blender4.0建模入门-3物体的基本操作

Blender入门 ——邵发 3.1 物体的移动 演示&#xff1a; 1、选中一个物体 2、选中移动工具 3、移动 - 沿坐标轴移动 - 在坐标平面内移动 - 自由移动&#xff08;不好控制&#xff09; 选中物体&#xff1a;右上的大纲窗口&#xff0c;点击物体名称&#xff0c;物体的轮…

文件操作(上)

目录 文件的必要性&#xff1a; 文件分类&#xff1a; 程序文件&#xff1a; 数据文件&#xff1a; 文件的打开与关闭&#xff1a; fopen函数分析: ​编辑 FILE*: char*filename: char*mode: fclose函数&#xff1a; 应用&#xff1a; 文件编译 Fgetc Fputc 应用…

HNU-数据挖掘-作业1

数据挖掘课程作业作业1 计科210X 甘晴void 202108010XXX 第一题 假设所分析的数据包括属性 age,它在数据元组中的值&#xff08;以递增序&#xff09;为13 ,15 ,16 ,16 ,19 ,20 ,20 ,21 ,22 ,22 ,25 ,25 ,25 ,25 ,30 ,33 ,33 ,35 ,35 ,35 ,35 ,36 ,40 ,45 ,46 ,52,70。 a.…

基于Unity平台开发Vision Pro应用

VisionOS是苹果最新空间计算设备Vision Pro的操作系统。Unity开发人员可以利用现有的3D场景 以及为 visionOS 构建游戏或应用程序的资产。有关 visionOS 的更多信息&#xff0c;请参阅 Apple 的 visionOS 概述。 visionOS提供了几种不同的显示应用程序的模式&#xff1a;Windo…