Spring提供的SPEL表达式
SPEL
1. 概述
SpEL是Spring框架中用于表达式语言的一种方式。它类似于其他编程语言中的表达式语言,用于在运行时计算值或执行特定任务。
SpEL提供了一种简单且强大的方式来访问和操作对象的属性、调用对象的方法,以及实现运算、条件判断等操作。它可以被用于XML和注解配置中,可以用于许多Spring框架中的特性,如依赖注入、AOP、配置文件等。
SpEL表达式可以在字符串中进行定义,使用特殊的语法和符号来表示特定的操作。例如,可以使用${expression}来表示一个SpEL表达式,其中expression是具体的SpEL语句。
SpEL支持各种操作和函数,包括算术运算、逻辑运算、条件判断、正则表达式匹配、集合操作等。它还支持访问上下文中的变量和参数,以及调用对象的方法
2. 基础语法学习案例
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.junit.Test;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.SimpleEvaluationContext;
import org.springframework.expression.spel.support.StandardEvaluationContext;import java.util.*;/*** SPEL表达式案例** @author xuyuan* @see EvaluationContext* @see SimpleEvaluationContext 定制化提供特定的上下文对象,控制读写权限,可以只读如下的SimpleEvaluationContext.forReadOnlyDataBinding().build()* SimpleEvaluationContext.forReadOnlyDataBinding().build():* 适用于简单的、只读的数据绑定场景。* 性能较好,但功能有限。* 不支持复杂的表达式操作。* <p>* new StandardEvaluationContext(obj):* 适用于复杂的表达式求值场景。* 功能全面,支持所有SPEL特性。* 可以设置根对象和其他上下文信息,灵活性高。*/
public class SpelExam {/*** 操作字面量*/@Testpublic void test() {ExpressionParser parser = new SpelExpressionParser();// 获取字符串 "Hello World"String helloWorld = parser.parseExpression("'Hello World'").getValue(String.class);System.out.println(helloWorld);// double类型 6.0221415E23double avogadrosNumber = parser.parseExpression("6.0221415E+23").getValue(Double.class);System.out.println(avogadrosNumber);// int类型 2147483647int maxValue = parser.parseExpression("0x7FFFFFFF").getValue(Integer.class);System.out.println(maxValue);// trueboolean trueValue = parser.parseExpression("true").getValue(Boolean.class);System.out.println(trueValue);// nullObject nullValue = parser.parseExpression("null").getValue();System.out.println(nullValue);}/*** 操作对象*/@Testpublic void test2() {// 定义Parser,可以定义全局的parserExpressionParser parser = new SpelExpressionParser();// 注意!属性名的第一个字母不区分大小写。 birthdate.year等效于Birthdate.Year// 取出Inventor 中,birthdate属性的year属性Inventor zhangsan = new Inventor("zhangsan", new Date(), "China");// 定义StandardEvaluationContext ,传入一个操作对象StandardEvaluationContext zhangsanContext = new StandardEvaluationContext(zhangsan);int year = parser.parseExpression("birthdate.year + 1900").getValue(zhangsanContext, Integer.class);System.out.println(year); // 2025// 取出Inventor的placeOfBirth的city属性PlaceOfBirth placeOfBirth = new PlaceOfBirth("长沙", "中国");zhangsan.setPlaceOfBirth(placeOfBirth);String city = parser.parseExpression("placeOfBirth.City").getValue(zhangsanContext, String.class);System.out.println(city); // 长沙}/*** 操作数组和List*/@Testpublic void test3() {// 定义Parser,可以定义全局的parserExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();// 省略数据初始化Society ieee = new Society();Inventor tesla = new Inventor("Tesla", "USA");ieee.getMembers().add(tesla);ieee.getMembers().add(new Inventor("BYD", "CN"));ieee.getMembers().add(new Inventor("BMW", "GE"));ieee.getMembers().add(new Inventor("FLL", "FR"));tesla.setInventions(new String[]{"Lightning", "Telephone", "Computer", "Electricity", "Electric Motor", "Electric Engine", "Electric Car"});String value = parser.parseExpression("inventions[3]").getValue(context, tesla, String.class);System.out.println("取出tesla对象的inventions 第四个数据:" + value);String name = parser.parseExpression("Members[0].Name").getValue(context, ieee, String.class);System.out.println("取出ieee对象的第一个Member的name属性:" + name);String invention = parser.parseExpression("Members[0].Inventions[6]").getValue(context, ieee, String.class);System.out.println("取出ieee对象的第一个Member的第七个Inventions:" + invention);}/*** 操作Map*/@Testpublic void test4() {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();Society ieee = new Society();ieee.getOfficers().put("president", new Inventor("Tesla", "USA"));ieee.getOfficers().put("advisors", new Inventor("BYD", "CN"));ieee.getOfficers().put("secretary", new Inventor("BMW", "GE"));ieee.getOfficers().put("treasurer", new Inventor("FLL", "FR"));String name = parser.parseExpression("officers['advisors'].name").getValue(context, ieee, String.class);System.out.println("取出ieee对象的advisors的name属性:" + name);}/*** 内嵌List/Map*/@Testpublic void test5() {// 定义Parser,可以定义全局的parserExpressionParser parser = new SpelExpressionParser();// [1, 2, 3, 4]List numbers = (List) parser.parseExpression("{1,2,3,4}").getValue();System.out.println(numbers);// 嵌套: [[a, b], [x, y]]List listOfLists = (List) parser.parseExpression("{{'a','b'},{'x','y'}}").getValue();System.out.println(listOfLists);// {name=Nikola, dob=10-July-1856}Map inventorInfo = (Map) parser.parseExpression("{name:'Nikola',dob:'10-July-1856'}").getValue();System.out.println(inventorInfo);// 嵌套:{name={first=Nikola, last=Tesla}, dob={day=10, month=July, year=1856}}Map mapOfMaps = (Map) parser.parseExpression("{name:{first:'Nikola',last:'Tesla'},dob:{day:10,month:'July',year:1856}}").getValue();System.out.println(mapOfMaps);// List与Map可以嵌套使用,互相结合。// 嵌套:[{name={first=Nikola, last=Tesla}}, {dob={day=10, month=July, year=1856}}]List listOfMaps = (List) parser.parseExpression("{{name:{first:'Nikola',last:'Tesla'}},{dob:{day:10,month:'July',year:1856}}}").getValue();System.out.println(listOfMaps);}/*** 构建数组*/@Testpublic void test6() {ExpressionParser parser = new SpelExpressionParser();int[] numbers1 = parser.parseExpression("new int[4]").getValue(int[].class);// 数组并初始化int[] numbers2 = parser.parseExpression("new int[]{1,2,3}").getValue(int[].class);// 多维数组int[][] numbers3 = parser.parseExpression("new int[4][5]").getValue(int[][].class);}/*** 调用方法*/@Testpublic void test7() {ExpressionParser parser = new SpelExpressionParser();// 调用substring方法System.out.println(parser.parseExpression("'abc'.substring(1, 3)").getValue(String.class));// 调用societyContext中对象的isMember方法,并传值。StandardEvaluationContext societyContext = new StandardEvaluationContext(new Society());boolean isMember = parser.parseExpression("isMember('Mihajlo Pupin')").getValue(societyContext, Boolean.class);}/*** 关系运算* 每个符号操作符也可以被指定为纯字母的等价物。这避免了所使用的符号对于嵌入表达式的文档类型具有特殊含义的问题(例如在XML文档中)。所有文本操作符都不区分大小写。对应的文本是:* lt (<)* gt (>)* le (<=)* ge (>=)* eq (==)* ne (!=)* div (/)* mod (%)* not (!)*/@Testpublic void test8() {ExpressionParser parser = new SpelExpressionParser();boolean trueValue = parser.parseExpression("2 == 2").getValue(Boolean.class);boolean falseValue = parser.parseExpression("2 < -5.0").getValue(Boolean.class);boolean trueValue1 = parser.parseExpression("'black' < 'block'").getValue(Boolean.class);}/*** instanceof 和 正则表达式的匹配操作符* 使用基本类型时要小心,因为它们会立即被装箱为包装器类型,所以1 instanceof T(int)会计算为false,而1 instanceof T(Integer)会计算为true。*/@Testpublic void test9() {ExpressionParser parser = new SpelExpressionParser();boolean value = parser.parseExpression("'xyz' instanceof T(Integer)").getValue(Boolean.class);boolean trueValue = parser.parseExpression("'5.00' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);boolean falseValue = parser.parseExpression("'5.0067' matches '^-?\\d+(\\.\\d{2})?$'").getValue(Boolean.class);}/*** 逻辑运算符:and, or, not*/@Testpublic void test10() {ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext societyContext = new StandardEvaluationContext(new Society());boolean value = parser.parseExpression("true and false").getValue(Boolean.class);String expression1 = "isMember('Nikola Tesla') and isMember('Mihajlo Pupin')";boolean value1 = parser.parseExpression(expression1).getValue(societyContext, Boolean.class);boolean value2 = parser.parseExpression("true or false").getValue(Boolean.class);String expression2 = "isMember('Nikola Tesla') or isMember('Albert Einstein')";boolean valu3 = parser.parseExpression(expression2).getValue(societyContext, Boolean.class);boolean value4 = parser.parseExpression("!true").getValue(Boolean.class);String expression3 = "isMember('Nikola Tesla') and !isMember('Mihajlo Pupin')";boolean value5 = parser.parseExpression(expression3).getValue(societyContext, Boolean.class);}/*** 数学计算符*/@Testpublic void test11() {ExpressionParser parser = new SpelExpressionParser();parser.parseExpression("1 + 1").getValue(Integer.class); // 2parser.parseExpression("'test' + ' ' + 'string'").getValue(String.class); // 'test string'parser.parseExpression("1 - -3").getValue(Integer.class); // 4parser.parseExpression("1000.00 - 1e4").getValue(Double.class); // -9000parser.parseExpression("-2 * -3").getValue(Integer.class); // 6parser.parseExpression("6 / -3").getValue(Integer.class); // -2parser.parseExpression("8.0 / 4e0 / 2").getValue(Double.class); // 1.0parser.parseExpression("7 % 4").getValue(Integer.class); // 3parser.parseExpression("8 / 5 % 2").getValue(Integer.class); // 1parser.parseExpression("1+2-3*8").getValue(Integer.class); // -21}/*** 类型获取符:T()* T(Type):用于引用静态类型。* T(Type).staticMethod():用于调用静态方法。* T(Type).STATIC_FIELD:用于访问静态字段。* instanceof T(Type):用于类型检查。*/@Testpublic void test12() {ExpressionParser parser = new SpelExpressionParser();Class dateClass = parser.parseExpression("T(java.util.Date)").getValue(Class.class);Class stringClass = parser.parseExpression("T(String)").getValue(Class.class);boolean trueValue = parser.parseExpression("T(java.math.RoundingMode).CEILING < T(java.math.RoundingMode).FLOOR").getValue(Boolean.class);}/*** 调用构造函数*/@Testpublic void test13() {System.out.println(Inventor.class.getName());ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext societyContext = new StandardEvaluationContext(new Society());Inventor einstein = parser.parseExpression("new com.xuyuan.spring.spel.SpelExam.Inventor('Albert Einstein', 'German')").getValue(Inventor.class);// 创建一个新的Inventor,并且添加到members的list中parser.parseExpression("Members.add(com.xuyuan.spring.spel.SpelExam.Inventor('Albert Einstein', 'German'))").getValue(societyContext);System.out.println(societyContext.getRootObject().getValue());}/*** Spel变量* #variableName语法在表达式中引用变量*/@Testpublic void test14() {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();context.setVariable("newName", "Mike Tesla"); // 设置变量Inventor tesla = new Inventor("Nikola Tesla", "Serbian");// 获取变量newName,并将其赋值给name属性parser.parseExpression("Name = #newName").getValue(context, tesla);System.out.println(tesla.getName()); // "Mike Tesla"}/*** #this变量引用当前的评估对象(根据该评估对象解析非限定引用)。* #root变量总是被定义并引用根上下文对象。虽然#this可能会随着表达式的组成部分的计算而变化,但是#root总是指根。*/@Testpublic void test15() {// 创建一个Integer数组List<Integer> primes = new ArrayList<Integer>();primes.addAll(Arrays.asList(2, 3, 5, 7, 11, 13, 17));ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadWriteDataBinding().build();context.setVariable("primes", primes);List<Integer> primesGreaterThanTen = (List<Integer>) parser.parseExpression("#primes.?[#this>10]").getValue(context);System.out.println(primesGreaterThanTen);}/*** 三元表达式*/@Testpublic void test16() {ExpressionParser parser = new SpelExpressionParser();String expression = "10 > 5 ? 'ten is greater than five' : 'ten is not greater than five'";parser.parseExpression(expression).getValue(String.class);}/*** Elvis操作符*/@Testpublic void test17() {ExpressionParser parser = new SpelExpressionParser();String name = "Elvis Presley";String displayName = (name != null ? name : "Unknown");String name1 = parser.parseExpression("name?:'Unknown'").getValue(String.class);System.out.println(name1); // 'Unknown'}/*** 安全导航运算符:obj?.prop* 安全导航操作符用于避免NullPointerException,来自Groovy语言。* 通常,当引用一个对象时,可能需要在访问该对象的方法或属性之前验证它不为null。为了避免这种情况,安全导航运算符返回null,而不是引发异常。以下示例显示了如何使用安全导航运算符*/@Testpublic void test18() {ExpressionParser parser = new SpelExpressionParser();EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();Inventor tesla = new Inventor("Nikola Tesla", "Serbian");tesla.setPlaceOfBirth(new PlaceOfBirth("Smiljan", "Croatia"));String city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);System.out.println(city); // Smiljantesla.setPlaceOfBirth(null);city = parser.parseExpression("PlaceOfBirth?.City").getValue(context, tesla, String.class);System.out.println(city); // null - does not throw NullPointerException!!!}/*** 集合选择:?[predicate]*/@Testpublic void test19() {Society ieee = new Society();ieee.getMembers().add(new Inventor("Tesla", "USA"));ieee.getMembers().add(new Inventor("BYD", "CN"));ieee.getMembers().add(new Inventor("BMW", "GE"));ieee.getMembers().add(new Inventor("FLL", "FR"));ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext context = new StandardEvaluationContext(ieee);// 语法.?[selectionExpression]List<Inventor> list = parser.parseExpression("Members.?[Nationality == 'Serbian']").getValue(context, List.class);Map<String, Integer> map = new HashMap<>();context.setVariable("map", map);map.put("Tesla0", 28);map.put("Tesla1", 26);map.put("Tesla2", 25);// 返回value小于27的值// 使用参数化的 Map 类型Map<String, Integer> newMap = parser.parseExpression("#map.?[value < 27]").getValue(context, Map.class);System.out.println(newMap); // 输出符合条件的键值对}/*** 集合投影:![expression]*/@Testpublic void test20() {Society ieee = new Society();ieee.getMembers().add(new Inventor("Tesla", "USA"));ieee.getMembers().add(new Inventor("BYD", "CN"));ieee.getMembers().add(new Inventor("BMW", "GE"));ieee.getMembers().add(new Inventor("FLL", "FR"));ExpressionParser parser = new SpelExpressionParser();StandardEvaluationContext context = new StandardEvaluationContext(ieee);List placesOfBirth = parser.parseExpression("Members.![placeOfBirth?.city]").getValue(context, List.class);}/*** 表达式模板:#{expression}* 通常使用#{}作为模板,与字符串拼接*/@Testpublic void test21() {ExpressionParser parser = new SpelExpressionParser();// 通常使用#{}作为模板,与字符串拼接起来String randomPhrase = parser.parseExpression("random number is #{T(java.lang.Math).random()}", new TemplateParserContext()).getValue(String.class);System.out.println(randomPhrase); // "random number is 0.7038186818312008"}@Data@AllArgsConstructor@NoArgsConstructorclass PlaceOfBirth {private String city;private String country;}@Data@AllArgsConstructor@NoArgsConstructorclass Society {private String name;public String Advisors = "advisors";public String President = "president";private List<Inventor> members = new ArrayList<>();private Map officers = new HashMap();public boolean isMember(String name) {for (Inventor inventor : members) {if (inventor.getName().equals(name)) {return true;}}return false;}}@Data@NoArgsConstructor@AllArgsConstructorclass Inventor {private String name;private String nationality;private String[] inventions;private Date birthdate;private PlaceOfBirth placeOfBirth;public Inventor(String name, String nationality) {GregorianCalendar c = new GregorianCalendar();this.name = name;this.nationality = nationality;this.birthdate = c.getTime();}public Inventor(String name, Date birthdate, String nationality) {this.name = name;this.nationality = nationality;this.birthdate = birthdate;}}}
相关文章:
Spring提供的SPEL表达式
SPEL 1. 概述 SpEL是Spring框架中用于表达式语言的一种方式。它类似于其他编程语言中的表达式语言,用于在运行时计算值或执行特定任务。 SpEL提供了一种简单且强大的方式来访问和操作对象的属性、调用对象的方法,以及实现运算、条件判断等操作。它可以…...
JAVA编程【jvm垃圾回收的差异】
jvm垃圾回收的差异 JVM(Java Virtual Machine)的垃圾回收(GC)机制是自动管理内存的一种方式,能够帮助开发者释放不再使用的内存,避免内存泄漏和溢出等问题。不同的垃圾回收器(GC)有…...
Elasticsearch:“Your trial license is expired”
目录标题 问题原因解决方案 问题 原因 ES的X-pack许可证是提供免费一个月的试用,到期之后就会报这个错误。 解决方案 查看license GET _license 开启试用license POST _xpack/license/start_trial?acknowledgetrue修改为基础license POST _xpack/license/start_…...
fmql之Linux WDT
正点原子第52章。 基础知识 正点原子教程 fmql-dts 代码 APP代码(不需要编写驱动代码) static int dw_wdt_drv_probe(struct platform_device *pdev) {struct device *dev &pdev->dev;struct watchdog_device *wdd;struct dw_wdt *dw_wdt; …...
【算法学习之路】7.链表算法
链表算法 前言一.原地逆置思路一:头插法思路二:双指针法思路3:递归 例题:1.头插法2.双指针法3,递归 二.双指针快慢指针:一个指针快一个指针慢例题1例题2 前言 我会将一些常用的算法以及对应的题单给写完&am…...
IDEA Commit 模态提交界面关闭VS开启对比
IDEA Commit 模态提交界面关闭VS开启对比 前言开启模态提交界面优点快捷且灵活的选择需要commit文件显示文件修改内容多(主观) 缺点在模态提交界面选择文件,临时关闭模态框重新打开会重置选择的commit文件 关闭模态提交界面优点允许在commit选择文件时查看其它没有修…...
【AI赋能】AI 工具生成视频教材:从创意到成品的全流程指南
AI 工具生成视频教材:从创意到成品的全流程指南 目标 通过本教材,您将学会如何利用 AI 工具(Grok、Sora、Speechify 和 CapCut)生成一个完整的视频,包括脚本生成、视频片段制作、字幕添加、音频生成以及最终剪辑合成…...
qt 操作多个sqlite文件
qt 操作多个sqlite文件 Chapter1 qt 操作多个sqlite文件1. 引入必要的头文件2. 创建并连接多个SQLite数据库3. 代码说明4. 注意事项 Chapter2 qt 多线程操作sqlite多文件1. 引入必要的头文件2. 创建数据库操作的工作线程类3. 在主线程中创建并启动多个工作线程4. 代码说明5. 运…...
WSL with NVIDIA Container Toolkit
一、wsl 下安装 docker 会提示安装 docekr 桌面版,所以直接安装 docker 桌面版本即可 二、安装 NVIDIA Container Toolkit NVIDIA Container Toolkit仓库 https://github.com/NVIDIA/nvidia-container-toolkitgithub.com/NVIDIA/nvidia-container-toolkit 安装…...
Vue 系列之:组件通讯
子组件调用父组件方法 1、直接在子组件中通过 this.$parent.event 来调用父组件的方法 父组件: <template><p><child></child></p> </template> <script>import child from ./child;export default {components: {chi…...
【Linux实践系列】:用c语言实现一个shell外壳程序
🔥本文专栏:Linux Linux实践项目 🌸博主主页:努力努力再努力wz 那么今天我们就要进入Linux的实践环节,那么我们之前学习了进程控制相关的几个知识点,比如进程的终止以及进程的等待和进程的替换,…...
STL map 的 lower_bound(x)、upper_bound(x) 等常用函数
【STL map 简介】 ● STL map 是一种关联容器,存储键值对,每个键(key value)是唯一的,而值(mapped value)可以重复。构建 STL map 时,无论元素插入顺序如何,STL map 中的…...
【A2DP】SBC 编解码器互操作性要求详解
目录 一、SBC编解码器互操作性概述 二、编解码器特定信息元素(Codec Specific Information Elements) 2.1 采样频率(Sampling Frequency) 2.2 声道模式(Channel Mode) 2.3 块长度(Block Length) 2.4 子带数量(Subbands) 2.5 分配方法(Allocation Method) 2…...
Computational Linguistics期刊全解析:领域顶刊的投稿指南与学术价值
在人工智能与语言学交叉融合的浪潮中,《Computational Linguistics》(CL)作为该领域的标杆期刊,始终是研究者发表前沿成果的首选平台。本文将从期刊影响力、投稿策略、收稿方向等角度,为学者提供一份全面的指南。 一、…...
【量化科普】Sharpe Ratio,夏普比率
【量化科普】Sharpe Ratio,夏普比率 🚀量化软件开通 🚀量化实战教程 在量化投资领域,夏普比率(Sharpe Ratio)是一个非常重要的风险调整后收益指标。它由诺贝尔经济学奖得主威廉F夏普(William…...
运行OpenManus项目(使用Conda)
部署本项目需要具备一定的基础:Linux基础、需要安装好Anaconda/Miniforge(Python可以不装好,直接新建虚拟环境的时候装好即可),如果不装Anaconda或者Miniforge,只装过Python,需要确保Python是3.…...
TikTok Shop欧洲市场爆发,欧洲TikTok 运营网络专线成运营关键
TikTok在欧洲的影响力还在持续攀升,日前,TikTok发布了最新的欧盟执行和使用数据报告,报告中提到: 2024年7~12月期间,TikTok在欧盟地区的月活用户达1.591亿,较上一报告期(2024年10月发布…...
基于YOLO11深度学习的电瓶车进电梯检测与语音提示系统【python源码+Pyqt5界面+数据集+训练代码】
《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...
计算机毕业设计SpringBoot+Vue.js制造装备物联及生产管理ERP系统(源码+文档+PPT+讲解)
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
微服务保护:Sentinel
home | Sentinelhttps://sentinelguard.io/zh-cn/ 微服务保护的方案有很多,比如: 请求限流 线程隔离 服务熔断 服务故障最重要原因,就是并发太高!解决了这个问题,就能避免大部分故障。当然,接口的并发…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果