NAPI 类对象导出及其生命周期管理(下)

4. 样例工程源码剖析

  • 工程的模板是Native C++,模型是Stage
  • 源码剖析主要围绕以下几个文件

4.1. NAPI导出对象和生命周期管理具体实现

4.1.1. 定义NapiTest类及方法
  • Napi.h文件内容如下:
#ifndef __NAPI_TEST_H__
#define __NAPI_TEST_H__#include "napi/native_api.h"
#include <js_native_api_types.h>#include <iostream>#define NAPI_CLASS_NAME "NapiTestClass"class NapiTest {
public:
NapiTest() : mEnv(nullptr), mRef(nullptr) {
}NapiTest(napi_env env) : mEnv(env), mRef(nullptr){
}
~NapiTest();// 创建NapiTest类的实体,并将实体返回到应用端,该方法为js创建一个类实体,因此需要将该接口对外导出
static napi_value Create(napi_env env, napi_callback_info info);// 初始化js类并设置对应属性并将其导出   
static napi_value Init(napi_env env, napi_value exports);         private:// 设置数据,此方法给到js直接调用,因此需要将该接口对外导出static napi_value SetMsg(napi_env env, napi_callback_info info);// 获取数据,此方法给到js直接调用,因此需要将该接口对外导出    static napi_value GetMsg(napi_env env, napi_callback_info info);// 定义js结构体时实际的构建函数static napi_value Constructor(napi_env env, napi_callback_info info);     // 释放资源的函数(类似类的析构函数)    static void Destructor(napi_env env, void *nativeObject, void *finalize); // 生命周期变量    static napi_ref sConstructor_;  // 设置和获取数据的变量    static std::string _msg;        // 记录环境变量    napi_env mEnv = nullptr;        // 记录生命周期变量    napi_ref mRef = nullptr;        };#endif  /* __NAPI_TEST_H__ */
4.1.1.1 napi_value
  • Node.js Node-API的值用napi_value类型表示。
    OpenHarmony NAPI将ECMAScript标准中定义的Boolean、Null、Undefined、Number、BigInt、String、Symbol和Object八种数据类型,以及函数对应的Function类型,统一封装成napi_value类型,下文中表述为JS类型,用于接收ArkUI应用传递过来的数据及返回数据给ArkUI应用。
  • 这是一个不透明的指针,用于表示JavaScript值。
4.1.1.2 napi_ref
  • 这是用来引用napi_value的抽象。这允许用户管理JavaScript值的生命周期,包括显式地定义它们的最小生命周期。
4.1.1.3 napi_env
  • napi_env用于表示上下文,底层的Node-API实现可以使用该上下文持久保持VM-specific的状态。
4.1.2 将NapiTest类定义为js类
4.1.2.1在定义js类之前,需要先设置js类对外导出的方法
    // 在定义js类之前,需要先设置类对外导出的方法napi_property_descriptor desc[] = {{ "getMsg", nullptr, NapiTest::GetMsg, nullptr, nullptr, nullptr, napi_default, nullptr },{ "setMsg", nullptr, NapiTest::SetMsg, nullptr, nullptr, nullptr, napi_default, nullptr },{ "create", nullptr, NapiTest::Create, nullptr, nullptr, nullptr, napi_default, nullptr }};
4.1.2.1.1 napi_property_descriptor

Node.js Node-API有一组API来获取和设置JavaScript对象的属性。在JavaScript中,属性被表示为一个键和一个值的元组。基本上,Node-API中的所有属性键都可以用以下形式中的任一一种表示:

  • Named:一个简单的UTF-8编码的字符串
  • Integer-Indexed:索引值,由uint32_t表示
  • JavaScript value:在Node-API中通过napi_value表示。它可以是一个napi_value,表示字符串、数字或符号。
typedef struct {// utf8name和name其中一个必须是NULLconst char* utf8name;napi_value name;napi_callback method;napi_callback getter;napi_callback setter;napi_value value;napi_property_attributes attributes;void* data;
} napi_property_descriptor;

参数解析:

  • utf8name:在定义js类之前设置的js类对外导出的方法名字,编码为UTF8。必须为该属性提供utf8name或name中的一个。(utf8name和name其中一个必须是NULL)
  • name:可选的napi_value,指向一个JavaScript字符串或符号,用作属性的键。必须为该属性提供utf8name或name中的一个。
  • method:将属性描述符对象的value属性设置为method表示的JavaScript函数。如果传入这个参数,将value、getter和setter设置为NULL(因为这些成员不会被使用)。
  • attributes:与特定属性相关联的属性。
  • data:调用函数时传递给method、getter和setter的callback data。
4.1.2.2 定义与C++类相对应的JavaScript类
    napi_value constructor = nullptr;// 定义与C++类相对应的JavaScript类if (napi_define_class(env, NAPI_CLASS_NAME, NAPI_AUTO_LENGTH, Constructor, nullptr, sizeof(desc) / sizeof(desc[0]),desc, &constructor) != napi_ok) {// "!="用来检查两个操作数的值是否相等,如果不相等则条件为真return nullptr;}
4.1.2.2.1 napi_define_class

napi_define_class函数说明:

napi_status napi_define_class(napi_env env,const char* utf8name,size_t length,napi_callback constructor,void* data,size_t property_count,const napi_property_descriptor* properties,napi_value* result);

功能:定义与C ++ 类相对应的JavaScript类。
参数说明:

  • [in] env: 调用api的环境
  • [in] utf8name: C ++ 类的名称
  • [in] length: C ++ 类的名称的长度,默认自动长度使用NAPI_AUTO_LENGTH
  • [in] constructor: 处理C ++ 类实例构造的回调函数 (因为Constructor函数被napi_define_class调用了)。在导出C ++ 类对象时,这个函数必须是带有napi_callback签名(Constructor函数有napi_callback签名是指要满足typedef napi_value (*napi_callback)(napi_env, napi_callback_info);的形式)的静态成员。不能使用c ++ 的类构造函数。
  • [in] data: 作为回调信息的数据属性传递给构造函数回调的可选数据
  • [in] property_count: 属性数组中参数的个数
  • [in] properties: 属性数组,具体看代码中napi_property_descriptor部分
  • [out] result: 通过类构造函数绑定类实例的napi_value对象
    返回:如果API调用成功返回napi_ok。

JS构造函数
如果一个js函数被使用new操作符来调用了,那么这个函数就称之为js构造函数

C++类回调函数
我们调用别人的API叫call,调用的第三方API调用我们的函数叫回调(callback)

4.1.2.3 实现js类的构造函数

当ArkTS应用在js端通过new方法获取类对象的时候,此时会调用 napi_define_class 中设置的 constructor 回调函数,该函数实现方法如下:

napi_value NapiTest::Constructor(napi_env env, napi_callback_info info)
{napi_value undefineVar = nullptr, thisVar = nullptr;napi_get_undefined(env, &undefineVar);// 获取传入的参数对象,对象不为空,根据该参数创建实例并并绑定到该对象if (napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr) == napi_ok && thisVar != nullptr) {// 创建NapiTest 实例NapiTest *reference = new NapiTest(env);// 绑定实例到对象并获取对象的生命周期if (napi_wrap(env, thisVar, reinterpret_cast<void *>(reference), NapiTest::Destructor, nullptr, &(reference->mRef)) == napi_ok) {return thisVar;}return thisVar;}return undefineVar;
}void NapiTest::Destructor(napi_env env, void *nativeObject, void *finalize)
{// 释放资源NapiTest *test = reinterpret_cast<NapiTest*>(nativeObject);test->~NapiTest();
}
  • NapiTest::Destructo方法是用来释放创建的对象:
void NapiTest::Destructor(napi_env env, void *nativeObject, void *finalize)
{// 类析构函数,释放资源NapiTest *test = reinterpret_cast<NapiTest*>(nativeObject);test->~NapiTest();
}
4.1.2.3.1 napi_wrap
napi_status napi_wrap(napi_env env,napi_value js_object,void* native_object,napi_finalize finalize_cb,void* finalize_hint,napi_ref* result);

功能:将C++类实例绑定到js对象,并关联对应的生命周期
参数说明:

  • [in] env: 调用api的环境
  • [in] js_object: 绑定native_object的js对象
  • [in] native_object: C++类实例对象
  • [in] finalize_cb: 释放实例对象的回调函数
  • [in] finalize_hint: 传递给回调函数的数据
  • [out] result: 绑定js对象的引用

返回:调用成功返回0,失败返回其他

4.1.2.3.2 napi_get_cb_info

NAPI提供了napi_get_cb_info()方法可从napi_callback_info中获取参数列表、this及其他数据。这个方法在constructor回调函数中使用,从给定的回调信息中检索有关调用的详细信息,如参数和This指针。

napi_status napi_get_cb_info(napi_env env,              napi_callback_info cbinfo, size_t* argc,                          napi_value* argv,     napi_value* this_arg, void** data)     

参数说明:

  • [in] env: 传入接口调用者的环境,包含js引擎等,由框架提供,默认情况下直接传入即可
  • [in] cbinfo: napi_callback_info对象,上下文的信息
  • [in-out] argc: argv数组的长度。若napi_callback_info中实际包含的参数的个数大于请求的数量argc,将只复制argc的值所指定数量的参数只argv中。若实际的参数个数小于请求的数量,将复制全部的参数,数组多余的空间用空值填充,并将参数实际长度写入argc。
  • [out] argv: 用于接收参数列表
  • [out] this_arg: 用于接收this对象
  • [out] data: NAPI的上下文数据 返回值:返回napi_ok表示转换成功,其他值失败。下面的返回napi_status方法一样。
4.1.3 导出js类
    // 创建生命周期,初始引用计数设为1if (napi_create_reference(env, constructor, 1, &sConstructor_) != napi_ok) {return nullptr;}// 设置NapiTest对象相关属性并绑定到导出变量exportsif (napi_set_named_property(env, exports, NAPI_CLASS_NAME, constructor) != napi_ok) {return nullptr;}
4.1.3.1 在设置js类导出前,需要先创建生命周期
if (napi_create_reference(env, constructor , 1, &sConstructor_) != napi_ok) {return nullptr;
}
  • constructor 定义js类时返回的代表类的构造函数的数据
  • sConstructor_ 生命周期变量
4.1.3.1.1 napi_create_reference

napi_create_reference为对象创建一个reference,以延长其生命周期。调用者需要自己管理reference生命周期。

napi_create_reference函数说明:

NAPI_EXTERN napi_status napi_create_reference(napi_env env,napi_value value,uint32_t initial_refcount,napi_ref* result);

功能:通过引用对象创建新的生命周期引用对象

  • [in] env: 调用 API 的环境
  • [in] value: napi_value表示我们要引用的对象
  • [in] initial_refcount: 生命周期变量的初始引用计数
  • [out] result: 新建的生命周期引用对象
    返回 napi_ok 这个API就是成功的.
4.1.3.2 将生命周期变量作为导出对象的传入属性,并将js类导出到exports中
//  设置constructor对象相关属性并绑定到导出变量exports
if (napi_set_named_property(env, exports, NAPI_CLASS_NAME, constructor) !=  napi_ok) {return nullptr;
}
4.1.3.2.1 napi_set_named_property

为给定对象的属性设置一个名称。

napi_status napi_set_named_property(napi_env env,napi_value object,const char* utf8Name,napi_value value);
  • [in] env: 调用API的环境
  • [in] object: NapiTest对象相关属性要绑定的属性值
  • [in] utf8Name: js类的名称
  • [in] value: 要引用的对象
    返回 napi_ok 则这个API是成功的
4.1.3.3 设置导出对象的属性

hello.cpp中

    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
4.1.3.3.1 napi_define_properties
napi_status napi_define_properties(napi_env env,napi_value object,size_t property_count,const napi_property_descriptor* properties);

作用:批量的向给定Object中定义属性

  • [in] env: 调用api的环境
  • [in] object: js对象相关属性的导出变量
  • [in] property_count: 属性数组中的元素数
  • [in] properties: 属性数组
4.1.4 创建类的实例对象
  • ArkTS应用除了调用new方法获取类的实例外,我们也可以提供一些方法让ArkTS应用获取对应的类的实例,如在我们的NapiTest类中,定义了一个Create方法,该方法实现了NapiTest类实例的获取。具体实现如下:
napi_value NapiTest::Create(napi_env env, napi_callback_info info) {napi_status status;napi_value constructor = nullptr, result = nullptr;// 获取生命周期变量status = napi_get_reference_value(env, sConstructor_, &constructor);// 创建生命周期内的实例对象并将其返回status = napi_new_instance(env, constructor, 0, nullptr, &result);auto napiTest = new NapiTest();// 绑定实例类创建NapiTest到导出的对象resultif (napi_wrap(env, result, reinterpret_cast<void *>(napiTest), Destructor,nullptr, &(napiTest->mRef)) == napi_ok) {return result;}return nullptr;
}
  • 在napi接口的注册中将该方法以接口的方式导出,应用层就可以直接调用该接口并获取到该类的实例对。
    特别说明:如果单独实现了一个类实例获取的方法,那么js的类构造函数可以不实现(也就是定义js结构体时实际的构建函数Constructor及释放资源的函数Destructor的代码够可以不写)
4.1.4.1 napi_get_reference_value

函数说明:

NAPI_EXTERN napi_status napi_get_reference_value(napi_env env,napi_ref ref,napi_value* result);
  • 作用:获取与reference相关联的js对象
  • [in] env: 调用API的环境
  • [in] ref: 生命周期管理的变量
  • [out] result: 对象引用的reference.
4.1.4.2 napi_new_instance
napi_status napi_new_instance(napi_env env,napi_value cons,size_t argc,napi_value* argv,napi_value* result)
  • 作用:通过给定的构造函数,构建一个对象
  • [in] env: 调用API的环境
  • [in] cons: napi_value表示要作为构造函数调用的 JavaScript 函数
  • [in] argc: argv 数组中的元素计数
  • [in] argv: JavaScript 值数组,表示构造函数的参数napi_value。
  • [out] result: napi_value表示返回的 JavaScript 对象

4.2 index.d.ts声明文件编写

使用NAPI框架代码生成工具,可以根据.h生成.d.ts

export const create : () => NapiTest;
export class  NapiTest {setMsg(msg: string): void;getMsg(): string;
}

也可以写成

export class  NapiTest {create();setMsg(msg: string): void;getMsg(): string;
}

4.3 CMakeLists.txt文件

# the minimum version of CMake.
cmake_minimum_required(VERSION 3.4.1)
project(ObjectWrapTest)set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})# 头文件路径
include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include)
# 动态库源文件
add_library(entry SHARED hello.cpp NapiTest.cpp)
# 依赖libace_napi.z.so动态库
target_link_libraries(entry PUBLIC libace_napi.z.so )

4.4 index.ets文件

// 让IDE不检查文件语法
// @ts-nocheck 
import testNapi from "libentry.so";@Entry
@Componentstruct Index {@State message: string = '导出对象'@State nativePointer:number = 0// 创建对象tttt = testNapi.create();build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {console.info("[NapiTest] Test NAPI 2 + 3 = " + testNapi.add(2, 3));try{if (this.nativePointer == 0) {// log打印,在程序中添加 logconsole.info("[NapiTest] Test NAPI add(2, 3) 1");this.nativePointer = testNapi.add(2, 3)console.info("[NapiTest] Test NAPI add(2, 3) 2");this.tt.setMsg("2+3")console.info("[NapiTest] Test NAPI add(2, 3) 3");} else {console.info("[NapiTest] Test NAPI add(0, 0) 1");this.nativePointer = testNapi.add(0, 0)console.info("[NapiTest] Test NAPI add(0, 0) 2");this.tt.setMsg("4+5")console.info("[NapiTest] Test NAPI add(0, 0) 3");}} catch(e) {console.info("[NapiTest]Test NAPI error" + JSON.stringify(e));}console.info("[NapiTest]Test NAPI " + this.tt.getMsg() + " = " + this.nativePointer);})}.width('100%')}.height('100%')}}

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

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

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

相关文章

Android Studio开发学习(六)———TableLayout(表格布局)、FrameLayout(帧布局)

目录 前言 一、Tablelayout &#xff08;一&#xff09;Tablelayout的相关简介 &#xff08;二&#xff09;TableLayout使用方法 1. 当TableLayout下面写控件、则控件占据一行的大小。(自适应一行&#xff0c;不留空白) 2.多个组件占据一行&#xff0c;则配合TableRow实现…

VulnHub靶机-easy_cloudantivirus 打靶

easy_cloudantivirus 靶机 目录 easy_cloudantivirus 靶机一、导入虚拟机配置二、攻击方式主机发现端口扫描web渗透-SQL注入命令注入反弹shellssh爆破提权 一、导入虚拟机配置 靶机地址&#xff1a; https://www.vulnhub.com/entry/boredhackerblog-cloud-av,453/下载完成&am…

计算机网络-TCP断开连接阶段错误应对机制

连接断开阶段 四次挥手机制&#xff1a;TCP连接的断开需要四次挥手&#xff0c;这是因为双方都需要独立地关闭数据传输。第二次和第三次挥手不能合并&#xff0c;因为在回复第二次挥手的时候&#xff0c;可能还有数据没有接收完成&#xff0c;所以需要先回复ACK报文&#xff0c…

KNN分类算法的MATLAB实现以及可视化

一、KNN简介 KNN算法&#xff0c;即K-Nearest Neighbors&#xff0c;是一种常用的监督学习算法&#xff0c;可以用于分类问题&#xff0c;并且在实际应用中取得了广泛的成功。 二、KNN算法的基本原理 对于给定的测试样本&#xff0c;KNN算法首先计算它与训练集中所有样本的距…

编译器领域一些特别好的文章

xz​​​​​​​s​​​​​​​cv_note/cv算法工程师成长路线.md at master HarleysZhang/cv_note GitHub记录cv算法工程师的成长之路&#xff0c;分享计算机视觉和模型压缩部署技术栈笔记。https://harleyszhang.github.io/cv_note/ - cv_note/cv算法工程师成长路线.md at…

kail渗透工具之nmap的使用方法

准备工作&#xff1a;开启两台虚拟机和一台Windows主机 kail Linux攻击机&#xff1a;192.168.80.131 red hat靶机&#xff1a;192.168.80.129 Windows主机&#xff1a;192.168.252.42 1、nmap扫描工具的简介 nmap是用来探测计算机网络上的主机和服务的一种安全扫描器。为了绘…

【教资】总结经验篇

4月.12日概述 今天是2024年上半学期中小学出成绩的一天&#xff0c;查到成绩的那一刻是灰常让人激动的&#xff0c;很开心&#xff0c;特此记下此时的真实感受&#xff0c;我也没有去问别人怎么样&#xff0c;特此针对自己以记之&#xff0c;加上最近有点摆烂&#xff0c;所以…

Excel---一个工作簿中的多个sheet合并成一个PDF

0 Preface/Foreword 1 操作方法 1.1 方法一 文件》 导出 》创建PDF/XPS 》 选项 》发布内容 》“整个工作簿” 1.2 方法二 文件》 打印》 打印机选项中&#xff0c;选择一种PDF阅读器 》设置选项中&#xff0c;选择打印整个工作簿。

【数据结构与算法】之8道顺序表与链表典型编程题心决!

个人主页&#xff1a;秋风起&#xff0c;再归来~ 数据结构与算法 个人格言&#xff1a;悟已往之不谏&#xff0c;知来者犹可追 克心守己&#xff0c;律己则安&#xff01; 目录 1、顺序表 1.1 合并两个有序数组 1.2 原地移除数组中所有的元素va…

工程施工业务中-几分钟搭建一个设计图纸和现状倾斜叠加的微信可查看三维场景

0序 一个施工单位的朋友提出&#xff1a; 很多项目前期还并没有制作完善的【施工策划方案】&#xff0c;刚做了现场的无人机航测&#xff0c;这时候就需要频繁的相互沟通&#xff0c;也很难每次都带着电脑去交流、汇报。 尤其是领导经常比较忙&#xff0c;如果能提前让领导看一…

【三十六】【算法分析与设计】综合练习(3),39. 组合总和,784. 字母大小写全排列,526. 优美的排列

目录 39. 组合总和 对每一个位置进行枚举 枚举每一个数出现的次数 784. 字母大小写全排列 526. 优美的排列 结尾 39. 组合总和 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不…

【每日刷题】Day11

【每日刷题】Day11 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; 目录 1. 860. 柠檬水找零 - 力扣&#xff08;LeetCode&#xff09; 2. 976. 三角形的最大周长 - 力扣&#xff08;LeetCode&#xff09; 3.…

CMD命令窗口提示文字乱码

我下面说的是日文版系统&#xff0c;中文版会有差异。 一般情况下是 Shiftjis 通常我是用sakura editor来写bat&#xff0c;但是运行后会在cmd窗口出现乱码 test.bat set HENSU这是一个变数 echo %HENSU% pause 执行后出现乱码 原因是不做设置时&#xff0c;command prom…

Switch-case

Java switch case 语句 switch case 语句判断一个变量与一系列值中某个值是否相等&#xff0c;每个值称为一个分支。 语法 switch case 语句语法格式如下&#xff1a; switch(expression){case value ://语句break; //可选case value ://语句break; //可选//你可以有任意数量…

卫星影像联合无人机实现农业保险全生命周期监管监测

随着科技的进步&#xff0c;农业保险监管系统的发展日新月异。特别是近年来&#xff0c;随着卫星技术与无人机技术的结合&#xff0c;为农业保险监管系统带来了前所未有的革新。本文将深入探讨如何利用卫星与无人机方案构建高效的农业保险监管系统&#xff0c;并结合实例进行说…

python之堆的实现

堆本质是一个完全二叉树&#xff0c;分为大根堆和小根堆&#xff0c;大根堆每个结点的值都大于它的孩子的值&#xff0c;小根堆相反&#xff0c;每个结点的值都小于它的孩子的值 heapq是python的标准库&#xff0c;用于维护堆&#xff0c;非常方便 heapq库常用的几个函数 he…

快速实现一个Hibernate的例子

写第一个简单的Hibernate程序&#xff1a; 具体的开始第一个Hibernate程序之前: 找到jar包, hibernate 的核心包, mysql数据库的连接驱动包, junit测试包 ①创建Hibernate配置文件 ②创建持久化类 也是和数据库中数据表一一对应这个类 ③创建对象-关系映射文件 ④通过hibern…

Day17_学点JavaEE_转发、重定向、Get、POST、乱码问题总结

1 转发 转发&#xff1a;一般查询了数据之后&#xff0c;转发到一个jsp页面进行展示 req.setAttribute("list", list); req.getRequestDispatcher("student_list.jsp").forward(req, resp);2 重定向 重定向&#xff1a;一般添加、删除、修改之后重定向到…

Pandas部分应掌握的重要知识点

目录 Pandas部分应掌握的重要知识点一、DataFrame数据框的创建1、直接基于二维数据创建&#xff08;同时使用index和columns参数&#xff09;2、基于excel文件中的数据来创建 二、查看数据框中的数据和联机帮助信息1、查看特殊行的数据2、查看联机帮助的两种常见方法&#xff0…

Python制作下载图片的脚本

如果你感觉有收获&#xff0c;欢迎给我微信扫打赏码 ———— 以激励我输出更多优质内容 需求: 今天遇到一个需求,需要下载一个网站上连续的图片素材,一开始一个一个下载太麻烦,于是制作了一个python脚本快速下载 操作: import os #【os模块常用功能】文件的目录、路径操作…