JSqlParser的使用

简介

        JSqlParse是一款很精简的sql解析工具,它可以将常用的sql文本解析成具有层级结构的语法树,我们可以针对解析后的节点进行处理(增加、移除、修改等操作),从而生成符合我们业务要求的sql,比如添加过滤条件等等

     JSqlParse采用访问者模式

项目简介

        

项目结构非常简单,从截图上看就5个包。如果对源码感兴趣的可以直接从github上下载源码包调试。其中expression包包含了所有的sql表达式的抽象对象:

statement包含了所有sql语句的类型,比如:增删改查,ddl语句,rollback语句等等

schema包是对数据库基本单元的抽象:服务器、数据库、表、列等等

parser包是整个解析的核心逻辑,感兴趣的可以自行源码调试

使用示例

        上面已经做了关于该解析工具的简单介绍,对于工具类,最重要的使用。以下举例关于增、删、改、查的sql语句中,均增加一列为例介绍该工具的简单使用

依赖引入

<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>4.5</version>
</dependency>

新增add

原始sql:insert into t_user_info(id,user_name,address) values('123','zhangsan','龙华')

期望在执行该sql时,能增加一列STATUS作为插入

都是一些api的运用,相关代码如下:

package com.lyc.boot.client.test.insert;

import com.lyc.boot.client.test.insert.visitor.InsertStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.values.ValuesStatement;

import java.util.List;

import static com.lyc.boot.client.test.CommonUtil.printStatement;
import static com.lyc.boot.client.test.CommonUtil.printTableName;

@Slf4j
public class InsertCommonTest {

    private static final String INSERT_COMMON = "insert into t_user_info(id,user_name,address) values('123','zhangsan','龙华')";

    public static void main(String[] args) throws JSQLParserException {
        useCommonAddColumn();
//        useVisitorAddColumn();
    }

    private static void useCommonAddColumn() throws JSQLParserException {
        Statement statement = CCJSqlParserUtil.parse(INSERT_COMMON);
        printStatement(statement);
        if (statement instanceof Insert) {
            Insert insert = (Insert)statement;
            printTableName(insert.getTable());
            List<Column> columns = insert.getColumns();
            columns.add(new Column("STATUS"));

            Select select = insert.getSelect();
            SelectBody selectBody = select.getSelectBody();
            if (selectBody instanceof SetOperationList) {
                SetOperationList operationList = (SetOperationList)selectBody;
                List<SelectBody> selects = operationList.getSelects();
                for (SelectBody body : selects) {
                    if (body instanceof ValuesStatement) {
                        ValuesStatement valuesStatement = (ValuesStatement)body;
                        ItemsList itemsList = valuesStatement.getExpressions();
                        if(itemsList instanceof ExpressionList) {
                            ExpressionList expressionList = (ExpressionList)itemsList;
                            List<Expression> expressions = expressionList.getExpressions();
                            for (Expression expression : expressions) {
                                if(expression instanceof RowConstructor) {
                                    RowConstructor rowConstructor = (RowConstructor)expression;
                                    ExpressionList exprList = rowConstructor.getExprList();
                                    List<Expression> rowConstructorExList = exprList.getExpressions();
                                    rowConstructorExList.add(new StringValue("0"));
                                }
                            }
                        }
                    }
                }
            }
        }
        printStatement(statement);
    }

    /**
     * 使用访问者方式增加insert的column
     *
     * @throws JSQLParserException
     */
    private static void useVisitorAddColumn() throws JSQLParserException {
        Statement statement = CCJSqlParserUtil.parse(INSERT_COMMON);
        printStatement(statement);

        statement.accept(new InsertStatementVisitor());
        printStatement(statement);
    }


}
package com.lyc.boot.client.test.insert.visitor;

import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;

import java.util.List;

import static com.lyc.boot.client.test.CommonUtil.printTableName;

public class InsertStatementVisitor extends StatementVisitorAdapter {

    @Override
    public void visit(Insert insert) {
        printTableName(insert.getTable());
        List<Column> columns = insert.getColumns();
        columns.add(new Column("status"));

        Select select = insert.getSelect();
        SelectBody selectBody = select.getSelectBody();
        selectBody.accept(new InsertSelectVisitor());
    }
}
package com.lyc.boot.client.test.insert.visitor;

import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.statement.select.SelectBody;
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;
import net.sf.jsqlparser.statement.select.SetOperationList;
import net.sf.jsqlparser.statement.values.ValuesStatement;

import java.util.List;

public class InsertSelectVisitor extends SelectVisitorAdapter {
    @Override
    public void visit(SetOperationList setOpList) {
        List<SelectBody> selects = setOpList.getSelects();
        for (SelectBody body : selects) {
            body.accept(this);
        }
    }

    @Override
    public void visit(ValuesStatement valuesStatement) {
        ItemsList itemsList = valuesStatement.getExpressions();
        itemsList.accept(new InsertItemsListVisitor());
    }
}
package com.lyc.boot.client.test.insert.visitor;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.util.validation.validator.ItemsListValidator;

import java.util.List;

public class InsertItemsListVisitor extends ItemsListValidator {

    @Override
    public void visit(ExpressionList expressionList) {
        List<Expression> expressions = expressionList.getExpressions();
        for (Expression expression : expressions) {
            expression.accept(new InsertExpressionVisitor());
        }
    }
}
package com.lyc.boot.client.test.insert.visitor;

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;

import java.util.List;

public class InsertExpressionVisitor extends ExpressionVisitorAdapter {
    @Override
    public void visit(RowConstructor rowConstructor) {
        ExpressionList exprList = rowConstructor.getExprList();
        List<Expression> expressions = exprList.getExpressions();
        expressions.add(new StringValue("0"));
    }
}

      以上是关于新增sql增加一列作为插入的简单运用,其中有通过类型判断处理和通过访问者模式处理(基于java多态实现),最终打印的结果如下:

删除delete

原sql:delete from t_user_info where user_name = ? and addres = ?

期望在删除时增加过滤条件STATUS='0'

相关代码如下:

package com.lyc.boot.client.test.delete;

import com.lyc.boot.client.test.delete.visitor.DeleteStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;

import static com.lyc.boot.client.test.CommonUtil.printStatement;

@Slf4j
public class DeleteCommonTest {

    private static final String DELETE_COMMON = "delete from t_user_info where user_name = ? and addres = ?";

    public static void main(String[] args) throws JSQLParserException {
//        commonAddColumn();
        visitorAddColumn();
    }

    private static void visitorAddColumn() throws JSQLParserException{
        Statement statement = CCJSqlParserUtil.parse(DELETE_COMMON);
        printStatement(statement);
        statement.accept(new DeleteStatementVisitor());
        printStatement(statement);
    }

    private static void commonAddColumn() throws JSQLParserException {
        Statement statement = CCJSqlParserUtil.parse(DELETE_COMMON);
        printStatement(statement);
        if(statement instanceof Delete) {
            Delete delete = (Delete)statement;
            DeleteStatementVisitor.addColumn(delete);
        }
        printStatement(statement);
    }
}

package com.lyc.boot.client.test.delete.visitor;

import com.lyc.boot.client.test.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.delete.Delete;

import java.util.Objects;

@Slf4j
public class DeleteStatementVisitor extends StatementVisitorAdapter {

    @Override
    public void visit(Delete delete) {
        addColumn(delete);
    }

    public static void addColumn(Delete delete) {
        CommonUtil.printTableName(delete.getTable());
        Expression where = delete.getWhere();
        Parenthesis parenthesis = new Parenthesis(new EqualsTo(new Column("STATUS"), new StringValue("1")));
        if (Objects.isNull(where)) {
            delete.setWhere(parenthesis);
        } else {
            delete.setWhere(new AndExpression(where,parenthesis));
        }
    }
}

执行结果如下图:

修改update

原sql为:update t_user_info set user_name = ?,address = ? where id = ? and score = ?

期望在修改时set增加STATUS = ? where条件增加STATUS = '1'

package com.lyc.boot.client.test.update;

import com.lyc.boot.client.test.update.visitor.UpdateStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;

import java.util.ArrayList;
import java.util.Objects;

import static com.lyc.boot.client.test.CommonUtil.printStatement;

/**
 * update语句修改
 *
 *
 */
@Slf4j
public class UpdateCommonTest {

    private static final String COMMON_UPDATE = "update t_user_info set user_name = ?,address = ? where id = ? and score = ?";

    public static void main(String[] args) throws JSQLParserException {
//        commonUpdateAddColumn();
        visitorAddColumn();
    }

    private static void visitorAddColumn() throws JSQLParserException{
        Statement statement = CCJSqlParserUtil.parse(COMMON_UPDATE);
        printStatement(statement);

        statement.accept(new UpdateStatementVisitor());
        printStatement(statement);
    }

    private static void commonUpdateAddColumn() throws JSQLParserException {
        Statement statement = CCJSqlParserUtil.parse(COMMON_UPDATE);
        printStatement(statement);
        if(statement instanceof Update) {
            Update update = (Update)statement;
            Table table = update.getTable();
            ArrayList<UpdateSet> updateSets = update.getUpdateSets();
            Column column = new Column("STATUS");
            StringValue stringValue = new StringValue("?");
            JdbcParameter jdbcParameter = new JdbcParameter();
            UpdateSet updateSet = new UpdateSet(column,jdbcParameter);
            updateSets.add(updateSet);

            Expression whereExpression = update.getWhere();
            EqualsTo equalsTo = new EqualsTo(new Column("STATUS"), new StringValue("1"));
            Parenthesis parenthesis = new Parenthesis(equalsTo);

            if (Objects.isNull(whereExpression)) {
                update.setWhere(parenthesis);
            } else {
                update.setWhere(new AndExpression(whereExpression,parenthesis));
            }
        }
        printStatement(statement);
    }

}
package com.lyc.boot.client.test.update.visitor;

import com.lyc.boot.client.test.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.update.Update;
import net.sf.jsqlparser.statement.update.UpdateSet;

import java.util.ArrayList;
import java.util.Objects;

@Slf4j
public class UpdateStatementVisitor extends StatementVisitorAdapter {

    @Override
    public void visit(Update update) {
        CommonUtil.printTableName(update.getTable());

        ArrayList<UpdateSet> updateSets = update.getUpdateSets();
        UpdateSet statusUpdateSet = new UpdateSet(new Column("STATUS"), new JdbcParameter());
        updateSets.add(statusUpdateSet);

        Expression where = update.getWhere();
        Parenthesis parenthesis = new Parenthesis(new EqualsTo(new Column("STATUS"), new StringValue("1")));

        if (Objects.isNull(where)) {
            update.setWhere(parenthesis);
        } else {
            update.setWhere(new AndExpression(where,parenthesis));
        }
    }
}

执行结果如下图所示:

查询select

原sql如下:select id as id,user_name as userName,address as address from t_user_info where id = ? and user_name = ? order by create_time desc

期望在查询时增加where的过滤条件STATUS = '1'

package com.lyc.boot.client.test.select;

import com.lyc.boot.client.test.select.visitor.SelectSelectVisitor;
import com.lyc.boot.client.test.select.visitor.SelectStatementVisitor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.select.*;

import static com.lyc.boot.client.test.CommonUtil.printStatement;

@Slf4j
/**
 * 给查询条件添加更多的过滤条件
 *
 * and status = '1'
 */
public class SelectCommonTest {

    private static final String SELECT_COMMON = "select id as id,user_name as userName,address as address from t_user_info where id = ? and user_name = ? order by create_time desc";

    public static void main(String[] args) throws JSQLParserException {
//        commonSelectAddWhere();
        visitorSelectAddWhere();
    }

    private static void visitorSelectAddWhere() throws JSQLParserException{
        Statement statement = CCJSqlParserUtil.parse(SELECT_COMMON);
        printStatement(statement);
        statement.accept(new SelectStatementVisitor());
        printStatement(statement);
    }

    private static void commonSelectAddWhere() throws JSQLParserException {
        Statement statement = CCJSqlParserUtil.parse(SELECT_COMMON);
        printStatement(statement);
        if (statement instanceof Select) {
            Select select = (Select)statement;
            SelectBody selectBody = select.getSelectBody();
            if (selectBody instanceof PlainSelect) {
                PlainSelect plainSelect = (PlainSelect)selectBody;
                SelectSelectVisitor.setWhereExpression(plainSelect);
            }
        }
        printStatement(statement);
    }

}
package com.lyc.boot.client.test.select.visitor;

import net.sf.jsqlparser.statement.StatementVisitorAdapter;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectBody;

public class SelectStatementVisitor extends StatementVisitorAdapter {

    @Override
    public void visit(Select select) {
        SelectBody selectBody = select.getSelectBody();
        selectBody.accept(new SelectSelectVisitor());
    }
}
package com.lyc.boot.client.test.select.visitor;

import com.lyc.boot.client.test.CommonUtil;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.SelectVisitorAdapter;

import java.util.List;
import java.util.Objects;

@Slf4j
public class SelectSelectVisitor extends SelectVisitorAdapter {

    @Override
    public void visit(PlainSelect plainSelect) {
        setWhereExpression(plainSelect);
    }

    public static void setWhereExpression(PlainSelect plainSelect) {
        Expression where = plainSelect.getWhere();
        EqualsTo equalsTo = new EqualsTo(new Column("STATUS"), new StringValue("1"));
        Parenthesis parenthesis = new Parenthesis(equalsTo);

        if (Objects.isNull(where)) {
            plainSelect.setWhere(parenthesis);
        } else {
            AndExpression andExpression = new AndExpression(where, parenthesis);
            plainSelect.setWhere(andExpression);
        }
    }
}

执行结果如下图:

扩展简析

jsqlParser的实际之一就是在mybaits-plus中的各种插件,比如:多租户插件com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor

该插件的作用是:在执行sql时在where条件处增加了过滤条件(默认是tenant_id = ?,具体的字段可以自己配置实现)

当配置了MybatisPlusInterceptor,并且添加了TenantLineInnerInterceptor时,在执行sql时会被该拦截器拦截,具体的源码流程如下:

当执行查询语句时,sql会被MybatisPlusInterceptor插件拦截,插件调TenantLineInnerInterceptor的beforeQuery方法触发

其中BaseMultiTableInnerInterceptor是JsqlParserSupport的子类,提供了模板方法用于修改sql

图上,生成的sql由com.baomidou.mybatisplus.extension.parser.JsqlParserSupport#parserSingle方法决定

最终执行sql解析完成添加过滤条件的操作:

在TenantLineInnerInterceptor插件中,最终是在where结尾出添加了(默认)tenant_id = xxxx的过滤条件,完成多租户数据隔离处理的。具体的源码逻辑可以调试根据

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

随笔】Git -- 基本概念和使用方式(五)

&#x1f48c; 所属专栏&#xff1a;【Git】 &#x1f600; 作  者&#xff1a;我是夜阑的狗&#x1f436; &#x1f680; 个人简介&#xff1a;一个正在努力学技术的CV工程师&#xff0c;专注基础和实战分享 &#xff0c;欢迎咨询&#xff01; &#x1f496; 欢迎大…

鸿蒙Harmony应用开发—ArkTS(stateStyles:多态样式)

Styles和Extend仅仅应用于静态页面的样式复用&#xff0c;stateStyles可以依据组件的内部状态的不同&#xff0c;快速设置不同样式。这就是我们本章要介绍的内容stateStyles&#xff08;又称为&#xff1a;多态样式&#xff09;。 概述 stateStyles是属性方法&#xff0c;可以…

【工具使用】VScode如何设置中文环境

操作步骤 1.1 安装中文插件 1.2 设置为中文&#xff0c;然后重启 按照插件的使用方法介绍设置中文&#xff1a; 按下“CtrlShiftP”组合键以显示“命令面板”&#xff1a; 输入“dispaly”&#xff0c;选择“Configure Display Language”&#xff1a; 选择“中文简体” …

Python Flask 表单的使用

新建templ;ates/index.html 内容如下 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body> <form action"">账号&#xff1a;<input …

能耗采集与分析 用能计费与收费【产业园区综合计费——安科瑞解决方案】

背景 2022年《非电网直接供电电费收取公示暂行办法》的通知要求由商业综合体、产业园区、物业、写字楼等供电主体体应按照终端用户用电电压等级对应的目录电价收取电费&#xff0c;不得在电费中加收其他费用。&#xff0c;按照“终端用户用电电压等级目录平段电价上浮幅度”确…

Docker构建多平台(x86,arm64)构架镜像

这里写自定义目录标题 背景配置buildx开启experimental重启检查 打包 背景 docker镜像需要支持不同平台架构 配置buildx 开启experimental vi /etc/docker/daemon.json {"experimental": true }或者 重启检查 # 验证buildx版本 docker buildx version# 重启do…

MNN 执行推理(九)

系列文章目录 MNN createFromBuffer&#xff08;一&#xff09; MNN createRuntime&#xff08;二&#xff09; MNN createSession 之 Schedule&#xff08;三&#xff09; MNN createSession 之创建流水线后端&#xff08;四&#xff09; MNN Session 之维度计算&#xff08;五…

基于python+vue的O2O生鲜食品订购flask-django-nodejs-php

近年来互联网络的迅猛发展和电子终端设备的普及&#xff0c;赋予了各行业充足的发展空间。微信小程序的O2O生鲜食品订购相比于传统信息技术&#xff0c;时效性是它最大的特色&#xff0c;已经在电子娱乐、经济等中发挥着举足轻重的作用。短时间内迅速扩大了线上管理系统的规模。…

【QT入门】 Qt自定义信号后跨线程发送信号

往期回顾&#xff1a; 【QT入门】 lambda表达式(函数)详解-CSDN博客 【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号 由于Qt的子线程是无法直接修改ui&#xff0c;需要发送信号到ui线程进行修改…

Linux centos 安装PHP8.2或其他版本等 仍显示5.4或者其他版本---需要修改环境变量

查询php文件 find / -name php 在不同的文件夹下查看php版本&#xff08;php安装路径每个人不一样&#xff0c;根据自己查到的php冷路径去执行&#xff09; 解决方法&#xff1a;环境变量中加上正确PHP版本的路径 编辑环境变量文件 vim /etc/profile 在文件里增加如何代码…

如何使用Excel创建一个行政考勤表

在企业和机构中&#xff0c;行政考勤管理是一项重要的日常工作&#xff0c;它涉及到员工的出勤情况、请假记录、加班情况等。使用Excel创建一个行政考勤表可以帮助管理者有效地记录和跟踪员工的考勤情况&#xff0c;下面将详细介绍如何使用Excel创建一个行政考勤表。 第一部分&…

重新配置node.js,npm,环境变量

起因是检查最近收到的一些朋友分享给我的各种资料&#xff0c;什么前端&#xff0c;后端&#xff0c;java,go,python等语言&#xff0c;想着将一个模拟QQ音乐的一个源代码进行跑通&#xff0c;看看有什么特别之处。如下图 出现了node环境路径问题&#xff0c;参考链接 https:/…

小孔平板应力集中问题matlab有限元编程【源码+PPT讲义】|三节点三角形单元|平面单元|稀疏矩阵 |Comsol网格

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《有限元编程从入门到精通》本专栏旨在提供 1.以案例的形式讲解各类有限元问题的程序实现&#xff0c;并提供所有案例完整源码&#xff1b;2.单元…

Domino中启用IPv6支持

大家好&#xff0c;才是真的好。 虽然这周末的新闻很多&#xff0c;例如HCL又发布了Nomad Web 1.0.11,还有Verse 3.2.1等更新。 但是但是&#xff0c;每周五的新闻大家看得很少&#xff0c;所以我们……留到下周五再讲述产品更新的新闻和信息吧。 今天讲的是Domino中如何启用…

【图解物联网】第6章 物联网与数据分析

6.1 传感器数据与分析 从前几章中我们已经了解到&#xff0c;只要把配备传感器的设备连接到网络&#xff0c;就能把所有的信息采集到物联网服务之中&#xff08;图6.1&#xff09;。 从工业角度而言&#xff0c;给工厂中的生产流水线和流通的产品打上电子标签&#x…

每日五道java面试题之springboot篇(二)

目录&#xff1a; 第一题. 你如何理解 Spring Boot 配置加载顺序&#xff1f;第二题. Spring Boot 中如何解决跨域问题 ?第三题. 什么是 CSRF 攻击&#xff1f;第四题. 比较一下 Spring Security 和 Shiro 各自的优缺点 ?第五题. bootstrap.properties 和 application.proper…

hcia datacom课程学习(3):http与https、FTP

1.超文本传输协议&#xff1a;http与https &#xff08;1&#xff09;用来访问www万维网。 wwwhttp&#xff0b;html&#xff0b;URLweb &#xff08;2&#xff09;它们提供了一种发布和接受html界面的方法&#xff1a;当在网页输入URL后&#xff0c;从服务器获取html文件来…

【效率提升】IDEA中书签功能的妙用

这里写目录标题 1.概述2.书签功能介绍2.1.书签创建和删除2.2.书签列表2.3.自定义书签名2.4.带标签的书签创建2.5.标签快速跳转&#xff08;1到9&#xff09;2.6.其他标签快捷键2.7.其他补充 3.写到最后 1.概述 在多年的代码开发工作中&#xff0c;有一些问题困扰我很长的时间&…

【python开发】安装配置启动+数据库管理+表管理+数据行管理+python操作Mysql及相关安全的问题

Mysql入门 一、安装&启动1、安装2、测试3、设置和修改root密码 二、数据库管理1、内置客户端操作&#xff08;1&#xff09;查看当前所有的数据库(show databases);&#xff08;2&#xff09;创建数据库&#xff1a;create database learn&#xff08;数据库名&#xff09;…

解决vue3中使用v-html,click不生效的问题

问题背景 说明&#xff1a; 前端接收到来自后端的一个长字符串&#xff0c;要求把里面的图片替换成为超链接&#xff0c;并且要通过请求一个接口进行图片下载。 举例说明 就是下列这样的一个字符串&#xff1a;vaddssss[图片](image_p0_f0.png)dsatewafdsaa[图片](image_p1…