Geotools-PG空间库(Crud,属性查询,空间查询)

建立连接

经过测试,这套连接逻辑除了支持纯PG以外,也支持人大金仓,凡是套壳PG的都可以尝试一下。我这里的测试环境是Geosence创建的pg SDE,数据库选用的是人大金仓。

/**
  * 获取数据库连接资源
  *
  * @param connectConfig
  * @return
  * {@link PostgisNGDataStoreFactory} PostgisNGDataStoreFactory还有跟多的定制化参数可以进去看看
  * @throws Exception
  */
 public static DataStore ConnectDatabase(GISConnectConfig connectConfig) throws Exception {
     if (pgDatastore != null) {
         return pgDatastore;
     }
     //数据库连接参数配置
     Map<String, Object> params = new HashMap<String, Object>();
     // 数据库类型
     params.put(PostgisNGDataStoreFactory.DBTYPE.key, connectConfig.getType());
     params.put(PostgisNGDataStoreFactory.HOST.key, connectConfig.getHost());
     params.put(PostgisNGDataStoreFactory.PORT.key, connectConfig.getPort());
     // 数据库名
     params.put(PostgisNGDataStoreFactory.DATABASE.key, connectConfig.getDataBase());
     //用户名和密码
     params.put(PostgisNGDataStoreFactory.USER.key, connectConfig.getUser());
     params.put(PostgisNGDataStoreFactory.PASSWD.key, connectConfig.getPassword());
     // 模式名称
     params.put(PostgisNGDataStoreFactory.SCHEMA.key, "sde");
     // 最大连接
     params.put( PostgisNGDataStoreFactory.MAXCONN.key, 25);
     // 最小连接
     params.put(PostgisNGDataStoreFactory.MINCONN.key, 10);
     // 超时时间
     params.put( PostgisNGDataStoreFactory.MAXWAIT.key, 10);
     try {
         pgDatastore = DataStoreFinder.getDataStore(params);
         return pgDatastore;
     } catch (IOException e) {
         LOG.error("获取数据源信息出错");
     }
     return null;
 }

查询

  • 查询所有的表格
/**
  * 查询所有的表格
  * @return
  * @throws IOException
  */
 public List<String> getAllTables() throws IOException {
     String[] typeNames = this.dataStore.getTypeNames();
     List<String> tables = Arrays.stream(typeNames).collect(Collectors.toList());
     return tables;
 }

属性查询&&空间查询通用

 /**
    * 查询要素
    * @param layerName
    * @param filter
    * @return
    * @throws IOException
    */
   public  SimpleFeatureCollection queryFeatures(String layerName, Filter filter) throws IOException {
       SimpleFeatureCollection features = null;
       try {
           SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName);
           features = featureSource.getFeatures(filter);
           return features;
       } catch (Exception e) {
           e.printStackTrace();
       }
       return features;
   }
  • 属性筛选查询
    用数据库查:
    在这里插入图片描述
SELECT *FROM demoWHERE xmbh = '3308812023104'  AND zzdybh = '3308812023104003' AND zzlx = '10'

在这里插入图片描述
用代码查:

 SimpleFeatureCollection simpleFeatureCollection = pgTemplate.queryFeatures("demo", CQL.toFilter("xmbh = '3308812023104'  AND zzdybh = '3308812023104003' AND zzlx = '10'"));

在这里插入图片描述

  • 空间筛选
Geometry geometry = new WKTReader().read("Polygon ((119.13571152004580256 29.96675730309299368, 119.14239751148502933 29.62242874397260195, 119.49341206204465493 29.84975245290645063, 119.23265839591465465 30.0670471746814556, 119.13571152004580256 29.96675730309299368))");
// 直接写SQL
Filter filter = CQL.toFilter("INTERSECTS(shape," + geometry .toString() + ")");
// 或者使用FilterFactory 
Within within = ff.within(ff.property("shape"), ff.literal(geometry));
SimpleFeatureCollection simpleFeatureCollection = pgTemplate.queryFeatures("demo", within);

如果不知道使用的什么关键字就比如相交INTERSECTS,可以点进对应的这个空间关系里去看这个Name,和这个保持一致。
在这里插入图片描述

总结:这里就在于怎么去写这个Filter,可以直接使用SQL语法。也可以自己去构造,需要借助这两个类

private static FilterFactory2 spatialFilterFc = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());
private static FilterFactory propertyFilterFc = CommonFactoryFinder.getFilterFactory(null);

添加要素

/**
 * 
 * @param type 
 * @param features 需要追加的要素
 * @throws IOException
 */
public  void appendFeatures(SimpleFeatureType type, List<SimpleFeature> features) throws IOException {
    ListFeatureCollection featureCollection = new ListFeatureCollection(type, features);
    String typeName = type.getTypeName();
    FeatureStore featureStore = (FeatureStore) dataStore.getFeatureSource(typeName);
    try {
        featureStore.addFeatures(featureCollection);
    } catch (IOException e) {
        e.printStackTrace();
    }
    Transaction transaction = new DefaultTransaction("appendData");
    featureStore.setTransaction(transaction);
    transaction.commit();
}

测试代码:

Geometry geometry = new WKTReader().read("Polygon ((118.41044123299997182 29.89092741100000694, 118.42024576499994737 29.83296547499998042, 118.30907619399994246 29.75101510400003235, 118.19200671200002262 29.74673207400002184, 118.41044123299997182 29.89092741100000694))");
    SimpleFeature build = CustomFeatureBuilder.build(new HashMap<String, Object>() {{
        put("xmbh", "ceshiceshi");
        put("zxmmc", "测试一把");
        put("shape", geometry);
    }}, "demo" , geometry);
    SimpleFeatureType simpleFeatureType = dataStore.getSchema("demo");
    pgTemplate.appendFeatures(simpleFeatureType, Arrays.asList(build));

构建要素的代码如下:

/**
   *  构建一个Feature
   * @param fieldsMap
   * @param typeName
   * @return
   */
  public static SimpleFeature build(Map<String, Object> fieldsMap, String typeName) {
      SimpleFeatureTypeBuilder simpleFeatureTypeBuilder = new SimpleFeatureTypeBuilder();
      List<Object> values = new ArrayList<>();
      fieldsMap.forEach((key, val) -> {
          simpleFeatureTypeBuilder.add(key, val.getClass());
          values.add(val);
      });
      simpleFeatureTypeBuilder.setName(typeName);
      SimpleFeatureType simpleFeatureType = simpleFeatureTypeBuilder.buildFeatureType();
      SimpleFeatureBuilder builder = new SimpleFeatureBuilder(simpleFeatureType);
      builder.addAll(values);
      SimpleFeature feature = builder.buildFeature(null);
      return feature;
  }

在这里插入图片描述
图形也能正常展示:
在这里插入图片描述

/**
  * 通过FeatureWriter 追加要素
  * @param type
  * @param features
  * @throws IOException
  */
 public  void appendFeatureByFeatureWriter(SimpleFeatureType type, List<SimpleFeature> features) throws IOException {
     String typeName = type.getTypeName();
     FeatureWriter<SimpleFeatureType, SimpleFeature> featureWriter = dataStore.getFeatureWriterAppend(typeName, new DefaultTransaction("appendData"));
     for (SimpleFeature feature : features) {
         SimpleFeature remoteNext = featureWriter.next();
         remoteNext.setAttributes(feature.getAttributes());
         remoteNext.setDefaultGeometry(feature.getDefaultGeometry());
         featureWriter.write();
     }
    featureWriter.close();
 }

使用FeatureWriter这个时候要注意啦,你插入的时候必须每个字段都设置值,追进源码里面发现它的SQL是写了所有字段的
源码路径:JDBCDataStore#insertNonPS

在这里插入图片描述
所以下面这种方式是不会成功的,要成功的话必须设置所有的字段对应上,我懒得弄了原理就是上面源码那样的:

// 错误示范 需要填所有字段
Geometry geometry = new WKTReader().read("Polygon ((118.41044123299997182 29.89092741100000694, 118.42024576499994737 29.83296547499998042, 118.30907619399994246 29.75101510400003235, 118.19200671200002262 29.74673207400002184, 118.41044123299997182 29.89092741100000694))");
SimpleFeature build = CustomFeatureBuilder.build(new HashMap<String, Object>() {{
    put("xmbh", "writer");
    put("zxmmc", "demo");
    put("zzdybh", "fdsa");
    put("shape", geometry);
}}, "demo" );
SimpleFeatureType simpleFeatureType = dataStore.getSchema("demo");
pgTemplate.appendFeatureByFeatureWriter(simpleFeatureType, Arrays.asList(build));

追加要素的原理都是借助于空间函数,我们如果调试源码就会发现最终生成了一个SQL类似于下面这个SQL

INSERT INTO "sde"."demo" ( "xmbh","zzdybh","zxmmc","zzlx","zxmlx","zxmbh","zgbm","jsgm","jhtz","xzgdmj","xzgddb","lxrq","wcrq","bz","txmj","bsm","czzj","shzj","gdb_geomattr_data","shape","objectid" ) VALUES ( 'ces','11111','update',null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,ST_GeomFromText('POLYGON ((119.1357115200458 29.966757303092994, 119.14239751148503 29.622428743972602, 119.49341206204465 29.84975245290645, 119.23265839591465 30.067047174681456, 119.1357115200458 29.966757303092994))', 4490),2)

源码如下:

{@link JDBCDataStore#insertNonPS}
try {
  for (SimpleFeature feature : features) {
      String sql = insertSQL(featureType, feature, keysFetcher, cx);

      ((BasicSQLDialect) dialect).onInsert(st, cx, featureType);

      LOGGER.log(Level.FINE, "Inserting new feature: {0}", sql);
      if (keysFetcher.hasAutoGeneratedKeys()) {
          st.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
      } else {
          st.executeUpdate(sql);
      }

      keysFetcher.postInsert(featureType, feature, cx, st);
  }
} finally {
  closeSafe(st);
}

更新

  • 更新属性
/**
   * 更新属性
   * @param type
   * @param fieldsMap
   * @param filter
   * @throws IOException
   */
  public  void updateFeatures(SimpleFeatureType type, Map<String, Object> fieldsMap, Filter filter) throws IOException {
      String typeName = type.getTypeName();
      List<Name> names =new ArrayList<>();
      FeatureStore featureStore = (FeatureStore) dataStore.getFeatureSource(typeName);
      Set<String> keys = fieldsMap.keySet();
      for (String field : keys) {
          Name name = new NameImpl(field);
          names.add(name);
      }
      featureStore.modifyFeatures(names.toArray(new NameImpl[names.size()]), fieldsMap.values().toArray(), filter);
  }

测试代码:

HashMap<String, Object> fieldsMap = new HashMap<String, Object>() {{
    put("xmbh", "testupdate");
    put("zxmmc", "update");
    put("zzdybh", "3308812023104003");
}};
SimpleFeatureType simpleFeatureType = dataStore.getSchema("demo");
pgTemplate.updateFeatures(simpleFeatureType, fieldsMap, CQL.toFilter(" xmbh = 'ceshiceshi'"));

在这里插入图片描述
如果你需要更新几何,只需要设置几何字段即可:

HashMap<String, Object> fieldsMap = new HashMap<String, Object>() {{
     put("xmbh", "ces");
     put("zxmmc", "update");
     put("zzdybh", "3308812023104003");
     put("shape", geometry);
 }};

我们还可以这样写

/**
 * 覆盖更新
 * @param type
 * @param fieldsMap
 * @param filter
 * @throws IOException
 */
public  void updateFeatureFeatureReader(SimpleFeatureType type, Map<String, Object> fieldsMap, Filter filter) throws IOException {
    String typeName = type.getTypeName();
    FeatureStore featureStore = (FeatureStore) dataStore.getFeatureSource(typeName);
    SimpleFeature simpleFeature = CustomFeatureBuilder.build(fieldsMap, typeName);
    // 设置一个 FeatureReader
    FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = new CollectionFeatureReader(simpleFeature);
    featureStore.setFeatures(featureReader);
    featureReader.close();
}

这里还需要注意一点,featureReaders 是覆盖更新的逻辑,所以使用的时候要谨慎一点
在这里插入图片描述

下面有这么多实现类,具体怎么组合使用就看你的想象力了:
在这里插入图片描述

删除要素

/**
 * 删除数据
 *
 * @param layerName 图层名称
 * @param filter 过滤器
 */
public  boolean deleteData(String layerName, Filter filter) {
    try {
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName);
        FeatureStore featureStore = (FeatureStore) featureSource;
        featureStore.removeFeatures(filter);
        Transaction transaction = new DefaultTransaction("delete");
        featureStore.setTransaction(transaction);
        transaction.commit();
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

完整DEMO

Demo 代码难免写的比较草率,不要喷我奥,哈哈哈哈哈

public class PgTemplate {
private final DataStore dataStore;

public PgTemplate(DataStore dataStore) {
    this.dataStore = dataStore;
}

/**
 * @param type
 * @param features 需要追加的要素
 * @throws IOException
 */
public void appendFeatures(SimpleFeatureType type, List<SimpleFeature> features) throws IOException {
    ListFeatureCollection featureCollection = new ListFeatureCollection(type, features);
    String typeName = type.getTypeName();
    FeatureStore featureStore = (FeatureStore) dataStore.getFeatureSource(typeName);
    try {
        featureStore.addFeatures(featureCollection);
    } catch (IOException e) {
        e.printStackTrace();
    }
    Transaction transaction = new DefaultTransaction("appendData");
    featureStore.setTransaction(transaction);
    transaction.commit();
}

/**
 * 更新属性
 *
 * @param type
 * @param fieldsMap
 * @param filter
 * @throws IOException
 */
public void updateFeatures(SimpleFeatureType type, Map<String, Object> fieldsMap, Filter filter) throws IOException {
    String typeName = type.getTypeName();
    List<Name> names = new ArrayList<>();
    FeatureStore featureStore = (FeatureStore) dataStore.getFeatureSource(typeName);
    Set<String> keys = fieldsMap.keySet();
    for (String field : keys) {
        Name name = new NameImpl(field);
        names.add(name);
    }
    featureStore.modifyFeatures(names.toArray(new NameImpl[names.size()]), fieldsMap.values().toArray(), filter);
}

/**
 * 覆盖更新
 *
 * @param type
 * @param fieldsMap
 * @param filter
 * @throws IOException
 */
public void updateFeatureFeatureReader(SimpleFeatureType type, Map<String, Object> fieldsMap, Filter filter) throws IOException {
    String typeName = type.getTypeName();
    FeatureStore featureStore = (FeatureStore) dataStore.getFeatureSource(typeName);
    SimpleFeature simpleFeature = CustomFeatureBuilder.build(fieldsMap, typeName);
    FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = new CollectionFeatureReader(simpleFeature);
    featureStore.setFeatures(featureReader);
    featureReader.close();
}

/**
 * 通过FeatureWriter 追加要素
 *
 * @param type
 * @param features
 * @throws IOException
 */
public void appendFeatureByFeatureWriter(SimpleFeatureType type, List<SimpleFeature> features) throws IOException {
    String typeName = type.getTypeName();
    FeatureWriter<SimpleFeatureType, SimpleFeature> featureWriter = dataStore.getFeatureWriterAppend(typeName, new DefaultTransaction("appendData"));
    for (SimpleFeature feature : features) {
        SimpleFeature remoteNext = featureWriter.next();
        remoteNext.setAttributes(feature.getAttributes());
        remoteNext.setDefaultGeometry(feature.getDefaultGeometry());
        featureWriter.write();
    }
    featureWriter.close();
}

/**
 * 删除数据
 *
 * @param
 * @param
 * @param
 */
public boolean deleteData(String layerName, Filter filter) {
    try {
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName);
        FeatureStore featureStore = (FeatureStore) featureSource;
        featureStore.removeFeatures(filter);
        Transaction transaction = new DefaultTransaction("delete");
        featureStore.setTransaction(transaction);
        transaction.commit();
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
    return true;
}

/**
 * 查询要素
 *
 * @param layerName
 * @param filter
 * @return
 * @throws IOException
 */
public SimpleFeatureCollection queryFeatures(String layerName, Filter filter) throws IOException {
    SimpleFeatureCollection features = null;
    try {
        SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName);
        features = featureSource.getFeatures(filter);
        return features;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return features;
}

/**
 * 查询要素
 *
 * @param layerName
 * @param filter
 * @return
 * @throws IOException
 */
public SimpleFeatureCollection queryFeaturesByFeatureReader(String layerName, Filter filter) throws IOException {
    FeatureReader<SimpleFeatureType, SimpleFeature> featureReader = dataStore.getFeatureReader(new Query(layerName, filter), new DefaultTransaction("query"));
    SimpleFeatureType featureType = featureReader.getFeatureType();
    List<SimpleFeature> features = new ArrayList<>();
    while (featureReader.hasNext()) {
        SimpleFeature next = featureReader.next();
        features.add(next);
    }
    return new ListFeatureCollection(featureType, features);
}

/**
 * 查询所有的表格
 *
 * @return
 * @throws IOException
 */
public List<String> getAllTables() throws IOException {
    String[] typeNames = this.dataStore.getTypeNames();
    List<String> tables = Arrays.stream(typeNames).collect(Collectors.toList());
    return tables;
}

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

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

相关文章

DDMS修改默认端口8700

当前操作系统为 Mac&#xff0c;编辑器 Intellij IDE 准备工作&#xff1a;在IDE中的终端下&#xff0c;输入monitor指令 > 回车&#xff0c;打开DDMS 1、第一步&#xff0c; 2、第二步&#xff1a;修改静态端口 3、第三步 4、第四步&#xff1a;修复配置端口 5、第五步 重…

t2vec code

文章目录 执行过程preprocess.jl 解释h5 文件结构 执行过程 (base) zzqserver1:~/project/t2vec/preprocessing$ julia porto2h5.jl Processing 1710660 trips… 100000 200000 300000 400000 500000 600000 700000 800000 900000 1000000 1100000 1200000 1300000 1400000 15…

读写锁(arm)

参考文章读写锁 - ARM汇编同步机制实例&#xff08;四&#xff09;_汇编 prefetchw-CSDN博客 读写锁允许多个执行流并发访问临界区。但是写访问是独占的。适用于读多写少的场景 另外好像有些还区分了读优先和写优先 读写锁定义 typedef struct {arch_rwlock_t raw_lock; #if…

Android Firebase (FCM)推送接入

官方文档&#xff1a; 向后台应用发送测试消息 | Firebase Cloud Messaging 1、根级&#xff08;项目级&#xff09;Gradlegradle的dependencies中添加&#xff1a; dependencies {...// Add the dependency for the Google services Gradle pluginclasspath com.google.gm…

使用推测解码 (Speculative Decoding) 使 Whisper 实现 2 倍的推理加速

Open AI 推出的 Whisper 是一个通用语音转录模型&#xff0c;在各种基准和音频条件下都取得了非常棒的结果。最新的 large-v3 模型登顶了 OpenASR 排行榜&#xff0c;被评为最佳的开源英语语音转录模型。该模型在 Common Voice 15 数据集的 58 种语言中也展现出了强大的多语言性…

CentOS安装k8s单机/集群及一些命令

目录 前言 1. 安装docker 2. 安装要求 3.准备网络&#xff08;如果只装单机版可跳过此部&#xff09; 4. 准备工作 5. 安装 5.1. 配置阿里云yum k8s源 5.2 安装kubeadm、kubectl和kubelet 5.3 初始化&#xff0c;只在master执行&#xff0c;子节点不要执行 5.3.1 一些…

ActiveMQ任意文件写入漏洞(CVE-2016-3088)

简述&#xff1a;ActiveMQ的fileserver支持写入文件(但是不支持解析jsp),同时也支持移动文件。所以我们只需要先上传到服务器&#xff0c;然后再移动到可以解析的地方即可造成任意文件写入漏洞。我们可以利用这个漏洞来上传webshell或者上传定时任务文件。 漏洞复现 启动环境 …

回归预测 | Matlab基于SO-BiLSTM蛇群算法优化双向长短期记忆神经网络的数据多输入单输出回归预测

回归预测 | Matlab基于SO-LSTM蛇群算法优化长短期记忆神经网络的数据多输入单输出回归预测 目录 回归预测 | Matlab基于SO-LSTM蛇群算法优化长短期记忆神经网络的数据多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于SO-BiLSTM蛇群算法优…

记录汇川:H5U与Fctory IO测试7

主程序&#xff1a; 子程序&#xff1a; IO映射 子程序&#xff1a; 辅助出料程序 子程序&#xff1a; 辅助上料 子程序&#xff1a; 自动程序 FB块创建&#xff1a; H5U模块添加&#xff1a; Fctory IO配置&#xff1a; HMI配置 实际动作如下&#xff1a; Fctory IO测试7

JDBC

1 连接JDBC jdbc是连接java和数据库的桥梁&#xff0c;对于不同的数据库&#xff0c;如果我们希望用java连接&#xff0c;我们需要下载不同的驱动。这里我们使用mysql数据库&#xff0c;下载驱动。 MySQL :: Download MySQL Connector/J (Archived Versions) &#xff08;版本…

一卡通水控电控开发踩过的坑

最近在做一个项目&#xff0c;是对接一卡通设备的。我一开始只拿到设备和3个文档开局。不知道从哪下手。一步一步踩坑过来。踩了很多没有必要的坑&#xff0c;写出来给有用的人吧。 读卡器怎么用&#xff1f; 有个读卡器&#xff0c;一开始什么软件也不提供。我都不知道是干嘛…

深信服态势感知一体机SIP-1000 Y2100 3.0.1Y升级3.0.3Y步骤

当前版本&#xff1a;3.0.1Y 升级后版本&#xff1a;3.0.3Y PS&#xff1a;3.0.1Y不能直升3.0.3Y&#xff0c;需要先通过升级工具升级到3.0.2Y&#xff0c;再安装前置补丁从3.0.2Y升级到3.0.3Y&#xff1b;每一次升级时间为20-30分钟&#xff0c;设备升级会重启&#xff0c;需提…

Scrapy框架自学

配置国内镜像源 # pip设置配置 pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple pip config set trusted-host pypi.tuna.tsinghua.edu.cn创建虚拟环境 # 使用conda创建虚拟环境&#xff08;具体内容请参考课件&#xff09; conda create -n py_s…

树状结构查询 - 华为OD统一考试

OD统一考试 分值&#xff1a; 200分 题解&#xff1a; Java / Python / C 题目描述 通常使用多行的节点、父节点表示一棵树&#xff0c;比如&#xff1a; 西安 陕西 陕西 中国 江西 中国 中国 亚洲 泰国 亚洲 输入一个节点之后&#xff0c;请打印出来树中他的所有下层节点。 …

Element-ui图片懒加载

核心代码 <el-image src"https://img-blog.csdnimg.cn/direct/2236deb5c315474884599d90a85d761d.png" alt"我是图片" lazy><img slot"error" src"https://img-blog.csdnimg.cn/direct/81bf096a0dff4e5fa58e5f43fd44dcc6.png&quo…

使用paho.mqtt.embedded-c和openssl实现MQTT的单向认证功能

1、背景 由于项目有需求在一个现有的产品上增加MQTT通信的功能&#xff0c;且出于安全考虑&#xff0c;MQTT要走TLS&#xff0c;采用单向认证的方式。 2、方案选择 由于是在现有的产品上新增功能&#xff0c;那么为了减少总的成本&#xff0c;故选择只动应用软件的来实现需求。…

微软Office 2019 批量授权版

软件介绍 微软办公软件套件Microsoft Office 2019 专业增强版2024年1月批量许可版更新推送&#xff01;Office2019正式版2018年10月份推出&#xff0c;主要为多人跨平台办公与团队协作打造。Office2019整合对过去三年在Office365里所有功能&#xff0c;包括对Word、Excel、Pow…

小程序系列--4.协同工作和发布

一、小程序成员管理 1. 成员管理的两个方面 2. 不同项目成员对应的权限 3. 开发者的权限说明 4. 添加项目成员和体验成员 二、小程序的版本 1、小程序的版本 三、发布上线 1. 小程序发布上线的整体步骤 一个小程序的发布上线&#xff0c;一般要经过上传代码 -> 提…

Python: Spire.PDF-for-Python

# encoding: utf-8 # 版权所有 2024 ©涂聚文有限公司 # 许可信息查看&#xff1a; # 描述&#xff1a; # Author : geovindu,Geovin Du 涂聚文. # IDE : PyCharm 2023.1 python 3.11 # Datetime : 2024/1/11 10:32 # User : geovindu # Product : PyChar…

Unity组件开发--长连接webSocket

1.下载安装UnityWebSocket 插件 https://gitee.com/cambright/UnityWebSocket/ 引入unity项目&#xff1a; 2.定义消息体结构&#xff1a;ExternalMessage和包结构Package&#xff1a; using ProtoBuf; using System; using System.Collections; using System.Collections.Ge…