【鸿蒙应用ArkTS开发系列】- 云开发入门实战二 实现省市地区联动地址选择器组件(上)

目录

概述

云数据库开发

一、创建云数据库的对象类型。

二、预置数据(为对象类型添加数据条目)。

三、部署云数据库

云函数实现业务逻辑

一、创建云函数

二、云函数目录讲解

三、创建resources目录

四、获取云端凭据

五、导出之前创建的元数据库对象信息

六、为实现操作数据库创建一个类CloudDBZoneProvinceDao

七、在云函数入口文件中进行地区数据库的查询操作。

八、调试云函数

九、部署云函数

        实现效果:

概述

        通过本次课程,我们将学习怎么使用云端一体化开发模板来创建云开发工程,以及如何使用云工程进行云数据库创建、云函数创建和调用。
那下面我们直接进入本次课程的学习。

使用云端一体化开发模板创建项目工程
这块内容,在上一篇文章《【鸿蒙应用ArkTS开发系列】- 云开发入门简介》中已经进行了讲解,这块这里就不在过多赘述,没有看过的同学可以点击这里: 链接 查阅

创建完毕,整体的工程目录结构如下:

接下来,我们展开CloudProgram 这个项目,开始进行云数据开发


云数据库开发

本次Demo将创建三个对象类型来维护查询地理位置信息,这三个对象类型分别是

  • provinces  省份表
  • cities 城市表
  • districts 区/县表

provinces的信息和预置数据如下表:

cities 的信息和预置数据如下表:

districts 的信息和预置数据如下表:

首先我们先创建云数据库的对象类型。

这里由于篇幅原因,我们这里以provinces 为例,来讲解数据表的创建以及对应预置数据的实现,其他两个表的操作是一样的,这里就不多提。

一、创建云数据库的对象类型。

1、右击“CloudProgram -> clouddb -> objecttype”目录,选择“New > Cloud DB Object Type”,命名为“provinces”,生成一个provinces.json文件。

2、打开provinces.json文件,配置字段、索引、以及角色与权限。

参数

说明

fieldName

字段名称。

字段的名称长度必须大于等于1个字符,小于等于30个字符,只能包含以下3种类型,并且至少包含“字母”类型:

  • 字母(A-Z或a-z)
  • 数字(0-9)
  • 特殊字符:_

说明

  • 字段名称必须以字母开头,以字母或者数字结尾。
  • 字段名称中不区分字母的大小写。
  • 每个对象类型,仅支持设置一种自增类型字段:IntAutoIncrement或LongAutoIncrement。
  • 修改对象类型时,不支持新增数据类型为IntAutoIncrement或LongAutoIncrement的字段,支持新增其它数据类型的字段。
  • 修改对象类型时,支持删除字段。
  • 字段名称不允许使用系统保留字段名称: naturalbase_version、naturalbase_deleted、naturalbase_operationtype、naturalbase_creator、naturalbase_accesstime、naturalbase_operationtime、naturalbase_syncstatus、naturalbase_changedfieldsbitmap、naturalbase_lastmodifier、cmin、cmax、xmin、xmax、ctid、oid、tableoid、xc_node_id、tablebucketid和rowid。

fieldType

字段的数据类型。

当前支持的数据类型:String、Boolean、Byte、Short、Integer、Long、Float、Double、ByteArray、Text、Date、IntAutoIncrement和LongAutoIncrement。

belongPrimaryKey

设置该字段是否为对象类型的主键

  • 至少设置一个字段为主键。
  • 支持设置复合主键,由多个字段组合成为主键,一个复合主键包含的字段小于等于5个,复合主键字段顺序与字段的顺序一致。
  • 数据类型为ByteArray、Text、Date、Double、Float和Boolean的字段不支持设置为主键。
  • 主键的值不允许更改。

notNull

设置字段值是否为非空

  • 数据类型为ByteArray和Date的字段不支持设置为非空。
  • 数据类型为IntAutoIncrement和LongAutoIncrement的字段默认为非空,且不允许更改。
  • 主键默认非空,且不允许更改。
  • 设置为非空的字段不支持加密。

isNeedEncrypt

设置字段是否需要加密。

开启全程加密数据管理功能。选择加密后,该字段对应的数据会加密存储在存储区中。

  • 主键字段不支持加密。
  • 加密的字段不支持设置为非空。
  • 一个对象类型中包含的加密字段小于等于5个。
  • 字段设置为加密后,不支持导出该字段的数据值。
  • 数据类型为ByteArray、Text、IntAutoIncrement和LongAutoIncrement的字段不支持加密。
  • 对象类型创建成功后,不支持修改加密属性。

【fields】provinces 配置三个字段,自增主键“id”和 省份编码 code 、省份名称label。

【indexes】配置索引信息,本Demo不设置。

【permissions】本Demo 针对不同用户配置不同的权限,配置如下:

role(用户)描述rights(权限)

World

所有用户,包含认证和非认证用户。默认且最多仅可以拥有Read权限。

只开放读取权限

  • Read

Authenticated

经过AppGallery Connect登录认证的用户,包含隐式登录的匿名用户。

开放读取跟插入更新权限

  • Read
  • Upsert

Creator

经过认证的数据创建用户,每条记录都有其对应的数据创建人。

开放读取、插入更新、删除权限

  • Read
  • Upsert
  • Delete 

Administrator

应用开发者。

开放读取、插入更新、删除权限

  • Read
  • Upsert
  • Delete

注:上面的权限只是针对Demo演示,具体配置开发者可以自行配置。

下面是provinces.json文件完整数据:

{
  "fields": [
    {
      "belongPrimaryKey": true,
      "fieldName": "id",
      "fieldType": "IntAutoIncrement",
      "isNeedEncrypt": false,
      "notNull": true
    },
    {
      "belongPrimaryKey": false,
      "fieldName": "code",
      "fieldType": "Text",
      "isNeedEncrypt": false,
      "notNull": false
    },
    {
      "belongPrimaryKey": false,
      "fieldName": "label",
      "fieldType": "Text",
      "isNeedEncrypt": false,
      "notNull": false
    }
  ],
  "indexes": [

  ],
  "objectTypeName": "provinces",
  "permissions": [
    {
      "rights": [
        "Read"
      ],
      "role": "World"
    },
    {
      "rights": [
        "Read",
        "Upsert"
      ],
      "role": "Authenticated"
    },
    {
      "rights": [
        "Read",
        "Upsert",
        "Delete"
      ],
      "role": "Creator"
    },
    {
      "rights": [
        "Read",
        "Upsert",
        "Delete"
      ],
      "role": "Administrator"
    }
  ]
}

二、预置数据(为对象类型添加数据条目)。

1、右击“CloudProgram -> clouddb -> dataentry”目录,选择“New > Cloud DB Data Entry”。

2、“Object Type”选择之前创建的对象类型“provinces”,填写数据条目名称后,点击“OK”。

3、在dataentry文件夹下生成了以数据条目名称为名的json文件:provinces.json

4、打开provinces.json文件,预置数据。

  • cloudDBZoneName:数据条目所在存储区。

  • objectTypeName:数据条目所在对象类型。

  • objects:每个object即为一条数据。

{
  "cloudDBZoneName": "cloudDBOfArea",
  "objectTypeName": "provinces",
  "objects": [
    {
      "id": 1,
      "code": "110000",
      "label": "北京市"
    },
    {
      "id": 2,
      "code": "120000",
      "label": "天津市"
    },
    {
      "id": 3,
      "code": "130000",
      "label": "河北省"
    },
    {
      "id": 4,
      "code": "140000",
      "label": "山西省"
    },
    {
      "id": 5,
      "code": "150000",
      "label": "内蒙古自治区"
    },
    {
      "id": 6,
      "code": "210000",
      "label": "辽宁省"
    },
    {
      "id": 7,
      "code": "220000",
      "label": "吉林省"
    },
    {
      "id": 8,
      "code": "230000",
      "label": "黑龙江省"
    },
    {
      "id": 9,
      "code": "310000",
      "label": "上海市"
    },
    {
      "id": 10,
      "code": "320000",
      "label": "江苏省"
    },
    {
      "id": 11,
      "code": "330000",
      "label": "浙江省"
    },
    {
      "id": 12,
      "code": "340000",
      "label": "安徽省"
    },
    {
      "id": 13,
      "code": "350000",
      "label": "福建省"
    },
    {
      "id": 14,
      "code": "360000",
      "label": "江西省"
    },
    {
      "id": 15,
      "code": "370000",
      "label": "山东省"
    },
    {
      "id": 16,
      "code": "410000",
      "label": "河南省"
    },
    {
      "id": 17,
      "code": "420000",
      "label": "湖北省"
    },
    {
      "id": 18,
      "code": "430000",
      "label": "湖南省"
    },
    {
      "id": 19,
      "code": "440000",
      "label": "广东省"
    },
    {
      "id": 20,
      "code": "450000",
      "label": "广西壮族自治区"
    },
    {
      "id": 21,
      "code": "460000",
      "label": "海南省"
    },
    {
      "id": 22,
      "code": "500000",
      "label": "重庆市"
    },
    {
      "id": 23,
      "code": "510000",
      "label": "四川省"
    },
    {
      "id": 24,
      "code": "520000",
      "label": "贵州省"
    },
    {
      "id": 25,
      "code": "530000",
      "label": "云南省"
    },
    {
      "id": 26,
      "code": "540000",
      "label": "西藏自治区"
    },
    {
      "id": 27,
      "code": "610000",
      "label": "陕西省"
    },
    {
      "id": 28,
      "code": "620000",
      "label": "甘肃省"
    },
    {
      "id": 29,
      "code": "630000",
      "label": "青海省"
    },
    {
      "id": 30,
      "code": "640000",
      "label": "宁夏回族自治区"
    },
    {
      "id": 31,
      "code": "650000",
      "label": "新疆维吾尔自治区"
    },
    {
      "id": 32,
      "code": "710000",
      "label": "台湾省"
    },
    {
      "id": 33,
      "code": "810000",
      "label": "香港特别行政区"
    },
    {
      "id": 34,
      "code": "820000",
      "label": "澳门特别行政区"
    }
  ]
}

注意:由于篇幅原因,这里步骤一、步骤二只演示了provinces 的对象类型创建跟数据预置,citiesdistricts 需要按上面步骤自行创建。

三、部署云数据库

数据配置完成,右击“CloudProgram -> clouddb”目录,选择“Deploy Cloud DB”,DevEco Studio将自动把配置的信息同步至AppGallery Connect云数据库中。

同步完成,在IDE的右下角会有如下截图:

友情提示:对象类型,字段 如果是 IntAutoIncrement 自增,初始值为1,不可从0开始,否则部署云数据的时候会报错。

我们可以在AppGallery Connect 对应项目中的云数据库中找到我们部署的数据存储区跟对象类型(表),以及对应预置的数据。

1、存储区

2、对象类型

3、数据

接下来我们继续讲下一章节的内容,讲讲我们如何开发云函数,利用云函数查询云数据库数据的功能。

云函数实现业务逻辑

一、创建云函数

1、右击“CloudProgram -> cloudfunctions”目录,选择“New > Cloud Function”,例如命名为“province-query”。

点击OK之后,在“cloudfunctions”目录下会生成一个province-query的函数目录,如下图所示:

二、云函数目录讲解

        1、provinceQuery.ts:函数入口文件(此处以“provinceQuery.ts”为例,请以实际名称为准)。请参考鸿蒙官网开发函数编写函数代码,这里不对函数入口文件做过多阐述。

let myHandler = async function (event, context, callback, logger) {
  logger.info(event);

  // do something here

  callback({
    code: 0,
    desc: "Success."
  });
};

export { myHandler };
  • myHandler:入口方法名称。
  • event:调用方传递的事件对象,JSON格式。具体内容请参见event对象。
  • context:函数运行时上下文对象,封装了日志接口、回调接口、环境变量env对象等。
  • callback:事件处理结果。
  • logger:记录日志。

        函数必须通过显示调用callback(object)将事件处理结果返回给AGC,结果可以是任意对象,但必须与JSON.stringify兼容,AGC会将结果转换成JSON字符串后,返回给调用方。callback执行完成,函数即执行结束。

        2、function-config.json:函数的配置文件,可配置触发器,通过触发器暴露的触发条件来实现函数调用。

        在“triggers”下配置触发器,云函数目前支持以下5种触发器。

       注意如您需在函数部署完成后更新触发器,请先删除之前的触发器配置,再添加新的触发器配置,否则您的更新将不生效。

触发器描述
HTTP触发器

函数部署到云端后会自动生成触发URL,在您向该URL发起HTTP请求时触发函数。

请参见官网通过HTTP触发器调用函数

CLOUDDB触发器

当云数据库发生插入或者更新数据、删除数据、清空数据等变更操作时将触发云函数。

请参见官网云数据库调用函数

AUTH触发器

为函数配置AUTH触发器来接收用户的注册、登录等关键事件。例如,若添加了“用户注册”事件类型的AUTH触发器,当认证服务检测到用户注册事件发生时将触发函数。

请参见认证服务调用函数官网认证服务调用函数

CLOUDSTORAGE触发器

当AGC云存储服务中发生文件或者文件夹上传或删除操作时,将触发函数并执行您想要实现的功能。

请参见官网云存储调用函数

CRON触发器

CRON触发器即定时任务触发器,用于在指定的时间点触发云函数。

请参见官网通过定时任务触发器调用函数

 

触发器的具体知识这里我们不讲,大家可以查阅鸿蒙官网,会比我讲的详细,本次Demo我们会使用到HTTP触发器。

   3、package.json:包含了当前函数的名称、版本等函数元数据。package.json内自动引入了云数据库的最新版本Node.js Server SDK,您也可以在“dependencies”下添加其他需要的依赖。

        我这边版本的IDE实际操作创建云函数时,函数目录下只生成了如上面截图所示的provinceQuery.ts、function-config.json、package.json这三个文件,package.json 文件中也没有自动引入云数据库依赖,实际上完整的云函数目录结构应该是下面这样的。

那我们只需要在package.json 文件中下增加如下云数据库依赖, 点击Run npm install即可 。

   4、node_modules:自动为该函数引入依赖包。

   5、package-lock.json:保存了node_modules中所有包的信息,如版本、下载地址等。

        

三、创建resources目录

·        在“province-query”下新建一个"resources"目录。

        

注意:由于篇幅原因,这里步骤一、步骤三只演示了provinces-query 云函数的创建和配置citiesdistricts 对应的云函数需要按上面步骤自行创建。

四、获取云端凭据

        1、进入AppGallery Connect,点击“我的项目”。

        2、点击应用或者元服务所属的项目,进入“项目设置”页面。

        3、选中“Server SDK”页签,点击“下载认证凭据”。

        4、将获取的云端凭据文件放置在云函数中新建的"resources"目录下。d

五、导出之前创建的元数据库对象信息

        1、进入AppGallery Connect,点击“我的项目”。

        2、点击元服务所属的项目,进入“项目设置”页面。

        3、左侧导航选择“Serverless > 云数据库”,选中“provinces”、“cities”、“districts”对象类型,点击“导出”。

        4、“导出文件格式”选择“js格式”,“js文件类型”选择“serverSDK”,点击“确定”,导出压缩包文件,解压后得到 provinces.js、cities.js、districts.js文件。

        5、将导出的provinces.js、cities.js、districts.js文件放置云函数的根目录。

        

六、为实现操作数据库创建一个类CloudDBZoneProvinceDao

        1、右击province-query云函数,选择“New > File”,文件名填写CloudDBZoneProvinceDao.ts

        2、在文件中补充如下完整代码,其中credentialPathagc-apiclient-1172400184764681664-7241544512647644597.json需替换为第四步获取的云端凭证名称。

import {
  AGConnectCloudDB,
  CloudDBZone,
  CloudDBZoneConfig,
  CloudDBZoneQuery,
  CloudDBZoneSnapshot
} from "@agconnect/database-server/dist/index.js"
import { AGCClient, CredentialParser } from "@agconnect/common-server"
import path from 'path'
import { provinces } from "./provinces"

let mProvincesObject = new provinces();

let logger

let mCloudDBZone: CloudDBZone

class CloudDBZoneProvinceDao {
  // AGC & 数据库初始化
  constructor(log) {

    let agcClient;

    const credentialPath = "/resources/gc-apiclient-1172400184764681664-7241544512647644597.json";
    try {
      agcClient = AGCClient.getInstance();
    } catch (error) {
      AGCClient.initialize(CredentialParser.toCredential(path.join(__dirname, credentialPath)));
      agcClient = AGCClient.getInstance();
    }

    AGConnectCloudDB.initialize(agcClient)

    const cloudDBZoneConfig = new CloudDBZoneConfig("cloudDBOfArea");

    const agconnectCloudDB = AGConnectCloudDB.getInstance(agcClient);
    mCloudDBZone = agconnectCloudDB.openCloudDBZone(cloudDBZoneConfig);
  }

  // 查询省份列表数据
  async executeQueryProvince(): Promise<provinces[]> {
    if (!mCloudDBZone) {
      console.log("CloudDBClient is null, try re-initialize it");
      return;
    }
    try {
      const query = CloudDBZoneQuery.where(provinces).orderByAsc('code');
      const resp: CloudDBZoneSnapshot<provinces> = await mCloudDBZone.executeQuery(query);
      console.log("CloudDB Success")
      return resp.getSnapshotObjects();
    } catch (error) {
      console.log("CloudDB error: " + error);
    }
  }
}

export default CloudDBZoneProvinceDao;

注意:这里只提供了CloudDBZoneProvinceDao作为例子,另外两个对象类型操作类请自行创建,也可在文章随附的Demo中拷贝。

在数据库对象类型操作类中,我们定义了几个数据库表操作方法:

  • executeQueryProvince  查询所有省份列表数据
  • executeQueryCitiesByPCode 根据省份编码查询城市列表数据
  • executeQueryDistrictByCCode 根据城市编码查询区/县列表数据

在下一步云函数触发器中,我们将使用这几个数据库对象类型操作类进行云数据数据查询操作。

七、在云函数入口文件中进行地区数据库的查询操作。

        这里依旧以province-query 云函数为例拷贝如下代码到provinceQuery.ts文件中,完整示例代码如下:

import CloudDBZoneProvinceDao from "./CloudDBZoneProvinceDao"
import {provinces} from "./provinces"

let myHandler = async function (event, context, callback, logger) {
  logger.info(event);

  var res = new context.HTTPResponse(context.env, {
    "res-type":"context.env",
    "faas-content-type":"json",
  },"application/json", "200");

  const cloudDBZoneProvinceDao = new CloudDBZoneProvinceDao(logger);

  let data: provinces[] = await cloudDBZoneProvinceDao.executeQueryProvince();

  var body = {
    result: data
  };
  res.body = body;

  callback(res);
};
export { myHandler };

        这里在myHandler中接收请求,可以获取请求参数进行处理,然后返回一个HttpResponse,使用CloudDBZoneProvinceDao 对象操作云数据库将省份列表数据从数据库中查询出来并作为请求响应body使用callback返回给客户端。

八、调试云函数

        省份列表数据云函数开发完毕,我们需要对函数进行调试,确保函数功能正常可用。

        1、右击“CloudProgram -> cloudfunctions”目录,选择“Run Cloud Functions”。

        

        如下截图,说明云函数本地运行成功。

        2、待DevEco Studio运行完成后,菜单选择“Tools > CloudDev > Cloud Functions Requestor”。

        3、在右侧“Cloud Functions Requestor”面板,对云函数进行调试。        

  •         Environment:选择“Local”。
  •         Cloud Function:选择“province-query”。
  •         Event:输入函数的参数,为JSON格式的请求体数据。

        4、点击“Trigger”,执行云函数,查看Result内容和日志信息。

九、部署云函数

        云函数调试正常后,右击“CloudProgram -> cloudfunctions”目录,选择“Deploy Cloud Functions”,DevEco Studio将自动把内容同步至AppGallery Connect云函数中。

        将函数部署到AGC控制台,支持单个部署和批量部署。这里我先演示一下单个部署。

        1、单个部署。右击需部署的函数目录,选择“Deploy Function”。  

       

        2、“底部状态栏右侧将展示函数打包与部署进度。请耐心等待,直至出现“Deploy successfully”消息,表示函数已成功部署。

        3、在AppGallery Connect 云函数面板可以查到我们部署上去的云函数。

        4、上面我们完成了省份查询 province-query云函数 中provinceQuery.js 云函数逻辑的编写,并将单个函数部署完成。那就一次到位,将城市查询云函数以及区县查询云函数的逻辑开发完毕,再进行批量云函数部署。

cityQuery.ts ,完整代码如下:

import CloudDBZoneCityDao from "./CloudDBZoneCityDao"
import {cities} from "./cities"

let myHandler = async function (event, context, callback, logger) {
  logger.info(event);

  var res = new context.HTTPResponse(context.env, {
    "res-type":"context.env",
    "faas-content-type":"json",
  },"application/json", "200");

  let provinceCode ;
  if (event.body) {
    var _body = JSON.parse(event.body);
    provinceCode = _body.code;
  } else {
    provinceCode = event.code;
  };

  if (!provinceCode) {
    provinceCode = '';
  }

  const cloudDBZoneCityDao = new CloudDBZoneCityDao(logger);

  let data: cities[] = await cloudDBZoneCityDao.executeQueryCitiesByPCode(provinceCode);

  var body = {
    result: data
  };
  res.body = body;

  callback(res);
};
export { myHandler };

 districtsQuery.js ,完整代码如下:

import CloudDBZoneDistrictDao from "./CloudDBZoneDistrictDao"
import {districts} from "./districts"

let myHandler = async function (event, context, callback, logger) {
  logger.info(event);

  var res = new context.HTTPResponse(context.env, {
    "res-type":"context.env",
    "faas-content-type":"json",
  },"application/json", "200");

  let cityCode;

  if (event.body) {
    var _body = JSON.parse(event.body);
    cityCode = _body.code;
  } else {
    cityCode = event.code;
  };

  if (!cityCode) {
    cityCode = '';
  }


  const cloudDBZoneDistrictDao = new CloudDBZoneDistrictDao(logger);

  let data: districts[] = await cloudDBZoneDistrictDao.executeQueryDistrictByCCode(cityCode);

  var body = {
    result: data
  };
  res.body = body;

  callback(res);
};
export { myHandler };

注意:

        这里有一个点需要留意下:

这里为什么要做这个处理的呢,只是因为方便直接在Cloud Functions Requestor面板中贴body中的JSON,比如客户端调用云函数时实际的报文是这样的,我们设置的json的时候是调用

functionCallable.call(params)

这个params 是  {"code":"110000"} ,后端接收到的是

{
  "body": "{\"code\":\"110000\"}"
}

body节点下的json需要进行转义。为了方便我们在Cloud Functions Requestor 中event框中直接贴

{"code":"110000"}

这里取请求报文做了下处理。

        5、批量部署函数。

        批量部署指将整个云函数目录下创建的所有函数同时部署到AGC控制台。

        

        到这里,关于云函数开发跟部署的流程我们就讲解完毕了,客户端关于地址联动涉及的三个接口我们都开发并完成部署,接下来我们开发客户端UI,介绍客户端如何调用云函数,并进行数据展示。

        由于篇幅原因,本篇文章数字已经到1W+,为了提高读者可读性,减少单次阅读疲劳感,我将另外写一篇《云开发入门实战二 实现城市多级联动Demo(下)》,对客户端调用云函数进行服务端数据获取展示功能进行讲解。

        这里对本篇文章进行一个回顾,做个总结

  1. 创建云数据库对象类型
  2. 预置数据
  3. 部署云数据库
  4. 创建云函数
  5. 获取云端凭证
  6. 导出元数据库对象信息拷贝到云函数根目录中
  7. 创建云数据库对象类型操作类(Dao)
  8. 云函数入口JS文件逻辑开发
  9. 调试并部署云函数

        谢谢大家的阅读。

         这里附上本文源码(只提供相关云数据库(对象类型、预置数据)、云函数核心类)源码下载地址

        

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

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

相关文章

redis之cluster集群

1、redis-cluster集群&#xff1a;redis3.0引入的分布式存储方案 2、集群&#xff1a;由多个node节点组成&#xff0c;redis数据分布在这些节点之中 &#xff08;1&#xff09;在集群之中也分主节点和从节点 &#xff08;2&#xff09;自带哨兵模式 3、redis-cluster集群的…

thinkphp6 不支持:redis错误

起因&#xff1a; 使用 redis 时候&#xff0c;thinkphp 报错。 解决方法&#xff1a; 打开 php.ini 文件&#xff0c;增加 extensionphp_redis.dll 即可

「 系统设计 」 为什么要做架构分层?

「 系统设计 」 为什么要做架构分层&#xff1f; 参考&鸣谢 3.设计模式之分层思维&#xff1a;为什么要做代码分层架构&#xff1f; 从零开始学架构&#xff08;八&#xff09;分层架构和设计模式 架构模式之分层架构总结 文章目录 「 系统设计 」 为什么要做架构分层&…

PLC通过lora网关采集温室大棚温湿度数据

概述: 运用lora网关远程控制大棚内风机&#xff0c;日光灯&#xff0c;温湿度传感器等设备。可以实现远程获取现场环境的空气温湿度、土壤水分温度、二氧化碳浓度、光照强度可以自动控制温室湿帘风机、喷淋滴灌、加温补光等设备&#xff0c;并向远程计算机端推送实时数据&…

安卓手机便签APP用哪个,手机上好用的便签APP是什么

在日常生活及工作方面&#xff0c;总是有许多做不完的事情需要大家来处理&#xff0c;当多项任务堆叠交叉在一起时&#xff0c;很容易漏掉一些项目&#xff0c;这时候大家会借助经常携带的手机来记录容易忘记的事情&#xff0c;如手机上的闹钟、定时提醒软件都可以用来记录待办…

Python生产、消费Kafka

如果想通过docker安装kafka&#xff0c;可参考 Docker安装Kafka 生产者 import json import time import tracebackfrom datetime import datetime from kafka import KafkaProducer from kafka.errors import kafka_errorsproducer KafkaProducer(bootstrap_servers[localho…

复费率电表和预付费电表有哪些区别?

随着科技的发展和能源管理的日益严格&#xff0c;电表技术也在不断更新换代。复费率电表和预付费电表作为两种主流的智能电表&#xff0c;各自具有独特的优势和应用场景。接下来&#xff0c;小编来为大家详细解析这两种电表的区别及其应用场景。 一、复费率电表 1.定义及工作原…

基于STM32的电影院安全系统的设计与实现(论文+源码)

1.系统设计 本次基于STM32F4的电影院安全系统的设计与实现&#xff0c;以STM32F4单片机为核心控制器&#xff0c;配合人体红外传感器&#xff0c;烟雾传感器&#xff0c;甲醛传感器等硬件设施&#xff0c;实现了对电影院内环境的检测&#xff0c;当出现异常则会通过蜂鸣器和LE…

拼多多商品详情数据接口(Pinduoduo.item_get)

拼多多商品详情数据接口是一种程序化的接口&#xff0c;通过这个接口&#xff0c;商家或开发者可以使用自己的编程技能&#xff0c;对拼多多平台上的商品信息进行查询、获取和更新。这个接口允许商家根据自身的需求&#xff0c;获取商品的详细信息&#xff0c;例如价格、库存、…

Harmony 应用开发之size 脚本

作者&#xff1a;麦客奥德彪 在应用开发中&#xff0c;最终呈现在用户面前的UI&#xff0c;是用户能否继续使用应用的强力依据之一&#xff0c;在之前的开发中&#xff0c;Android 屏幕碎片化严重&#xff0c;所以出现了很多尺寸适配方案。 最小宽适配、百分比适配等等。 还有一…

【论文】Bao:一种用于现代多核嵌入式系统的轻型静态分区管理程序

Bao&#xff1a;一种用于现代多核嵌入式系统的轻型静态分区管理程序 个人学习过程中 Bao Hypervisor 论文翻译&#xff08;借助翻译工具个人校对&#xff09;&#xff0c;仅供学习使用&#xff0c;由于个人对一些技术专有名词不够熟悉&#xff0c;翻译不当的地方欢迎指出 论文地…

windows11下安装Tensor RT,并在conda虚拟环境下使用

建议仔细读一读NVIDIA官方出的安装教程&#xff0c;里面有windows、linux等安装教程&#xff0c;非常详细&#xff0c;这里再做一下简要总结。 TensorRT主要有三种安装模式、五种安装方式 毫无疑问&#xff0c;在windows系统中&#xff0c;我们只能选择zip安装。 安装tensorR…

【软件测试】技术不好?不学这几招你怎么跳槽?

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、软件测试面试环…

java springboot测试类鉴定虚拟MVC请求 返回内容与预期值是否相同

上文 java springboot测试类鉴定虚拟MVC运行值与预期值是否相同 中 我们验证了它HTTP的返回状态 简单说 校验了他 是否成功的状态 这次 我们来不对得到的内容 我们 直接改写测试类代码如下 package com.example.webdom;import org.junit.jupiter.api.Test; import org.springf…

AIGC 实践——七鱼客服机器人业务指标波动分析

智能客服机器人的业务指标&#xff0c;最常见的就是解决率&#xff0c;解决率的高低直接关系到客户采购机器人的价值。解决率很高&#xff0c;客户可以省下很多成本开销&#xff0c;如果解决率很低&#xff0c;那么就没有必要采购这个客服机器人。所以&#xff0c;智能客服机器…

PyTorch深度学习实战——人体姿态估计

PyTorch深度学习实战——人体姿态估计 0. 前言1. 人体姿态估计2. 使用 Detectron2 实现人体姿态估计相关链接 0. 前言 我们已经学习了如何执行实例分割&#xff0c;在本节中&#xff0c;我们将了解如何利用 Detectron2 对图像执行人体姿态估计&#xff0c;检测图像中人物的身体…

Atlassian Confluence 路径遍历和命令执行漏洞 (CVE-2019-3396)

漏洞描述 Confluence 是由澳大利亚软件公司 Atlassian 开发的基于 Web 的企业 wiki。 Atlassian Confluence 6.14.2 版本之前存在一个未经授权的目录遍历漏洞&#xff0c;攻击者可以使用 Velocity 模板注入读取任意文件或执行任意命令。 漏洞环境及漏洞利用 启动docker环境…

GPRS电表和4G电表有哪些区别?

随着科技的不断进步&#xff0c;通信技术在智能电网中的应用越来越广泛。其中&#xff0c;GPRS电表和4G电表作为两种常见的远程智能抄表方案&#xff0c;为广大用户带来了便捷的用电管理体验。然而&#xff0c;这两种电表在技术特点、应用场景等方面存在一定差异。下面&#xf…

Authing 入选《 2023 年央国企信创应用与实践研究报告》优秀服务商

11 月 21 日&#xff0c;Authing 身份云作为国内唯一事件驱动云原生身份平台入选《 2023 年央国企信创应用与实践研究报告》优秀服务商&#xff0c;该报告由第一新声研究院合伙人、Gartner 前高管合伙人/副总裁李长华牵头指导&#xff0c;第一新声创始人兼 CEO 组织&#xff0c…

华中科技大学李松课题组,利用机器学习预测多孔材料水吸附等温线

多孔材料的水吸附等温线是一个非常重要的参数&#xff0c;但这一参数的获得并不容易。这是因为多孔材料种类过多、结构多元&#xff0c;通过实验和计算的方式获得水吸附等温线数据成本过高&#xff0c;耗时过长。 华中科技大学的李松课题组&#xff0c;建立了一个两步机器学习模…