Java脚本化编程实践整理 ScriptEngineManager万字详解

news2024/9/24 9:18:10

文章目录

  • 认识
    • Java支持脚本语言的意义
    • Java对JavaScript的支持
    • Rhino/Nashorn概述
    • Nashorn的目的
  • 实践操作
    • HelloWorld
    • 执行脚本文件代码
    • 脚本语言使用Java的变量
    • 执行脚本方法/函数
    • 脚本语言使用Java的类对象
    • 脚本语言实现Java的接口
    • 脚本的多个作用域
    • 脚本语言使用Java的数据类型
    • 创建java对象实例
    • 访问静态方法和属性
  • JDK中测试脚本的工具
  • 安全分析
  • Nashorn与GraalVM的未来
  • 项目实践案例参考
    • 场景描述
    • 【设计思考】
  • 总结
  • 参考文档

认识

Java支持脚本语言的意义

JDK 6.0 增加了对脚本语言的支持,原理上是通过将脚本语言编译成字节码(Byte Code)实现的。这样,脚本语言也能享用Java平台的诸多优势,包括可移植性,安全等。另一方面,由于编译成字节码后再执行,因此比原来边解释边执行的效率要高出很多。在加入对脚本语言的支持后,Java语言本身也享有了以下的好处:
【1】许多脚本语言都有动态特性。例如,不需要在使用一个变量之前先声明它、并且可以用一个变量存放完全不同类型的对象、不需要进行强制类型转换(因为转换都是自动进行的)。现在Java语言也可以通过对脚本语言的支持而间接获得这种灵活性。
【2】通过引入脚本语言可以轻松实现 Java 应用程序的扩展性和自定义。我们可以把原来分散在Java应用程序中的业务规则提取出来,转而用JavaScript来实现。

Java对JavaScript的支持

JDK 6.0包含了一个基于Mozilla Rhino的脚本语言引擎,以支持JavaScript。请注意,这并不说明JDK 6.0只支持JavaScript,任何第三方都可以自己实现一个JSR-223兼容的脚本引擎,使得JDK 6.0支持其他的脚本语言。例如,如果想让JDK支持Python,那么可以自己按照 JSR 223 的规范实现一个 Python 的脚本引擎类,也就是自己动手实现javax.script.ScriptEngine和javax.script.ScriptEngineFactory两个接口。Scripting API 是用于在 Java 程序中书写脚本语言程序的 API, Scripting API 包含在javax.script包中。这个包中含有一个ScriptEngineManager类,它是使用Scripting API的入口。
JSR 223中规范了在Java虚拟机上运行的脚本语言与Java程序之间的交互方式。JSR 233是JavaSE6的一部分,在Java表中API中的包是javax.script。目前Java虚拟机支持比较多的脚本语言,比较流行的有JavaScript、Scala、JRuby、Jython和Groovy等。

Rhino/Nashorn概述

Rhino和Nashorn都是用Java实现的JavaScript引擎。它们自身都是普通的Java程序,运行在JVM上。Rhino是在JDK 6.0设计开发的脚本语言引擎,Nashorn引擎是在Java8设计被用来替代Rhino引擎的。
Nashorn是一个完全重写的实现,努力实现了与Java简便交互、高性能和对JavaScript ECMA规范的精确一致性。Nashorn是达到百分之百完全符合规范要求的JavaScript实现,并且在大多数装载上比Rhino至少快20倍。
Nashorn采用完全编译的方法,但是对运行时中的编译器进行了优化,这样JavaScript源代码就不会在程序执行开始之前编译。这意味着无须专门为Nashorn编写,而JavaScript代码仍然可以很轻易地部署到平台上。
在这里插入图片描述
当我在JDK11的环境下运行javax.script包下的类时,IDE提示我Nashorn引擎将会在未来的版本中被移除。但是在目前JDK运行是不会有问题的,而且即使引擎被移除也不会影响到javax.script包下API的使用。

Nashorn的目的

在Java和JVM生态系统中,Nashorn有多种用途。首先,它为JavaScript开发者提供了一个可用的环境,用于探索JVM的功能。其次,它让企业继续利用对Java技术的现有投资,采用JavaScript作为一门开发语言。最后,它为HotSpot使用的先进虚拟机技术提供了一个很好的工程样板。
JavaScript不断发展,应用范围越来越宽,以前只能在浏览器中使用,而现在则能在更通用的计算和服务器端使用。Nashorn在稳固的Java现有生态系统和一波有前途的新技术之间架起了一座桥梁。

实践操作

HelloWorld

        // 创建一个脚本执行引擎管理器
        ScriptEngineManager factory = new ScriptEngineManager();
        // 创建一个JavaScript引擎
        ScriptEngine engine = factory.getEngineByName("nashorn");
        // 执行JavaScript代码
        engine.eval("print('Hello, World')");

在这里插入图片描述

执行脚本文件代码

    /**
     * 根据指定的JS文件执行JavaScript代码
     */
    @Test
    public void test2() throws Exception {
        // 创建一个脚本执行引擎管理器
        ScriptEngineManager factory = new ScriptEngineManager();
        // 创建一个JavaScript引擎
        ScriptEngine engine = factory.getEngineByName("nashorn");
        // 根据指定的JS文件执行JavaScript代码
        engine.eval(new java.io.FileReader("src/main/resources/test2.js"));
    }

JS文件内容:
print(“执行JS脚本文件”)

脚本语言使用Java的变量

    /**
     * 脚本变量
     */
    @Test
    public void test3() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        File f = new File("src/main/resources/test.txt");
        // 将File对象作为变量公开给脚本
        engine.put("file", f);
        // 执行JAVA传入的对象方法以及脚本方法
        engine.eval("print(file.getAbsolutePath())");
    }

在这里插入图片描述

运行在脚本宿主机(Scripting Host)中的脚本语言,它的执行权限和能访问的设备范围是很有限的,往往要借助其他的手段(如ActiveX Control、Applet)才能访问磁盘文件,正是因为这个原因,在JavaScript语言中甚至没有定义文件对象类型。
上面示例中通过JAVA语言构建了一个File对象,然后将该File对象传递给了JS脚本引擎,然后在JS中就可以操作文件对象了。

执行脚本方法/函数

    /**
     * 执行脚本函数
     */
    @Test
    public void test4() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        // 定义一个JavaScript方法
        String script = "function hello(name) { print('Hello, ' + name); }";
        // 执行脚本
        engine.eval(script);
        // 由ScriptEngines实现的接口,其方法允许调用以前已执行的脚本中的过程。
        Invocable inv = (Invocable) engine;
        // 调用全局函数,并传入参数
        inv.invokeFunction("hello", "测试");
    }

脚本引擎本身并不负责调用在脚本中定义的方法,而是将其转换成实现 javax.script. Invocable 接口的 inv 对象,由 inv 对象利用invokeFunction()方法来调用脚本方法。
invokeFunction()接受不定数量的入参,但第一个入参必须是方法名,后面的入参是将要传递给脚本方法的参数,均为 java.lang.Object 类型。JavaScript 是一种弱类型定义的语言,由脚本引擎将 java.lang.Object 类型的参数转换为脚本语言能接受的值。

脚本语言使用Java的类对象

JavaScript不仅能使用Java为之定义的变量,而且能够完整地引入Java的类包。凭借这一点,我们可以发现:JavaScript可以实现Java所能实现的全部功能。
示例:在JS脚本中获取数据库连接并查询打印数据,为了方面这里直接使用一个hutool的数据库连接工具,该工具使用不在赘述。
创建一个js脚本文件,编写如下代码

var DB = Java.type("cn.hutool.db.Db")
print(DB.use().findAll("sys_user"))
    @Test
    public void test1() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        engine.eval(new java.io.FileReader("src/main/java/com/zy/core_java/script_jsr/js_file/demo1.js"));
    }

执行测试,在JS中操作JAVA类对象,可以看到可以在JS脚本中正常操作获取数据。

在这里插入图片描述

脚本语言实现Java的接口

    /**
     * 通过脚本实现Java接口
     */
    @Test
    public void test5() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        // JavaScript脚本代码
        String script = "function run() { print('run called'); }";
        // 执行脚本代码
        engine.eval(script);
        Invocable inv = (Invocable) engine;
        // 通过Invocable实现接口
        Runnable r = inv.getInterface(Runnable.class);
        // Java创建一个线程并运行脚本实现的代码
        Thread th = new Thread(r);
        th.start();
        th.join();
    }

这里使用javax.script.Invocable 接口的另一个方法getInterface()来获取JavaScript定义的Interface,并将其转换为实现特定的Java Interface的对象。
javax.script.Invocable接口的getInterface()方法接收两个入参:第1个入参是从JavaScript中获取的变量(也就是待转换成特定Java Interface的对象),第2个入参是转换目标Interface的类名,本例将把obj对象转换成实现java.lang.Runnable接口的对象。注意:这种转换不是任意的,如果待转换的对象不具备目标Interface的方法,将返回null。

脚本的多个作用域

    @Test
    public void test6() throws Exception {
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        // 添加一个变量
        engine.put("x", "hello");
        // 执行脚本,输出:hello
        engine.eval("print(x);");
        // 构建一个不同的脚本上下文
        ScriptContext newContext = new SimpleScriptContext();
        newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
        Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
        // 在新的执行引擎作用域中添加与上面相同名称的变量
        engineScope.put("x", "world");
        // 执行脚本,注意这里指定新的执行作用域上下文
        engine.eval("print(x);", newContext);
    }

脚本语言使用Java的数据类型

通过ScriptEngine 我们可以在JavaScript脚本中声明创建Java语言的数据类型。
创建一个测试js文件

var arrayListType = Java.type("java.util.ArrayList")
var intType = Java.type("int")
var stringArrayType = Java.type("java.lang.String[]")
var int2DArrayType = Java.type("int[][]")
    /**
     * 访问和使用JAVA类
     */
    @Test
    public void test7()throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        engine.eval(new java.io.FileReader("src/main/resources/test7.js"));
    }

在JavaScript脚本中声明创建Java语言的数据类型需要传入一个全限定名称路径。然后就可以基于这个类型创建实例对象。

如果是一个内部类话,需要按照如下的路径方式,以$符号间隔内部类

var ftype = Java.type(“java.awt.geom.Arc2D$Float”)

该类对应的全限定名称:java.awt.geom.Arc2D.Float

创建java对象实例

创建测试脚本文件test8.js,并写入如下代码

var ArrayListType = Java.type("java.util.ArrayList")
var arrayList = new ArrayListType
arrayList.add("a")
arrayList.add("b")
print(arrayList)
    /**
     * 访问和使用JAVA类
     */
    @Test
    public void test8()throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        engine.eval(new java.io.FileReader("src/main/resources/test8.js"));
    }

在这里插入图片描述

可以看到输出结果是一个数组,也就是说在js脚本里面正常使用了JAVA数据类型ArrayList

访问静态方法和属性

我们通过Java.type(“java.util.ArrayList”)的方式就可以获取到一个JAVA类,上面通过new的方式创建了实例对象。除此之外,对于一些类静态方法和属性,我们可以直接通过Java.type的方法值去操作。

创建一个测试类,提供一个静态方法和静态属性

package com.zy.scriptengine;

public class Test9 {

    public static final String name = "Alice";
    
    public static String hello() {
        return "hello " + name;
    }
}

创建一个测试脚本文件test9.js,并写如下代码

var Test9 = Java.type("com.zy.scriptengine.Test9")
print(Test9.name)
print(Test9.hello())
    /**
     * 访问和使用JAVA静态方法和属性
     */
    @Test
    public void test9()throws Exception{
        ScriptEngineManager manager = new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("nashorn");
        engine.eval(new java.io.FileReader("src/main/resources/test9.js"));
    }

在这里插入图片描述
可以看到正常方法对应JAVA类的静态方法和静态属性了。

JDK中测试脚本的工具

JDK 6.0中有一个命令行工具——jrunscript,可以在JDK 6.0安装目录的bin子目录下找到这个命令行工具。jrunscript是一个脚本语言的解释程序,它独立于脚本语言,但默认是用JavaScript,我们可以用jrunscript来测试自己写的脚本语言是否正确。
这对于我们开发测试脚本文件比较适用,可以在编写完脚本后通过该工具进行验证,因为并不是所有的脚本语言语法都能够完全被JAVA执行引擎所兼容。

测试程序如下所示:print(JSON.parse(‘{“name”:“张三”}’).name),可以看到JS中常用的JSON解析函数可以运行使用。
在这里插入图片描述
若想在Nashorn中执行名为my.js的JavaScript文件,使用jrunscript命令即可:jrunscript my.js
除了Nashorn,jrunscript还能使用其他脚本引擎。如果需要使用其他引擎,可以通过-l选项指定:jrunscript -l nashorn my.js

安全分析

【1】通过ScriptEngineManager加载恶意代码。ScriptEngineManager有两个构造函数,其中一个构造函数的参数是ClassLoader类型。恶意攻击者可以使用ScriptEngineManager在实例化时会通过URLClassLoader去指定的位置加载一个恶意类。URLClassLoader在将恶意类加载到本地后会直接将其实例化,从而触发写在恶意类的构造函数中的恶意代码。
【2】代码注入攻击,ScriptEngineManager可以动态的加载脚本文件,而脚本文件是可以被存放在代码中,外部文件中,数据库中,配置中心等等。一方面安全检查工具无法对这些动态加载的代码进行侦查,另一方面恶意攻击者如果修改了脚本文件那么系统运行就会有很大安全隐患。

Nashorn与GraalVM的未来

备注:本段内容摘抄自《Java技术手册(原书第7版)》
2018年春天,甲骨文首次发布了GraalVM(https://github.com/oracle/graal) ,它是甲骨文实验室的一个研究项目,可能会用于替换掉当前Java运行时环境(HotSpot)。这项研究工作可以看作是几个独立但相互关联的项目,它是为HotSpot打造的新JIT编译器,也是一个新的、支持多语言的虚拟机。我们将JIT编译器称为Graal,将新VM称为GraalVM。
Graal使用新的JVM编译器接口(JVMCI,以JEP 243的形式提供)来接入HotSpot,但也可以独立使用,它是GraalVM的主要部分。Graal技术已经出现并随同Java 11发布,但是它仍然被认为不能完全适用于大多数生产场景用例。
Graal的一些功能可以看作是JSR 223(Java平台的脚本编写)的替代品,但是Graal方法比以前的HotSpot中类似的技术更进一步、更深入。该特性依赖于GraalVM和Graal SDK,Graal SDK是GraalVM默认类路径的一部分,但是应该作为依赖项被显式地包含在项目中。下面是一个简单的例子,我们只是从Java调用一个JavaScript函数:
在这里插入图片描述
自从Java 6引入了编写脚本的API,多语言支持功能的基本形态就存在了。随着Nashorn的到来,以及其中基于动态调用的JavaScript实现,多语言功能在Java 8中有了显著的提升。
GraalVM技术真正与众不同的是,在这个生态系统中显式地包含了一个SDK以及支持工具,用于支持多语言,并使这些语言作为共同平等和配合互动的公民在底层VM上运行。在运行于GraalVM的诸多语言中,Java只是其中之一(尽管它很重要)。
这一步的关键是一个名为Truffle的组件和一个简单的、不加修饰的VM,即能够执行JVM字节码的底层VM。Truffle提供了一个运行时和库,用于为非Java语言创建解释器。一旦这些解释器运行,Graal编译器将介入并将解释器编译成快速的机器代码。为了开箱即用,GraalVM附带了JVM字节码、JavaScript和LLVM支持,随着时间的推移还将添加其他语言。GraalVM方法意味着,例如,JS运行时可以调用另一个运行时的对象的方法,并进行无缝的类型转换(至少对于简单的情况可以做到)。JVM工程师们已经讨论了很长一段时间(至少10年),在语义和类型系统非常不同的语言之间具有可替换性的能力,并且随着GraalVM的到来,它朝着主流迈出了非常重要的一步。
GraalVM对Nashorn的意义在于,甲骨文已经宣布他们打算放弃Nashorn,并最终将其从Java的发行版中删除。预期的替代品是GraalVM版本的JavaScript,但目前还没有时间表,甲骨文承诺在替代品完全准备好之前不会删除Nashorn。

项目实践案例参考

场景描述

【1】项目中有一个数据同步的任务,其中主要的流程是将系统A的几十个字段映射为系统B的对应字段。
【2】这其中字段的名称可能不一致,数据类型可能不一致,部分字段可能需要进行特殊转换。每个业务的情况也是不一样的。
【3】此外,有一个非常重要的事项是这个功能需要做成一个可适配的,即如果有新的业务进来,那么最好能够不修改代码就可以完成对应业务数据转换。
【4】添加一个新的业务场景,最好可以不进行重新部署就完成功能上线。

【设计思考】

针对这个需求使用ScriptEngine来实现更多是基于该特性灵活性的优点。实现过程大致如下:
【1】设计一个满足字段转换的数据结构,考虑了这个数据同步的场景,设计出大致数据结构如下

		{
			srcName: "nameA",
			targetName:"nameB",
			method: function(sycData){
			
			}
		}

其中srcName是源系统的字段名称,targetName是目标系统的字段名称,method是转换方法,可选的参数,该方法的作用是满足一些需要特定转换才能完成映射的字段。方法的传参可以根据实际场景进行选择调整。

【2】在上面的入门实例中演示是在JAVA代码中构建JS脚本字符串,或者将脚本存储到一个JS文件中。但是当下并没有采取与之相同的方式,为了满足脚本执行以及业务扩展的灵活性,我们将js脚本存储到数据表中。

【3】存储到数据表中之后,我们通过编写一个简单的表单页面,并集成了一个简单的JS格式化代码高亮插件,然后将数据表的JS脚本通过这个表单进行操作和展示。当需要调整业务时在后台表单页面修改JS脚本即可完成实时的更新。

【4】针对脚本的执行需要编写一个JAVA执行方法,在这个方法里面需要根据实际情况适当的传入一个JAVA对象,日志对象等。对于被Spring管理的Bean也可以传入到JS脚本中,对于ORM对象也可以进行传入,JS中可以正常执行数据的增删改查。

总结

【1】对于多变的计算公式,应用程序扩展/定制:你可以“外部化”应用程序的各个部分,例如配置脚本、业务逻辑/规则和金融应用程序的数学表达式。
【2】对于规则引擎类似的功能实现,对于其中的业务流程,动态脚本使用也可以参考使用这种脚本语言特性。
【3】下图是Kettle软件工具的截图,可以看到下面有很多的脚本处理方式,Kettle就是Java编写的,我自己就使用过很多次其中的动态脚本的功能,那么对于这类场景来说,我们就可以去使用ScriptEngineManager去帮助我们实现。
在这里插入图片描述
【4】对于上面的项目实践参考案例而言,在一些业务流程相似并且需要不停机动态切换业务场景下,我们可以尝试着使用类似的解决方案去实现。
【5】使用脚本化编程可以帮助我们实现更加灵活的解决方式,但是我们需要注意使用过程的安全策略的处理,避免遭受恶意攻击。
【6】动态脚本和静态语言在处理数据类型和变量是有所不同的,这些需要我们在使用中特别注意,避免出现运行异常。

参考文档

【1】Java平台上JavaScript引擎—Rhino/Nashorn概述
https://www.zhoulujun.cn/html/webfront/browser/webkit/2020_0718_8520.html
【2】JEP 372: Remove the Nashorn JavaScript Engine
https://openjdk.org/jeps/372
【3】Java语言的动态性支持(一)ScriptEngineManager
https://blog.csdn.net/tbdp6411/article/details/46817211
【4】《征服RIA——基于JavaScript的Web客户端开发》
【5】Java Scripting Programmer’s Guide
http://cr.openjdk.java.net/~sundar/8015969/webrev.00/raw_files/new/docs/JavaScriptingProgrammersGuide.html

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

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

相关文章

[附源码]计算机毕业设计基于Web的软考题库平台Springboot程序

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

CSS固定定位与粘性定位4大企业级案例

前面两篇文章为大家详细讲解了相对定位与绝对定位的应用场景和案例。如果想了解的可以在公众号里面查看去看。本小节我们学习下固定定位与粘性定位的应用场景和案例。 属性值 描述 relative 相对定位 相对于自身正常位置进行位置的调整 absolute 绝对定位 相对于其最近的定…

如何用实时数据分析辅助企业智能决策,这个高效的解决方案了解下?

随着产业互联网的发展,企业数字化能力的边界也在不断拓展,除了对海量数据的获取、处理及应用需求以外,更快地获取实时数据也开始成为大数据时代各行各业的共同目标。 在企业的业务经营中,实时数据是营销、运维、决策的重要支撑&am…

ChatGPT OpenAI 让学习更加高效工作中实现效率翻倍

ChatGPT是一款由OpenAI开发的聊天机器人,它具有出色的自然语言处理能力,能够与人类进行真实的对话。它的核心技术是GPT-3语言模型,能够自动学习语言特征,并进行语义理解、文本生成等任务。ChatGPT具有快速回答和丰富内容的特点&am…

Mac M1使用brew安装nvm

nvm作为node版本管理器,全称node version manager,可以管理安装的node和node-sass版本。在macOS系统上的安装步骤如下: *本机使用的是M1芯片,终端配置文件默认使用.zshrc 1. 安装homebrew /usr/bin/ruby -e "$(curl -fsSL h…

2022_SPIC_FANet

Feature aggregation network for RGBD saliency detection 1. 动机 如何将RGB和Depth充分挖掘和融合仍是一个关键问题。 第一个问题是如何从深度图中充分挖掘几何信息,从而可以可靠地反映场景的空间结构。 第二个问题是如何有效地融合外观信息和几何信息&…

koa项目

一.koa起步 1.项目初始化 执行 npm init -y ,生成 package.json npm init -y2.安装koa 执行命令 npm install koa3.编写基本app 创建 src/main.js //1.导入koa包 const Koa new require("Koa");//2。实例化app对象 const app new Koa();//3.编写中间件 app.…

基于C#+Mysql实现(WinForm)企业的设备管理系统【100010018】

企业的设备管理系统 1 引言 企业的设备管理在企业的生产制造和管理过程之中意义比较重大,明确企业的设备的产权和维护成本对于企业的成本控制和财务管理之中起到了重要的作用。随着市场竞争的加剧,现代企业所处的市场环境发生了深刻的变革,…

JDK19都出来了~是时候梳理清楚JDK的各个版本的特性了【JDK13特性讲解】

JDK各个版本特性讲解-JDK13特性 一、JAVA13概述 2019年9月17日,国际知名的OpenJDK开源社区发布了Java编程语言环境的最新版本OpenJDK13。 Features:总共有5个新的JEP(JDK Enhancement Proposals): http://openjdk.java.net/projects/jdk/13/ Features: …

java基于springboot的人事管理系统-计算机毕业设计

开发环境 开发语言:Java 框架:springboot JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Maven包:Maven 项目介绍 在这个计…

m基于GA遗传优化的三维工程施工设施布局算法matlab仿真,显示二维和三维布局优化效果

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 GA把问题的解表示成“染色体”,在算法中也即是以二进制编码的串。并且,在执行遗传算法之前,给出一群“染色体”,也即是假设解。然后,把…

Matplotlib学习笔记(第二章 2.13 Matplotlib中的图形(三))

图例(Legends) legend()函数,使用MATLAB兼容的图例,放置函数自动生成图形图例。 感谢查尔斯特沃迪对图例功能的投入。 Fig. 19: Legend 文本对象的Tex表示法(TeX-notation for text objects) 下面是Matplotlib内部的mathtext工程支持的许多Tex表达式…

基于C#+SQLServer 2005实现(WinForm)校园卡消费信息系统【100010013】

校园卡消费信息管理系统 一、前言 1.1 选题说明 校园卡消费信息系统是一个实用并且与我们的学校生活密切相关的管理信息系统;如果能够很好的研究、开发并加以利用,校园卡的相关业务会变得更加简单、学生能更便利地进行消费同时准确了解自己的消费情况…

信号包络提取

目录 一、信号包络提取的相关应用: 二、信号包络提取方法 1、希尔伯特变换-Hilbert Transform 1.1 公式原理 1.2 例子说明 2、平方能量包络提取 3、香农能量包络提取 三、3种方法的对比 一、信号包络提取的相关应用: 1)当某一个机械部…

多副本自动化发布——standalone下

一: supervisor 具体这玩意是干嘛的,我就不说了,大家自己看官网: http://www.supervisord.org/ 接下来快速部署一下。 1. pip pip是python的一个包管理器,类似于nuget,如果你的centos上没有安装,那么请执行下面命令。 1 yum -y install epel-release 2 yum -y inst…

经矩形窗截断的信号频谱泄露现象研究-附Matlab代码

⭕⭕ 目 录 ⭕⭕✳️ 一、频谱泄露现象✳️ 二、原因分析以及解决方法✳️ 三、Matlab程序获取与验证✳️ 一、频谱泄露现象 有一个余弦信号,信号频率30Hz,信号为x(t)cos(2π30t),采样频率fs128Hz,样本长度分别取N128和N100&…

代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II

代码随想录算法训练营第四天| 24. 两两交换链表中的节点 ,19.删除链表的倒数第N个节点 ,面试题 02.07. 链表相交 ,142.环形链表II 24. 两两交换链表中的节点 用虚拟头结点,这样会方便很多。 本题链表操作就比较复杂了&#xff…

MicroPython-On-ESP8266——8x8LED点阵模块(4)基于MAX7219滚动显示字符/图案

MicroPython-On-ESP8266——8x8LED点阵模块(4)基于MAX7219滚动显示字符/图案 1. 继续折腾点阵模块 咱们已经学习了点阵屏基础电路与驱动原理,并用74HC595和MAX7219都成功地驱动点阵屏显示了爱心图案。 MicroPython-On-ESP8266——8x8LED点…

python-(6-5-2)爬虫---处理cookie来获取书架数据

文章目录一 需求二 流程分析1 登录2 获取书架的数据三 完整代码一 需求 通过处理cookie来访问自己的书架资源。 二 流程分析 带着cookie,去请求url,得到书架内容。 要将上述的两个操作连续起来,可以使用session。 session是一连串的请求…

自动驾驶之多任务方法调研

1. YOLOP github C TRT TX2 我们提出了一种高效的多任务网络,该网络可以联合处理自动驾驶中的目标检测(车,没有红绿灯)、可驾驶区域分割和车道检测三个关键任务 速度: TX2上23FPS;TAITAN XP上41FPS. 自测结果: 灵活性: 支持…