Elasticsearch:Jira 连接器教程第一部分

作者:来自 Elastic Gustavo Llermaly

将我们的 Jira 内容索引到 Elaasticsearch 中以创建统一的数据源并使用文档级别安全性进行搜索。

在本文中,我们将回顾 Elastic Jira 原生连接器的一个用例。我们将使用一个模拟项目,其中一家银行正在开发一款汇款应用,需要将 Jira 中的信息集成到 Elastic 中。

原生连接器允许我们从票据、任务和其他文档中获取 Elastic 集群信息,集中数据并启用高级搜索功能。

使用此连接器的主要好处是:

  1. Jira 中的数据与 Elasticsearch 同步。
  2. 访问高级搜索功能。
  3. 文档级安全性 (DLS) 匹配源安全性。你只能搜索 Jira 中允许你查看的内容。

步骤

  1. 配置 Jira 连接器
  2. 将文档索引到 Elasticsearch
  3. 查询数据
  4. 文档级安全性 (document level security  - DLS)

配置 Jira 连接器

首先,你需要从 Jira 获取 API token 以连接到 Elasticsearch。转到此链接了解如何创建它。

将其命名为 “elastic-connector”。它应该如下所示:

获取 token 并进入 Kibana 仪表板。然后,转到原生连接器并选择 New Jira Cloud connector。

https://<YOUR_KIBANA_URL>/app/enterprise_search/content/connectors/new_connector?service_type=jira&connector_type=native

用 Kibana 端点替换 YOUR_KIBANA_URL。

将连接器命名为 “bank”,然后点击 “Create and attach an index named bank”,即可创建一个同名的新索引。

完成了!现在我们需要配置我们的 Jira 数据。

由于我们不会使用自己的 SSL 证书,因此我们将保持 “Enable SSL” 关闭。

你可以在官方文档中查看每个字段的详细信息。

激活文档级安全性 (DLS),以便你获得有权查看文档的用户和组。

正确配置连接器后,你可以继续同步数据,如下所示。从 Jira 获取数据可能需要几分钟。

  • 完整内容(Full Content):索引所有 Jira 文档。
  • 增量内容(Incremental Content):仅索引自上次完整内容同步以来的更改。
  • 访问控制(Access Control):在安全索引中索引 Jira 用户以激活 DLS。

我们可以检查连接器的概述来查看同步是否成功。

在 “Documents” 选项卡中,我们可以准确地看到使用连接器获取的数据。第一次同步的对象是:

  • Projects
  • Issues
  • Attachments

将文档索引到 Elasticsearch

我们不仅限于跨连接器文档进行搜索。Elasticsearch 允许你使用单个查询搜索多个索引。

在我们的示例中,我们将其他文档索引到 galactic_documents 索引中,以了解搜索如何与多个数据源配合使用:

  • GBFF 合规手册
  • Galactic Banking App 用户指南
  • 技术规格报告

但在索引之前,我们将为每个字段创建优化映射:

PUT /galactic_documents
{
  "mappings": {
    "properties": {
      "document_id": {
        "type": "keyword"
      },
      "title": {
        "type": "text",
        "fields": {
          "raw": {
            "type": "keyword"
          }
        }
      },
      "content": {
        "type": "text"
      },
      "release_date": {
        "type": "date",
        "format": "yyyy-MM-dd"
      },
      "page_count": {
        "type": "integer"
      },
      "tags": {
        "type": "keyword"
      }
    }
  }
}

配置映射后,我们现在可以索引:

POST galactic_documents/_bulk
{ "index": { "_index": "galactic_documents", "_id": "1" } }
{ "document_id": "GBFF-001", "title": "Compliance Manual of the GBFF", "content": "This document sets forth the compliance standards for intergalactic financial entities: Quantum-level data encryption to guarantee security in all transactions. Mandatory multi-factor authentication for all users and administrators. Quarterly reviews of security policies and access audit logs.", "release_date": "2024-01-01", "page_count": 5, "tags": ["compliance", "security"] }
{ "index": { "_index": "galactic_documents", "_id": "2" } }
{ "document_id": "GBFF-002", "title": "User Guide for the Galactic Banking App", "content": "Welcome to the Galactic Banking application by Interstellar Finance Corp. Here you can: Transfer galactic credits to any registered account across the Milky Way. Check your balance and manage your investments in real-time. Access interplanetary loans with ease. For your security, use multi-factor authentication each time you log in.", "release_date": "2024-01-01", "page_count": 3, "tags": ["user guide", "application"] }
{ "index": { "_index": "galactic_documents", "_id": "3" } }
{ "document_id": "GBFF-003", "title": "Technical Specifications Report - Galactic Banking Project", "content": "This report details the technical architecture of the Galactic Banking application: Microservices-based backend for scalability and performance. Secure communication protocols utilizing quantum encryption. Transaction management adapted to environments with gravity variations and time dilation.", "release_date": "2024-01-01", "page_count": 7, "tags": ["technical", "specifications", "architecture"] }

查询数据

现在我们有了 Jira 对象和文档,我们可以一起搜索它们。

GET bank,galactic_documents/_search
{
  "query": {
    "multi_match": {
      "query": "galactic moon",
      "fields": [
        "content",
        "title",
        "*description",
        "*summary"
      ]
    }
  }
}

查询 “galactic moon” 将为我们获取 Jira 对象和我们索引的文档:

{
  "took": 3,
  "timed_out": false,
  "_shards": {
    "total": 3,
    "successful": 3,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 1.2613049,
    "hits": [
      {
        "_index": "bank",
        "_id": "Marketing Mars-MM-2",
        "_score": 1.2613049,
        "_source": {
          "Type": "Task",
          "Custom_Fields": {
            "Satisfaction": null,
            "Approvals": null,
            "Change reason": null,
            "Epic Link": null,
            "Actual end": null,
            "Design": null,
            "Campaign assets": null,
            "Department": null,
            "Story point estimate": null,
            "Approver groups": null,
            "[CHART] Date of First Response": null,
            "Request Type": null,
            "Campaign goals": null,
            "Project overview key": null,
            "Related projects": null,
            "Campaign type": null,
            "Impact": null,
            "Request participants": [],
            "Locked forms": null,
            "Time to first response": null,
            "Work category": null,
            "Audience": null,
            "Open forms": null,
            "Details": null,
            "Sprint": null,
            "Stakeholders": null,
            "Marketing asset type": null,
            "Submitted forms": null,
            "Start date": null,
            "Actual start": null,
            "Category": null,
            "Change risk": null,
            "Target start": null,
            "Issue color": null,
            "Parent Link": {
              "hasEpicLinkFieldDependency": false,
              "showField": false,
              "nonEditableReason": {
                "reason": "EPIC_LINK_SHOULD_BE_USED",
                "message": "To set an epic as the parent, use the epic link instead"
              }
            },
            "Format": null,
            "Target end": null,
            "Approvers": null,
            "Team": null,
            "Change type": null,
            "Satisfaction date": null,
            "Request language": null,
            "Amount": null,
            "Rank": "0|i0003j:",
            "Affected services": null,
            "Type": null,
            "Time to resolution": null,
            "Total forms": null,
            "[CHART] Time in Status": null,
            "Organizations": [],
            "Flagged": null,
            "Project overview status": null
          },
          "Issue": {
            "statuscategorychangedate": "2024-11-01T17:52:30.550-0300",
            "issuetype": {
              "avatarId": 10318,
              "hierarchyLevel": 0,
              "name": "Task",
              "self": "https://xxxx.atlassian.net/rest/api/2/issuetype/10017",
              "description": "A small, distinct piece of work.",
              "entityId": "f30ea676-7b3d-44ad-9858-558081742a2e",
              "id": "10017",
              "iconUrl": "https://xxxx.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10318?size=medium",
              "subtask": false
            },
            "components": [],
            "timespent": null,
            "timeoriginalestimate": null,
            "project": {
              "simplified": true,
              "avatarUrls": {
                "48x48": "https://xxxx.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10418",
                "24x24": "https://xxxx.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10418?size=small",
                "16x16": "https://xxxx.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10418?size=xsmall",
                "32x32": "https://xxxx.atlassian.net/rest/api/2/universal_avatar/view/type/project/avatar/10418?size=medium"
              },
              "name": "Marketing Mars",
              "self": "https://xxxx.atlassian.net/rest/api/2/project/10003",
              "id": "10003",
              "projectTypeKey": "business",
              "key": "MM"
            },
            "description": null,
            "fixVersions": [],
            "aggregatetimespent": null,
            "resolution": null,
            "timetracking": {},
            "security": null,
            "aggregatetimeestimate": null,
            "attachment": [],
            "resolutiondate": null,
            "workratio": -1,
            "summary": "Conquer the moon",
            "issuerestriction": {
              "issuerestrictions": {},
              "shouldDisplay": true
            },
            "watches": {
              "self": "https://xxxx.atlassian.net/rest/api/2/issue/MM-2/watchers",
              "isWatching": true,
              "watchCount": 1
            },
            "lastViewed": "2024-11-01T17:52:34.925-0300",
            "creator": {
              "accountId": "712020:88983800-6c97-469a-9451-79c2dd3732b5",
              "emailAddress": "contornan_cliche.0y@icloud.com",
              "avatarUrls": {
                "48x48": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png",
                "24x24": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png",
                "16x16": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png",
                "32x32": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png"
              },
              "displayName": "Tomas Murua",
              "accountType": "atlassian",
              "self": "https://xxxx.atlassian.net/rest/api/2/user?accountId=712020%3A88983800-6c97-469a-9451-79c2dd3732b5",
              "active": true,
              "timeZone": "Chile/Continental"
            },
            "subtasks": [],
            "created": "2024-11-01T17:52:30.289-0300",
            "reporter": {
              "accountId": "712020:88983800-6c97-469a-9451-79c2dd3732b5",
              "emailAddress": "contornan_cliche.0y@icloud.com",
              "avatarUrls": {
                "48x48": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png",
                "24x24": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png",
                "16x16": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png",
                "32x32": "https://secure.gravatar.com/avatar/f098101294d1a0da282bb2388df8c257?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FTM-3.png"
              },
              "displayName": "Tomas Murua",
              "accountType": "atlassian",
              "self": "https://xxxx.atlassian.net/rest/api/2/user?accountId=712020%3A88983800-6c97-469a-9451-79c2dd3732b5",
              "active": true,
              "timeZone": "Chile/Continental"
            },
            "aggregateprogress": {
              "total": 0,
              "progress": 0
            },
            "priority": {
              "name": "Medium",
              "self": "https://xxxx.atlassian.net/rest/api/2/priority/3",
              "iconUrl": "https://xxxx.atlassian.net/images/icons/priorities/medium.svg",
              "id": "3"
            },
            "labels": [],
            "environment": null,
            "timeestimate": null,
            "aggregatetimeoriginalestimate": null,
            "versions": [],
            "duedate": null,
            "progress": {
              "total": 0,
              "progress": 0
            },
            "issuelinks": [],
            "votes": {
              "hasVoted": false,
              "self": "https://xxxx.atlassian.net/rest/api/2/issue/MM-2/votes",
              "votes": 0
            },
            "comment": {
              "total": 0,
              "comments": [],
              "maxResults": 0,
              "self": "https://xxxx.atlassian.net/rest/api/2/issue/10018/comment",
              "startAt": 0
            },
            "assignee": null,
            "worklog": {
              "total": 0,
              "maxResults": 20,
              "startAt": 0,
              "worklogs": []
            },
            "updated": "2024-11-01T17:52:42.711-0300",
            "status": {
              "name": "To Do",
              "self": "https://xxxx.atlassian.net/rest/api/2/status/10014",
              "description": "",
              "iconUrl": "https://xxxx.atlassian.net/",
              "id": "10014",
              "statusCategory": {
                "colorName": "blue-gray",
                "name": "To Do",
                "self": "https://xxxx.atlassian.net/rest/api/2/statuscategory/2",
                "id": 2,
                "key": "new"
              }
            }
          },
          "id": "Marketing Mars-MM-2",
          "_timestamp": "2024-11-01T17:52:42.711-0300",
          "Key": "MM-2",
          "_allow_access_control": [
            "account_id:712020:88983800-6c97-469a-9451-79c2dd3732b5",
            "name:Tomas-Murua"
          ]
        }
      },
      {
        "_index": "galactic_documents",
        "_id": "2",
        "_score": 0.61183906,
        "_source": {
          "document_id": "GBFF-002",
          "title": "User Guide for the Galactic Banking App",
          "content": "Welcome to the Galactic Banking application by Interstellar Finance Corp. Here you can: Transfer galactic credits to any registered account across the Milky Way. Check your balance and manage your investments in real-time. Access interplanetary loans with ease. For your security, use multi-factor authentication each time you log in.",
          "release_date": "2024-01-01",
          "page_count": 3,
          "tags": [
            "user guide",
            "application"
          ]
        }
      },
      {
        "_index": "galactic_documents",
        "_id": "3",
        "_score": 0.5029222,
        "_source": {
          "document_id": "GBFF-003",
          "title": "Technical Specifications Report - Galactic Banking Project",
          "content": "This report details the technical architecture of the Galactic Banking application: Microservices-based backend for scalability and performance. Secure communication protocols utilizing quantum encryption. Transaction management adapted to environments with gravity variations and time dilation.",
          "release_date": "2024-01-01",
          "page_count": 7,
          "tags": [
            "technical",
            "specifications",
            "architecture"
          ]
        }
      }
    ]
  }
}

如果文档太长,你可以将选项 _source 添加到查询中,以仅包含你需要的字段。如果你只想删除一些字段,我们将在本系列的第二部分介绍该选项。

文档级安全性 (DLS)

我们现在将配置文档级安全性 (DLS),以将 Jira 权限与 Elasticsearch 中的权限相匹配,以便用户搜索时只能看到他们在 Jira 中被允许看到的内容。

首先,我们将转到 Elastic Cloud 中连接器的控制面板,然后单击 Access Control Sync。

此同步将带来 Jira 用户的访问和权限信息。为了测试这一点,我创建了另一个 Jira 板(board),但用户 “Gustavo” 无权访问该板。

注意:创建板后,不要忘记运行内容同步。你可以运行一次性同步,也可以按计划运行。

让我们开始检查新板中的文档是否存在:

GET bank/_search
{
  "_source": ["Issue.summary"],
  "query": {
   "match": {
     "Issue.project.name": "Marketing Mars"
   }
  }
}

我们可以有效地看到以下问题:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 2,
    "successful": 2,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 0.7473189,
    "hits": [
      {
        "_index": "bank",
        "_id": "Marketing Mars-MM-1",
        "_score": 0.7473189,
        "_source": {
          "Issue": {
            "summary": "Conquer Mars"
          }
        }
      },
      {
        "_index": "bank",
        "_id": "Marketing Mars-MM-3",
        "_score": 0.7473189,
        "_source": {
          "Issue": {
            "summary": "Conquering Earth"
          }
        }
      },
      {
        "_index": "bank",
        "_id": "Marketing Mars-MM-2",
        "_score": 0.7473189,
        "_source": {
          "Issue": {
            "summary": "Conquer the moon"
          }
        }
      }
    ]
  }
}

但是,由于用户 “Gustavo” 没有访问权限,因此他应该无法看到它们。

让我们在 ACL 过滤器索引中查找用户的文档以查看他们的权限。

GET .search-acl-filter-bank/_search

响应:

{
  "_index": ".search-acl-filter-bank",
  "_id": "63c04b092341bff4fff6e0cb",
  "_score": 1,
  "_source": {
    "created_at": "2024-11-01T23:19:35.784996+00:00",
    "id": "63c04b092341bff4fff6e0cb",
    "_timestamp": "2024-11-01T05:42:04.410478+00:00",
    "identity": {
      "account_id": "account_id:63c04b092341bff4fff6e0cb",
      "email_address": null,
      "display_name": "name:Gustavo",
      "locale": "locale:en_US"
    },
    "query": {
      "template": {
        "source": """{
          "bool": {
            "should": [
              {
                "bool": {
                  "must_not": {
                    "exists": {
                      "field": "_allow_access_control"
                    }
                  }
                }
              },
              {
                "terms": {
                  "_allow_access_control.enum": {{#toJson}}access_control{{/toJson}}
                }
              }
            ]
          }
        }""",
        "params": {
          "access_control": [
            "account_id:63c04b092341bff4fff6e0cb",
            "group_id:d3f28403-7e99-4262-8f11-77a75bcd33d8",
            "role_key:jira-software"
          ]
        }
      }
    }
  }
}

该索引包括用户 ID 及其所有 Jira 组。我们需要将用户访问控制中的内容与每个文档中的字段 _allowed_access_control 进行匹配。

我们将使用以下命令为 Gustavo 创建 API 密钥。你必须从上一步复制 query.template 值:

POST /_security/api_key
{
  "name": "gustavo",
  "expiration": "30d",
  "role_descriptors": {
    "jira-role": {
      "index": [
        {
          "names": [
            "bank",
            "galactic_documents"
          ],
          "privileges": [
            "read",
            "view_index_metadata"
          ],
          "query": {
            "template": {
              "params": {
                "access_control": [
                  "account_id:63c04b092341bff4fff6e0cb",
                  "group_id:d3f28403-7e99-4262-8f11-77a75bcd33d8",
                  "role_key:jira-software"
                ]
              },
              "source": """{
                "bool": {
                  "should": [
                    {
                      "bool": {
                        "must_not": {
                          "exists": {
                            "field": "_allow_access_control"
                          }
                        }
                      }
                    },
                    {
                      "terms": {
                        "_allow_access_control.enum": {{#toJson}}access_control{{/toJson}}
                      }
                    }
                  ]
                }
              }"""
            }
          }
        }
      ]
    }
  }
}

请注意,我们仅通过此选项授予对本文中索引的访问权限。

为 Gustavo 创建 API 密钥的响应如下:

{
  "id": "yLa1FJMBU4bZPaw5Stnl",
  "name": "gustavo",
  "expiration": 1733811245816,
  "api_key": "UrGdsnDFSyGxjQvLayw5jQ",
  "encoded": "eUxhMUZKTUJVNGJaUGF3NVN0bmw6VXJHZHNuREZTeUd4alF2TGF5dzVqUQ=="
}

你可以使用 curl 来测试我们是否可以使用 API KEY 运行搜索,并且它不会从 Marketing board 获取信息,因为 Gustavo 无权访问它。

curl --location --request GET 'https://interstellar-finance-corp.es.us-central1.gcp.cloud.es.io/bank/_search' \
--header 'Authorization: ApiKey eUxhMUZKTUJVNGJaUGF3NVN0bmw6VXJHZHNuREZTeUd4alF2TGF5dzVqUQ==' \
--header 'Content-Type: application/json' \
--data '{
  "_source": ["Issue.summary"],
  "query": {
   "match": {
     "Issue.project.name": "Marketing Mars"
   }
  }
}'

响应:

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 0,
      "relation": "eq"
    },
    "max_score": null,
    "hits": []
  }
}

我们可以看到,Gustavo 没有获得任何信息,因为他没有访问权限。现在,让我们用他被允许查看的 board 文件进行测试:

curl --location --request GET 'https://interstellar-finance-corp.es.us-central1.gcp.cloud.es.io/bank/_search?pretty=true' \
--header 'Authorization: ApiKey eUxhMUZKTUJVNGJaUGF3NVN0bmw6VXJHZHNuREZTeUd4alF2TGF5dzVqUQ==' \
--header 'Content-Type: application/json' \
--data '{
  "_source": ["Issue.summary"],
  "query": {
   "match": {
     "Issue.project.name": "Galactic Banking Project"
   }
  }
}'

响应:

{
  "took" : 7,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 3.1784885,
    "hits" : [
      {
        "_index" : "bank",
        "_id" : "Galactic Banking Project-GBP-3",
        "_score" : 3.1784885,
        "_source" : {
          "Issue" : {
            "summary" : "Intergalactic Security and Compliance"
          }
        }
      },
      {
        "_index" : "bank",
        "_id" : "Galactic Banking Project-GBP-2",
        "_score" : 0.5469647,
        "_source" : {
          "Issue" : {
            "summary" : "Bank Application Frontend"
          }
        }
      },
      {
        "_index" : "bank",
        "_id" : "Galactic Banking Project-GBP-1",
        "_score" : 0.5469647,
        "_source" : {
          "Issue" : {
            "summary" : "Development of API for International Transfers"
          }
        }
      }
    ]
  }
}

结论

如你所见,将 Elasticsearch 与 Jira 集成有许多好处,例如能够对你正在处理的所有项目进行统一搜索,以及能够在多个数据源中运行更高级的搜索。添加的 DLS 是一种快速简便的方法,可确保用户保持他们在原始源中已有的访问权限。

想要获得 Elastic 认证?了解下一次 Elasticsearch 工程师培训何时开始!

Elasticsearch 包含新功能,可帮助你为你的用例构建最佳搜索解决方案。深入了解我们的示例笔记本以了解更多信息,开始免费云试用,或立即在你的本地机器上试用 Elastic。

原文:Jira connector tutorial part I - Elasticsearch Labs

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

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

相关文章

Spring 6 第1章——概述

一.Spring是什么 Spring是一款主流的Java EE轻量级&#xff08;体积小、不需要依赖其它组件&#xff09;开源框架Spring的目的是用于简化Java企业级应用的开发难度和开发周期Spring的用途不仅限于服务端的开发&#xff0c;从简单性、可测试性和松耦合的角度而言&#xff0c;任…

git管理源码之git安装和使用

git是什么&#xff1f; git是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本管理&#xff0c;也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。git与常用的版本控制工具SVN等不同&#xff0c;它采用…

大疆最新款无人机发布,可照亮百米之外目标

近日&#xff0c;DJI 大疆发布全新小型智能多光旗舰 DJI Matrice 4 系列&#xff0c;包含 Matrice 4T 和 Matrice 4E 两款机型。DJI Matrice 4E 价格为27888 元起&#xff0c;DJI Matrice 4T价格为38888元起。 图片来源&#xff1a;大疆官网 DJI Matrice 4E DJI Matrice 4T D…

基于Java的语音陪聊软件——支持聊天私聊-礼物系统-直播系统-缘分匹配-游戏陪玩

丰富的经验、成熟的技术&#xff0c;打造适合当下市场发展的语音交友软件源码。Java 语言凭借其独特的优势&#xff0c;为这款语音陪聊软件的稳健运行和持续发展奠定了坚实基础。它不仅融合了聊天私聊、礼物系统和直播系统等实用且有趣的功能&#xff0c;还创新性地引入了缘分匹…

npm发布工具包+使用

1.初始化package包 npm init -y {"name": "common-cjs-tools","version": "1.0.0","main": "index.js","scripts": {"test": "echo \"Error: no test specified\" &&…

WXML模版语法-事件绑定

知识点1&#xff1a;什么是事件 事件是渲染层到逻辑层的通讯方式。通过事件可以将用户在渲染层产生的行为&#xff0c;反馈到逻辑层进行业务的处理。 知识点2&#xff1a;小程序中常用的事件 类型绑定方式事件描述tapbindtap或bind:tap手指触摸后马上离开&#xff0c;类似于…

Uniapp-运行到手机安卓基座报错

1、运行报错 2、解决adb冲突,显示设备列表&#xff0c;说明手机与电脑连接成功 3、重新运行&#xff0c;还是找不到&#xff0c;就多刷新几下即可。

ESP8266固件烧录

一、烧录原理 1、引脚布局 2、引脚定义 3、尺寸封装 4、环境要求 5、接线方式 ESP8266系列模块集成了高速GPI0和外围接口&#xff0c;这可能会导致严重的开关噪声。如果某些应用需要高功率和EMI特性&#xff0c;建议在数字I/0线上串联10到100欧姆。这可以在切换电源时抑制过冲…

紫光无人机AI飞控平台介绍

随着无人机技术的迅猛发展&#xff0c;无人机飞控平台的智能化需求不断提升。紫光无人机AI飞控平台作为一款创新型产品&#xff0c;为用户提供了从飞行控制到任务管理的一站式解决方案&#xff0c;尤其在AI实时识别和事件分析方面具有显著优势。本文将介绍平台的核心功能、技术…

【SpringBoot】Spring 一站式解决方案:融合统一返回结果、异常处理与适配器模式

前言 &#x1f31f;&#x1f31f;本期讲解关于统一功能处理的详细介绍~~~ &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; 你的点赞就是小编不断更新的最大动力 &#x1f386;那么废话…

回归预测 | MATLAB实RVM相关向量机多输入单输出回归预测

回归预测 | MATLAB实RVM相关向量机多输入单输出回归预测 目录 回归预测 | MATLAB实RVM相关向量机多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 RVM-Adaboost相关向量机集成学习多输入单输出回归预测是一种先进的机器学习方法&#xff0c;用于处理…

【C语言】内存函数详解与模拟实现

文章目录 拓展&#xff1a;Ⅰ. memcpy -- 内存拷贝1、函数介绍与使用2、模拟实现 Ⅱ. memmove -- 内存拷贝1、函数介绍与使用&#xff08;与memcpy函数的区别&#xff09;2、模拟实现 Ⅲ. memcmp -- 内存比较1、函数介绍与使用2、模拟实现 Ⅳ. memset -- 内存设置1、函数介绍与…

解析OVN架构及其在OpenStack中的集成

引言 随着云计算技术的发展&#xff0c;虚拟化网络成为云平台不可或缺的一部分。为了更好地管理和控制虚拟网络&#xff0c;Open Virtual Network (OVN) 应运而生。作为Open vSwitch (OVS) 的扩展&#xff0c;OVN 提供了对虚拟网络抽象的支持&#xff0c;使得大规模部署和管理…

解密AIGC三大核心算法:GAN、Transformer、Diffusion Models原理与应用

在当今数字化时代&#xff0c;人工智能生成内容&#xff08;AIGC&#xff09;技术正以前所未有的速度改变着我们的生活和工作方式。从创意无限的文本生成&#xff0c;到栩栩如生的图像创作&#xff0c;再到动听的音乐旋律&#xff0c;AIGC的魔力无处不在。而这一切的背后&#…

艾体宝干货丨网络故障排除基本指南

一、确保网络可视性以有效排除故障 有效的网络故障排除要求对穿越网络的数据具有完全的可见性&#xff0c;以便迅速识别和解决潜在问题。本指南深入探讨了一种结构化的网络分析方法&#xff0c;旨在提高故障排除的效率。首先&#xff0c;提出正确的问题至关重要&#xff0c;它…

汽车免拆诊断案例 | 2007 款法拉利 599 GTB 车发动机故障灯异常点亮

故障现象  一辆2007款法拉利599 GTB车&#xff0c;搭载6.0 L V12自然吸气发动机&#xff08;图1&#xff09;&#xff0c;累计行驶里程约为6万km。该车因发动机故障灯异常点亮进厂检修。 图1 发动机的布置 故障诊断 接车后试车&#xff0c;发动机怠速轻微抖动&#xff0c;…

浪潮海岳 UploadListFile文件上传致RCE漏洞

一、漏洞简介 浪潮云财务系统的/cwbase/EP/ListContent/UploadListFile.ashx接口存在任意文件上传漏洞&#xff0c;未经身份验证的攻击者可以通过该漏洞上传恶意脚本文件&#xff0c;从而控制目标服务器。 二、漏洞影响 三、网络测绘&#xff1a; fofa: body"/cwbase/w…

高等数学学习笔记 ☞ 不定积分的积分法

1. 第一换元积分法 1. 基础概念&#xff1a;形如的过程&#xff0c;称为第一换元积分法。 2. 核心思想&#xff1a;通过对被积函数的观察(把被积函数的形式与积分表的积分公式进行比较)&#xff0c;把外部的部分项拿到的内部(求原函数)&#xff0c; 然后进行拼凑&#xff0c;…

Spring Boot 整合 Shiro详解

文章目录 Spring Boot 整合 Shiro详解一、引言二、整合步骤1、创建项目并引入依赖2、配置Shiro2.1、自定义Realm2.2、配置SecurityManager和ShiroFilterFactoryBean 三、使用示例四、总结 Spring Boot 整合 Shiro详解 一、引言 在现代的Web应用开发中&#xff0c;用户认证和授…

win10 Outlook(new) 企业邮箱登录 登录失败。请在几分钟后重试。附移除办法

windows系统经常弹出使用Outlook(new&#xff09;&#xff0c;自动切过去。 但是登录企业的内网邮箱&#xff0c;折腾了好几次都使用不了。排查网络等问题&#xff0c;在社区找到了答案。 推出一年多不支持企业账户&#xff0c;所以之前的折腾都是浪费时间。 因为这个答案不太…