JAVA动态表达式:Antlr4 表达式树解析

接上面

JAVA动态表达式:Antlr4 G4 模板 + 读取字符串表达式结构树-CSDN博客

 目前已经实现了常量及分组常规表达式的解析。

String formula = "'啦啦啦'=='1' and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'";
String formula = "'啦啦啦'=='1' and (1==1 or 2==2) and '1123' contains '1' and '23455' notcontains '5'";
String formula = "'啦啦啦'=='1' and (1 contains 1 or 2 notcontains 2) ";
String formula = "(1==1 or 2==2) and '啦啦啦'=='1'";
String formula = "((1==1) or (2==2)) and '啦啦啦'=='1'";
String formula = "((1==1 and (2==2 or 3==3)) or (2==2 or 3==3)) and '啦啦啦'=='1'";

实现思路通过Antlr4把解析得到表达式树:

下面的RuleEntity rule对象,就是把上面的结构树给拿到了。

// 构建字符流
CodePointCharStream charStream = CharStreams.fromString(formula);
// 从字符流分析词法, 解析为token
ExprLexer lexer = new ExprLexer(charStream);
// 从token进行分析
ExprParser parser = new ExprParser(new CommonTokenStream(lexer));
// 使用监听器,遍历语法树,根据语法定义,prog为语法树的根节点
ParseTree progTree = parser.expression();if (((ExprParser.ExpressionContext) progTree).exception != null) {throw new Exception("输入的表达式不符合解析规则");
}
// 遍历语法树节点
RuleEntity rule = traverseTree(progTree, name, new RuleEntity());

这样通过循环你就能得到这串表达式的每个值:((1==1 and (2==2 or 3==3)) or (2==2 or 3==3)) and '啦啦啦'=='1'

比如,第一个是( ,第二个是(,第三个是1,第四个是==......

这样你就需要通过逻辑去拼接成这样的对象:

{"id":"rule_2o0S3Ar37K","name":"","tierIndex":"1","conditionList":[{"id":"HK3e6pbRh8","type":"group","tierIndex":"2","conditionList":[{"id":"GmaIWw94NU","type":"group","tierIndex":"3","conditionList":[{"id":"gqx7N9E8p6","type":"single","leftOperatorExpression":{"id":"Constant_ZE0K2xEU82","type":"1","valueType":"double","value":"1","label":"数字"},"compareOperation":"1","rightOperatorExpression":{"id":"Constant_35054671Wu","type":"1","valueType":"double","value":"1","label":"数字"},"describe":""},{"id":"MOsI066Zys","type":"symbol","formulaRelation":"and"},{"id":"R364030W6T","type":"group","tierIndex":"4","conditionList":[{"id":"KtCN58q1Qj","type":"single","leftOperatorExpression":{"id":"Constant_3v9x4vQ716","type":"1","valueType":"double","value":"2","label":"数字"},"compareOperation":"1","rightOperatorExpression":{"id":"Constant_20I9PuvuLE","type":"1","valueType":"double","value":"2","label":"数字"},"describe":""},{"id":"1JViMLz2L0","type":"symbol","formulaRelation":"or"},{"id":"5PQD6ZU2a2","type":"single","leftOperatorExpression":{"id":"Constant_K6626YX2ya","type":"1","valueType":"double","value":"3","label":"数字"},"compareOperation":"1","rightOperatorExpression":{"id":"Constant_27885U5143","type":"1","valueType":"double","value":"3","label":"数字"},"describe":""}]}]},{"id":"D5dnzS9162","type":"symbol","formulaRelation":"or"},{"id":"F15k4S12AZ","type":"group","tierIndex":"3","conditionList":[{"id":"gJS0jy1Kl7","type":"single","leftOperatorExpression":{"id":"Constant_Z5v3vD9ky6","type":"1","valueType":"double","value":"2","label":"数字"},"compareOperation":"1","rightOperatorExpression":{"id":"Constant_W6ZlHv110E","type":"1","valueType":"double","value":"2","label":"数字"},"describe":""},{"id":"K967v6PJ8E","type":"symbol","formulaRelation":"or"},{"id":"99L0cJj55g","type":"single","leftOperatorExpression":{"id":"Constant_8VM6MJlQ08","type":"1","valueType":"double","value":"3","label":"数字"},"compareOperation":"1","rightOperatorExpression":{"id":"Constant_4bKLn5xQsA","type":"1","valueType":"double","value":"3","label":"数字"},"describe":""}]}]},{"id":"685x2JL36x","type":"symbol","formulaRelation":"and"},{"id":"tt104S829A","type":"single","leftOperatorExpression":{"id":"Constant_52nUmF4dmO","type":"1","valueType":"string","value":"啦啦啦","label":"字符串"},"compareOperation":"1","rightOperatorExpression":{"id":"Constant_08q1K2KO6s","type":"1","valueType":"string","value":"1","label":"字符串"},"describe":""}]}

 然后下面是用到的实现逻辑:

POM文件

<!--JSON--><dependency><groupId>net.sf.json-lib</groupId><artifactId>json-lib</artifactId><version>2.2.3</version><classifier>jdk15</classifier></dependency><!--动态表达式--><dependency><groupId>org.antlr</groupId><artifactId>antlr4</artifactId><version>4.10.1</version></dependency>
@Testpublic void Test00() throws Exception {//String formula="@prices == 1 and (@val >=1 or @name<=4) and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'";//这个逻辑暂时没开发//String formula = "'啦啦啦'=='1' and 1==1 and '2'=='3' and '1123' contains '1' and '23455' notcontains '5'";//String formula = "'啦啦啦'=='1' and (1==1 or 2==2) and '1123' contains '1' and '23455' notcontains '5'";//String formula = "'啦啦啦'=='1' and (1 contains 1 or 2 notcontains 2) ";//String formula = "(1==1 or 2==2) and '啦啦啦'=='1'";//String formula = "((1==1) or (2==2)) and '啦啦啦'=='1'";String formula = "((1==1 and (2==2 or 3==3)) or (2==2 or 3==3)) and '啦啦啦'=='1'";String json = FormulaToJson.formulaToJson("", formula);System.out.println(json);}
package com.java.core.web.antlr4.util;import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.java.core.web.antlr4.ExprLexer;
import com.java.core.web.antlr4.ExprParser;
import com.java.core.web.antlr4.param.AbnormalParameter;
import com.java.core.web.antlr4.param.DeletionParameter;
import com.java.core.web.antlr4.param.Parameter;
import com.java.core.web.antlr4.param.ParameterPojo;
import com.java.core.web.antlr4.pojo.*;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNode;import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;public class FormulaToJson {/*** 遍历语法树节点** @param tree*/public static RuleEntity traverseTree(ParseTree tree, String name, RuleEntity rule) {//自定义变量// public String type; //类型 1-属性 2-值 (由比较操作符决定)// public String group; //组 0-不用添加组 1-需要添加组 (有一个小括号)// public String bracket;//括号 判断是否是组 (小括号的数量记录)// public String isObject;//是否new object (条件对象 0-不创建 1-创建 由逻辑运算符决定 如 and/or)if (tree instanceof TerminalNode) {TerminalNode terminalNode = (TerminalNode) tree;//得到树节点String text = terminalNode.getText().replace("'", "");//获取条件组List<Condition> list = rule.getConditionList();//判断节点类型 (比较操作符/逻辑运算符号/小括号/中括号/@符)int res = CheckSymbolOptions.getNameOrValue(text);if (res == 1) { //比较操作符rule.setType("2");rule.setEndBracket("0");if (rule.getGroup() == null || rule.getGroup().equals("0")) {if (list.size() > 0) {Condition condition = list.get(list.size() - 1);String symbolOptions = SymbolOptions.getNameOrValue(text);condition.setCompareOperation(symbolOptions);//比较操作(操作符)}} else {//取当前分组的最后一条数据Condition condition = getLastGroupCondition(list, rule);;condition = condition.getConditionList().get(condition.getConditionList().size() - 1);String symbolOptions = SymbolOptions.getNameOrValue(text);condition.setCompareOperation(symbolOptions);//比较操作(操作符)}} else if (res == 2) { //逻辑运算符if (rule.getGroup() == null || rule.getGroup().equals("0")) {//添加条件对象Condition condition = addCondition(name, "symbol", text);list.add(condition);rule.setIsObject("1");//需要添加条件对象  0-不添加 1-添加rule.setType("1");} else {//获得当前组的对象Condition cond = getLastGroupCondition(list, rule);List<Condition> conditionList = cond.getConditionList();//添加条件对象Condition condition = addCondition(name, "symbol", text);conditionList.add(condition);rule.setIsObject("1");//需要添加条件对象  0-不添加 1-添加}} else if (res == 3) { //括号标识符if (text.equals("(")) {if (rule.getId() == null) {//设置rule属性rule.setId(generateId("rule"));//id需要自动生成 rule_xxxxxxxxxx(10位数)rule.setName(name);rule.setSubscript("1");//记录索引rule.setTierIndex("1");//层级索引 需要确定来源}rule.setType("1");if (rule.getBracket() == null || rule.getBracket().equals("0")) {rule.setBracket("1");}int va = Integer.valueOf(rule.getBracket()) + 1;rule.setBracket(String.valueOf(va));//创建对象Condition condition = addCondition(name, "group", null);rule.setGroup("1");if (rule.getGroupIds() == null || rule.getGroupIds().size() == 0) {rule.setGroupIds(new ArrayList<>());}condition.setDescribe(null);if (rule.getSubscript() == null) {rule.setSubscript("1");}int endva = Integer.valueOf(rule.getSubscript()) + 1;rule.setSubscript(String.valueOf(endva));//记录下标condition.setTierIndex(String.valueOf(endva));rule.setIsObject("0");//添加对象后回复初始状态if (list == null) {list = new ArrayList<>();list.add(condition);rule.setConditionList(list);} else if (rule.getGroupIds().size() == 0) {list.add(condition);} else {//保证每个分组都是最后一个Condition cond = getLastGroupCondition(list, rule);condition.setTierIndex(String.valueOf(Integer.valueOf(cond.getTierIndex()) + 1));if (cond.getConditionList() == null) {cond.setConditionList(new ArrayList<>());}cond.getConditionList().add(condition);}//更新新的分组IDrule.getGroupIds().add(condition.getId());rule.setBracket("0");}if (text.equals(")")) {//判断上一层是否是分组,如果不是分组则设置不是分组的标记if (rule.getGroupIds().size() > 0) {//现在使用的组rule.getGroupIds().remove(rule.getGroupIds().size() - 1);}if (rule.getGroupIds().size() == 0) {rule.setGroup("0");}}} else if (res == 4 || text.lastIndexOf("@") >= 0) { //@ 参数标识rule.setType("1");} else {//初始化对象与集合if (list == null || list.size() == 0) {list = new ArrayList<>();Condition condition = addCondition(name, "single", null);list.add(condition);rule.setConditionList(list);}if (rule.getGroup() == null || rule.getGroup().equals("0")) {if (rule.getIsObject() != null) {if (rule.getIsObject().equals("1")) {//创建对象Condition condition = addCondition(name, "single", null);list.add(condition);rule.setIsObject("0");//添加对象后回复初始状态}}} else {if (rule.getIsObject() != null && rule.getIsObject().equals("1")) {Condition cond = getLastGroupCondition(list, rule);List<Condition> conditionList = cond.getConditionList();//创建对象Condition addCondition = addCondition(name, "single", null);conditionList.add(addCondition);rule.setIsObject("0");//添加对象后回复初始状态rule.setType("1");//添加左边值}}Condition condition = null;if (rule.getGroup() != null && rule.getGroup().equals("1")) {condition = getLastGroupCondition(list, rule);//获取最后的分组对象List<Condition> conditionList = condition.getConditionList();Condition cond = null;//初始化对象与集合if (conditionList == null || conditionList.size() == 0) {conditionList = new ArrayList<>();cond = addCondition(name, "single", null);setCondition(cond, text, rule);conditionList.add(cond);condition.setConditionList(conditionList);} else {cond = conditionList.get(conditionList.size() - 1);setCondition(cond, text, rule);}} else {condition = list.get(list.size() - 1);setCondition(condition, text, rule);}}}//递归 循环遍历for (int i = 0; i < tree.getChildCount(); i++) {traverseTree(tree.getChild(i), name, rule);}return rule;}//获取最后一个分组对象private static Condition getLastGroupCondition(List<Condition> list, RuleEntity rule) {String groupId = rule.groupIds.get(rule.groupIds.size() - 1);Condition cond = list.get(list.size() - 1);while (true) {if (cond.getId().equals(groupId)) {break;}cond = cond.getConditionList().get(cond.getConditionList().size() - 1);}return cond;}private static void setCondition(Condition condition, String text, RuleEntity rule) {//获取属性详情,判断属性是否存在,如果存在拿到属性名称、类型等信息String type = DataType.getDataType(text);if (condition.getLeftOperatorExpression() == null || condition.getRightOperatorExpression() == null) {if (rule.getType() == null || rule.getType().equals("1")) {//创建左边运算符表达式LeftOperatorExpression left = addLeftOperatorExpression(type, text);condition.setLeftOperatorExpression(left);rule.setType("0");}if (rule.getType().equals("2")) {//创建右边运算符表达式RightOperatorExpression right = addRightOperatorExpression(type, text);condition.setRightOperatorExpression(right);rule.setType("0");rule.setBracket("0");}//如果都是常量,则进行类型对齐//一边是日期,一边是非日期,则全部改成字符串//一边是数字,一边非数字,则全部改成字符串//或者状态是contains和notcontains(7,8)也需要转成字符串if (condition.getLeftOperatorExpression() != null&& condition.getLeftOperatorExpression().getId().lastIndexOf("Constant") >= 0&& condition.getRightOperatorExpression() != null&& condition.getRightOperatorExpression().getId().lastIndexOf("Constant") >= 0&& (!condition.getLeftOperatorExpression().getValueType().equals(condition.getRightOperatorExpression().getValueType())|| condition.getCompareOperation().equals("7") || condition.getCompareOperation().equals("8"))) {condition.getLeftOperatorExpression().setValueType("string");condition.getLeftOperatorExpression().setLabel(SymbolOptions.getNameOrValue("string"));condition.getRightOperatorExpression().setValueType("string");condition.getRightOperatorExpression().setLabel(SymbolOptions.getNameOrValue("string"));}}}/*** 创建 Condition 对象** @param name* @param type* @return*/public static Condition addCondition(String name, String type, String text) {//创建对象Condition condition = new Condition();//设置条件组属性condition.setFormulaRelation(text);condition.setId(generateId(""));//id需要自动生成 bc3369691d(10位数)condition.setType(type);//类型(单个的 如何获取??)if (text == null) {condition.setDescribe(name);//描述}if (type.equals("group")) {condition.setDescribe("");}return condition;}/*** 创建左边运算符表达式** @param type* @param text* @return*/public static LeftOperatorExpression addLeftOperatorExpression(String type, String text) {LeftOperatorExpression left = new LeftOperatorExpression();if (text.lastIndexOf("@") >= 0) {left.setId(generateId("Parameter"));//id需要自动生成 Parameter_xxxxxxxxxx(10位数)//是变量left.setType("6");left.setValue(text);//值} else {left.setId(generateId("Constant"));//id需要自动生成 Parameter_xxxxxxxxxx(10位数)//是常量left.setType("1");left.setValue(text);//值}left.setValueType(type);//值类型left.setLabel(SymbolOptions.getNameOrValue(type));//参数名称(属性值的名称 @ 如何定义?没有依据)return left;}/*** 创建右边运算符表达式** @param type* @param text* @return*/public static RightOperatorExpression addRightOperatorExpression(String type, String text) {RightOperatorExpression right = new RightOperatorExpression();if (text.lastIndexOf("@") >= 0) {right.setId(generateId("Parameter"));//id需要自动生成 Parameter_xxxxxxxxxx(10位数)//是变量right.setType("6");right.setValue(text);//值} else {right.setId(generateId("Constant"));//id需要自动生成 Parameter_xxxxxxxxxx(10位数)//是常量right.setType("1");right.setValue(text);//值}right.setValueType(type);//值类型right.setLabel(SymbolOptions.getNameOrValue(type));//参数名称(属性值的名称 @ 如何定义?没有依据)return right;}/*** 将公式转换成json** @param name    公式名称* @param formula 公式* @return*/public static String formulaToJson(String name, String formula) throws Exception {// 构建字符流CodePointCharStream charStream = CharStreams.fromString(formula);// 从字符流分析词法, 解析为tokenExprLexer lexer = new ExprLexer(charStream);// 从token进行分析ExprParser parser = new ExprParser(new CommonTokenStream(lexer));// 使用监听器,遍历语法树,根据语法定义,prog为语法树的根节点ParseTree progTree = parser.expression();if (((ExprParser.ExpressionContext) progTree).exception != null) {throw new Exception("输入的表达式不符合解析规则");}// 遍历语法树节点RuleEntity rule = traverseTree(progTree, name, new RuleEntity());//设置自定义变量为null,做转换json忽略空置预处理if (rule != null) {rule.setType(null);rule.setIsObject(null);rule.setGroup(null);rule.setGroupIds(null);rule.setBracket(null);rule.setEndBracket(null);rule.setSubscript(null);}// 初始化Jackson的ObjectMapperObjectMapper objectMapper = new ObjectMapper();objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); // 忽略空值字段// 将对象转换为JSON字符串String json = null;try {json = objectMapper.writeValueAsString(rule);} catch (JsonProcessingException e) {throw new RuntimeException(e);}return json;}/*** 数字和字母随机组合10位数** @param name* @return*/public static String generateId(String name) {String generate = "";Random random = new Random();for (int i = 0; i < 10; i++) {// 输出字母还是数字String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";// 字符串if ("char".equalsIgnoreCase(charOrNum)) {// 取得大写字母还是小写字母int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;generate += (char) (choice + random.nextInt(26));} else if ("num".equalsIgnoreCase(charOrNum)) { // 数字generate += String.valueOf(random.nextInt(10));}}if (name == null || "".equals(name)) {return generate;}return name + "_" + generate;}/*** 根据属性ID 获取表单属性集合** @param parameterId* @return*/public static List<Parameter> getParameterById(Long parameterId) {//定义属性集合List<Parameter> parameterList = new ArrayList<>();if (parameterId != null) {//属性查询操作//获取属性值String jsonString = "{\"list\":[],\"config\":{\"layout\":\"horizontal\",\"labelCol\":{\"xs\":4,\"sm\":4,\"md\":4,\"lg\":4,\"xl\":4,\"xxl\":4},\"wrapperCol\":{\"xs\":18,\"sm\":18,\"md\":18,\"lg\":18,\"xl\":18,\"xxl\":18},\"view\":[{\"viewMode\":1,\"viewName\":\"发起视图\",\"controlList\":[]},{\"viewMode\":2,\"viewName\":\"审批视图\",\"controlList\":[]},{\"viewMode\":3,\"viewName\":\"查看视图\",\"controlList\":[]},{\"viewMode\":4,\"viewName\":\"打印视图\",\"controlList\":[]}],\"parameter\":[{\"name\":\"金额\",\"code\":\"Price\",\"describe\":\"结算金额\",\"value\":\"5000\",\"type\":\"string\",\"id\":\"793565f5314254944cdf1d79b2e20df6\"},{\"name\":\"数字\",\"code\":\"Price\",\"describe\":\"1\",\"value\":\"1\",\"type\":\"double\",\"id\":\"fea23b17d0d4f44de96cc0f01ce63abf\"}],\"cache\":false,\"hideRequiredMark\":false,\"hiddenFieldStrategy\":1,\"formStyle\":1,\"formStyleWidth\":\"95%\",\"formStyleBgColor\":\"#ecf2f7\",\"formStyleBg\":\"\",\"formHead\":\"\",\"formStyleTitle\":\"Test_Xiangfei\",\"formTitleStatus\":false,\"formSystemStyleId\":2,\"isShowHeader\":true,\"isFold\":false,\"isShowBoxIcon\":true,\"formStyleTitleCss\":{\"align\":\"center\",\"fontSize\":18,\"color\":\"#0c1b74\"},\"event\":{\"init\":null},\"eventList\":[],\"opinionExtra\":true}}";//通过fromObject将json字符串翻译成JSON对象(JSONObject)JSONObject jsonObject = JSONObject.parseObject(jsonString);//获取JSONObject对象值String config = jsonObject.getString("config");//结果就是简单的值类型if (config.length() > 0) {//二次转换将json对象值翻译成JSON对象JSONObject jsonConfig = JSONObject.parseObject(config);//获取JSONObject对象值String parameter = jsonConfig.getString("parameter");if (parameter.length() > 0) {//将对象属性转换成属性集合parameterList = JsonUtil.jsonToList(parameter, Parameter.class);}}}return parameterList;}//判断属性是否存在public static ParameterPojo checkParameter(String param, List<Parameter> list) {ParameterPojo parameterPojo = new ParameterPojo();//定义属性Code集合List<String> codeList = new ArrayList<>();if (list.size() > 0) {for (Parameter par : list) {if (par != null) {codeList.add(par.getCode());}}}//判断属性int res = Collections.frequency(codeList, param);if (res == 1) {//存在属性Parameter parameter = new Parameter();for (Parameter par : list) {if (par.getCode().equals(param)) {}}parameter.setCode(param);parameterPojo.setParameter(parameter);} else if (res > 1) {//一对多属性 需要抛异常AbnormalParameter abnormalParameter = new AbnormalParameter();abnormalParameter.setCode(param);parameterPojo.setAbnormalParameter(abnormalParameter);} else {//缺失属性DeletionParameter deletionParameter = new DeletionParameter();deletionParameter.setCode(param);parameterPojo.setDeletionParameter(deletionParameter);}return parameterPojo;}}

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

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

相关文章

SAP 角色授权账户 重复的问题 解决方案

直接从agr_usrs 里面删除新的 *&---------------------------------------------------------------------* *& Report ZRPT_BC_ROLEASSIGN_RM_DUP *&---------------------------------------------------------------------* *&角色授权去重 *&--------…

植物大战僵尸杂交版 fatal error及问题解决闪退

echo off set KEY_NAMESoftware\PopCap\PlantsVsZombies set VALUE_NAMEScreenmode set DATA0 reg add HKCU%KEY_NAME% /v %VALUE_NAME% /t REG_DWORD /d %DATA% /f if %errorlevel% neq 0 ( echo 注册表数值数据修改失败 ) else ( echo 注册表数值数据已成功修改为0 ) 将上述…

requests post json/data;requests response 接收不同数据

1、requests post json/data 在Python的requests库中&#xff0c;当你发送POST请求时&#xff0c;可以选择使用json参数或data参数来传递数据。这两者之间的主要区别在于它们如何被序列化和发送到服务器。 json参数&#xff1a; 当你使用json参数时&#xff0c;requests库会自…

【CTF Web】CTFShow 数据库恶意下载 Writeup(目录扫描+mdb文件泄露+Access脱库)

数据库恶意下载 10 mdb文件是早期aspaccess构架的数据库文件&#xff0c;文件泄露相当于数据库被脱裤了。 解法 用 dirsearch 扫描。 dirsearch -u 4b9b415f-4062-4bba-a6f5-3b107804043f.challenge.ctf.show找到一个 db 目录。 扫描 db 目录。 dirsearch -u 4b9b415f-4062-…

湖仓一体全面开启实时化时代

摘要&#xff1a;本文整理自阿里云开源大数据平台负责人王峰&#xff08;莫问&#xff09;老师在5月16日 Streaming Lakehouse Meetup Online 上的分享&#xff0c;主要介绍在新一代湖仓架构上如何进行实时化大数据分析。内容主要分为以下五个部分&#xff1a; Data Lake Dat…

Spring Boot 项目启动时在 prepareContext 阶段做了哪些事?

概览 如果你对Spring Boot 启动流程还不甚了解&#xff0c;可阅读《Spring Boot 启动流程详解》这篇文章。如果你已了解&#xff0c;那就让我们直接看看prepareContext() 源码。 private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironme…

mmap引起的内存泄漏分析

最近遇到一个内存泄漏问题&#xff0c;由于问题出现在客户端&#xff0c;只能通过客户提供的Log来分析。 根据客户提供的/proc/meminfo数据发现&#xff0c;MemAvailable 由294072kB减小至18128kB&#xff0c;减小约269MB&#xff0c;引起该变化的最直接原因是PageTables由614…

CTFshow-web sql注入

Web171 1 在题目中可以看到查询语句为 "select username,password from user where username !flag and id ".$_GET[id]." limit 1;"; 直接使用万能密码 查到了所有用户 获得flag Web172 0 可以看到返回逻辑显示 如果返回的查询数据中username不等于fl…

Linux基础IO【II】真的很详细

目录 一.文件描述符 1.重新理解文件 1.推论 2.证明 2.理解文件描述符 1.文件描述符的分配规则 3.如何理解文件操作的本质&#xff1f; 4.输入重定向和输出重定向 1.原理 2.代码实现重定向 3.dup函数 ​编辑 4.命令行中实现重定向 二.关于缓冲区 1.现象 …

Web应用安全测试-业务功能滥用(一)

Web应用安全测试-业务功能滥用&#xff08;一&#xff09; 1、短信定向转发 漏洞描述&#xff1a;短信接收人可任意指定 测试方法&#xff1a;拦截发送短信的请求&#xff0c;将手机号改为测试人员的手机号&#xff0c;测试是否可接收短信验证码。 风险分析&#xff1a;攻击…

echarts学习:使用dataset管理数据

前言 在我们公司的组件库中有许多echarts图表相关的组件&#xff0c;这些组件在使用时&#xff0c;只需将图表数据以特定的格式传入组件中&#xff0c;十分方便。因此当我得知echarts 可以使用dataset集中管理数据时&#xff0c;我就决定自己一定要搞懂它&#xff0c;于是在最…

oracle 删除当前用户下所有表

荆轲刺秦王 通常呢 我们将正式环境的 oracle 数据库 导出成 dmp 文件&#xff0c;然后导入到测试环境或者本地环境&#xff0c;期间可能会出现各种问题。那么如何使错误的导入数据全部删除呢。可以这样做&#xff1a; 1. 本地虚拟机启动 oracle 服务 2. sqldeveloper 连接 o…

vue 安装依赖报错

解决方法&#xff1a; npm install --legacy-peer-deps 然后再运行项目即可。

LabVIEW利用旋转编码器脉冲触发数据采集

利用旋转编码器发出的脉冲控制数据采集&#xff0c;可以采用硬件触发方式&#xff0c;以确保每个脉冲都能触发一次数据采集。本文提供了详细的解决方案&#xff0c;包括硬件连接、LabVIEW编程和触发设置&#xff0c;确保数据采集的准确性和实时性。 一、硬件连接 1. 旋转编码…

北斗应急通信手持终端如何在户外使用

北斗应急通信手持终端在户外的使用&#xff0c;需要遵循一定的步骤和注意事项以确保其高效、安全地运作。以下是一个清晰的使用指南&#xff1a; 一、准备阶段 检查电量&#xff1a;确保北斗应急通信手持终端的电量充足&#xff0c;并携带备用电源以应对长时间使用的情况。 熟…

Ubuntu系统设置中文输入法

重新设置超级用户权限(root)密码(非必要) sudo passwd root 需要注意的是Ubuntu的root密码不能少于8个字符 设置成功后输入命令和新的密码即可无需输入sudo启用root命令 su - 更新软件包列表 sudo apt update sudo apt upgrade 安装fcitx5输入法框架 个别情况需要卸载旧的…

红黑树【C++实现】

文章目录 红黑树的概念红黑树的性质红黑树的操作红黑树结点的定义红黑树的插入情况一&#xff1a;插入结点的叔叔存在&#xff0c;且叔叔的颜色是红色情况二: 插入结点的叔叔存在&#xff0c;且叔叔的颜色是黑色情况三: 插入结点的叔叔不存在 红黑树的验证红黑树的查找 红黑树的…

实现直流高电压(100Vdc~1000Vdc)检测的采样电路(隔离方案)

目前&#xff0c;在电力系统自动化领域、新能源电动汽车领域以及高压储能领域&#xff0c;经常需要采样、检测高压直流母线电压&#xff0c;一般直流高压可能达到100Vdc&#xff5e;1000Vdc&#xff0c;结合电路成本和采样精度&#xff0c;我们设计人员就需要选择合适的采样电路…

【elementui源码解析】如何实现自动渲染md文档-第一篇

文章目录 目录 背景 获取源码 代码分析 背景 之前基于vant3的源码开发过二次开发过组件&#xff0c;其中vant实现了将md文档渲染到界面上&#xff0c;有天突发奇想想知道这是如何实现的将md文档渲染到界面上的&#xff0c;因为平时开发中使用elementui占多数&#xff0c;所…

java线程池讲解!核心参数

创建方式 | 构造方法 Executor构造方法 存放线程的容器&#xff1a; private final HashSet<Worker> workers new HashSet<Worker>(); 构造方法&#xff1a; public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit uni…