当前位置: 首页 > news >正文

使用Apache Commons SCXML实现状态机管理

第1章:引言

大家好,我是小黑,咱们程序员在开发过程中,经常会遇到需要管理不同状态和状态之间转换的场景。比如,一个在线购物的订单,它可能有“新建订单”、“已支付”、“配送中”、“已完成”等状态。在这些不同的状态之间转换,其实就是一个状态机的过程。

状态机,简单来说,就是一种模型,用来描述一个系统在不同状态下的行为。它的魅力在于能够让复杂的状态转换变得简洁清晰。想象一下,如果没有状态机,我们可能需要写很多if-else来处理不同的状态和事件,那代码可就乱得像鸡窝了。

这就引出了小黑今天要聊的主角——Apache Commons SCXML。这货是一个用来管理状态机的Java库,能让咱们以一种更优雅的方式来处理状态转换。它不仅支持XML配置状态机,还提供了API来控制状态机的行为,简直是管理复杂状态的利器!

第2章:SCXML简介

Apache Commons SCXML,这个名字听起来可能有点小长,但它其实是个非常给力的工具。它提供了一个基于SCXML标准(State Chart XML)的状态机实现,让咱们可以用XML文件来定义状态机。

为什么要用SCXML呢?因为它基于XML,这让状态机的定义变得非常直观和灵活。你可以直接在XML文件里定义状态、事件和转换规则,而不需要在Java代码里写一大堆逻辑。这样一来,状态机的修改和维护就简单多了,不用每次都去翻Java代码。

使用Apache Commons SCXML的好处还不止这些。它支持嵌套状态、并行状态、历史状态等高级特性,这些都是在复杂应用场景中非常有用的功能。比如,你的应用可能需要同时管理多个独立的状态机,或者在用户返回时保持之前的状态,SCXML都能轻松搞定。

那怎么用这个库呢?先来看看如何添加它到你的项目里。如果你用的是Maven,只需要在pom.xml中添加如下依赖:

<dependency><groupId>org.apache.commons</groupId><artifactId>commons-scxml</artifactId><version>0.9</version>
</dependency>

依赖配置好了之后,就可以开始愉快地定义状态机了。比如,小黑想定义一个简单的订单状态机,可能会这样写:

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"initial="新建订单"><state id="新建订单"><transition event="支付" target="已支付"/></state><state id="已支付"><transition event="发货" target="配送中"/></state><state id="配送中"><transition event="签收" target="已完成"/></state><state id="已完成"/>
</scxml>

这段XML就定义了一个简单的订单状态机。它从“新建订单”开始,然后可以按照支付、发货、签收的顺序转换到“已完成”。这样一来,咱们就用几行XML描述了整个订单流程。

第3章:状态机基础 - 让复杂的流程简单起来

聊到状态机,咱们得先搞明白它的三大基石:状态(State)、事件(Event)和转换(Transition)。这就像是学开车,得知道油门、刹车和方向盘怎么用一样。咱们先来一点点拆解这些概念。

状态(State):程序的各种场景

状态,就是程序在某一时刻的情形或者场景。比如,一个游戏角色可能有“静止”、“行走”、“跳跃”等状态。每个状态代表了角色在不同时刻的不同行为和特征。在状态机里,状态是静态的,就像是一张静止的照片,记录了某个瞬间的全部信息。

事件(Event):触发状态转换的信号

事件则是导致状态转换的外部输入。继续拿游戏角色来说,当玩家按下跳跃键时,就发生了一个“跳跃”事件,这个事件会触发角色从“静止”状态转换到“跳跃”状态。在状态机中,事件是动态的,就像是电影里的一幕幕,推动故事的发展。

转换(Transition):从一个状态到另一个状态的桥梁

最后,转换是连接两个状态的桥梁。它定义了在什么事件发生时,状态应该如何改变。例如,如果当前状态是“静止”,当“跳跃”事件发生时,状态就会转换到“跳跃”。

好了,理论知识讲完,小黑来给咱们看个具体的例子。假设小黑要管理一个电商的订单流程,订单有“新建”、“已支付”、“已发货”和“已完成”这几个状态。咱们用Java代码来实现一个简单的状态机:

import org.apache.commons.scxml2.model.*;public class OrderStateMachine {// 创建状态机private SCXMLExecutor executor;public OrderStateMachine() throws ModelException {// 定义状态机State newState = new State("新建");State paidState = new State("已支付");State shippedState = new State("已发货");State completedState = new State("已完成");// 定义状态转换Transition payTransition = new Transition("支付", paidState);Transition shipTransition = new Transition("发货", shippedState);Transition completeTransition = new Transition("签收", completedState);// 添加转换到各个状态newState.addTransition(payTransition);paidState.addTransition(shipTransition);shippedState.addTransition(completeTransition);// 设置初始状态SCXML scxml = new SCXML();scxml.setInitialstate(newState);scxml.addState(newState);scxml.addState(paidState);scxml.addState(shippedState);scxml.addState(completedState);// 初始化状态机执行器this.executor = new SCXMLExecutor();this.executor.setStateMachine(scxml);this.executor.go();}// 触发事件的方法public void fireEvent(String event) throws ModelException {this.executor.triggerEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT));}// 获取当前状态public String getCurrentState() {return this.executor.getStatus().getStates().iterator().next().getId();}
}

这段代码中,小黑创建了一个订单状态机。它包含四个状态,通过定义转换来控制状态的变化。这样一来,咱们就可以根据不同的事件(比如支付、发货等)来改变订单的状态了。

通过这个例子,咱们可以看到,状态机其实就是一种把复杂流程图变成代码的工具。它可以帮助咱们清晰地管理程序的各种状态,让代码既简洁又易于理解。

第4章:初始化状态机

假设咱们要创建一个简单的流程控制,比如一个简单的任务流程,它有“开始”、“进行中”和“完成”这几个状态。

首先,小黑要定义状态机的SCXML文件。创建一个名为task-state-machine.scxml的文件,内容如下:

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"initial="开始"><state id="开始"><transition event="开始任务" target="进行中"/></state><state id="进行中"><transition event="完成任务" target="完成"/></state><state id="完成"/>
</scxml>

这个文件定义了三个状态:开始、进行中和完成,并且定义了从“开始”到“进行中”以及从“进行中”到“完成”的转换。

然后,在Java代码中加载这个SCXML文件。小黑这里用一个简单的方法来演示:

import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.model.*;
import org.apache.commons.scxml2.io.SCXMLReader;import java.io.File;public class TaskStateMachine {private SCXMLExecutor executor;public TaskStateMachine() throws Exception {// 读取SCXML文件SCXML stateMachine = SCXMLReader.read(new File("path/to/task-state-machine.scxml"));// 初始化状态机this.executor = new SCXMLExecutor();this.executor.setStateMachine(stateMachine);this.executor.go();}// 触发事件public void fireEvent(String event) throws ModelException {this.executor.triggerEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT));}// 获取当前状态public String getCurrentState() {return this.executor.getStatus().getStates().iterator().next().getId();}// 主函数,用于测试public static void main(String[] args) throws Exception {TaskStateMachine taskStateMachine = new TaskStateMachine();System.out.println("当前状态: " + taskStateMachine.getCurrentState());taskStateMachine.fireEvent("开始任务");System.out.println("当前状态: " + taskStateMachine.getCurrentState());taskStateMachine.fireEvent("完成任务");System.out.println("当前状态: " + taskStateMachine.getCurrentState());}
}

在这段代码中,咱们创建了一个TaskStateMachine类,它可以加载SCXML文件来初始化状态机。然后,通过fireEvent方法来触发不同的事件,实现状态的转换。

第5章:设计状态机 - 把复杂的逻辑变简单

状态机设计的基本原则

设计状态机时,有几个原则要记住:

  1. 明确状态: 确定所有可能的状态,每个状态应该有明确的定义和边界。
  2. 定义转换: 明确状态之间如何转换,每个转换应该对应一个明确的事件。
  3. 避免过度复杂: 不要让状态机太复杂,否则会难以维护和理解。
实战演练:设计一个简单的工作流状态机

来吧,咱们用SCXML来设计一个简单的工作流状态机。这个状态机将有三个状态:待办进行中已完成。用户可以从待办状态开始任务,进入进行中,然后完成任务,到达已完成状态。

定义SCXML文件

首先,小黑得写一个SCXML文件来定义这个状态机。创建一个名为workflow-state-machine.scxml的文件,内容如下:

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"initial="待办"><state id="待办"><transition event="开始任务" target="进行中"/></state><state id="进行中"><transition event="完成任务" target="已完成"/></state><state id="已完成"/>
</scxml>

这个文件定义了状态机的各个状态和转换规则。从待办状态,当接收到开始任务事件时,转换到进行中状态;在进行中状态,当接收到完成任务事件时,转换到已完成状态。

在Java中加载和使用SCXML

接下来,小黑要在Java代码中加载这个SCXML文件,并使用它来管理状态。来看看具体怎么操作:

import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.model.*;
import org.apache.commons.scxml2.io.SCXMLReader;import java.io.File;public class WorkflowStateMachine {private SCXMLExecutor executor;public WorkflowStateMachine() throws Exception {// 读取SCXML文件SCXML stateMachine = SCXMLReader.read(new File("path/to/workflow-state-machine.scxml"));// 初始化状态机this.executor = new SCXMLExecutor();this.executor.setStateMachine(stateMachine);this.executor.go();}// 触发事件public void fireEvent(String event) throws ModelException {this.executor.triggerEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT));}// 获取当前状态public String getCurrentState() {return this.executor.getStatus().getStates().iterator().next().getId();}// 测试状态机public static void main(String[] args) throws Exception {WorkflowStateMachine workflowStateMachine = new WorkflowStateMachine();System.out.println("当前状态: " + workflowStateMachine.getCurrentState());workflowStateMachine.fireEvent("开始任务");System.out.println("当前状态: " + workflowStateMachine.getCurrentState());workflowStateMachine.fireEvent("完成任务");System.out.println("当前状态: " + workflowStateMachine.getCurrentState());}
}

在这个例子中,小黑创建了一个WorkflowStateMachine类来表示工作流状态机。它可以加载SCXML文件并根据事件来转换状态。

第6章:实现状态机逻辑 - 让代码动起来

状态转换与事件触发

状态机的核心就是状态的转换和事件的触发。咱们之前已经在SCXML文件里定义了状态和转换规则,现在就要在Java中实现这些转换的触发。

在小黑之前的例子中,已经展示了如何触发事件。现在咱们来看一个更实际的例子。假设有一个简单的用户认证流程,它包含未登录登录中登录成功登录失败这几个状态。咱们会根据用户的行为(比如输入用户名和密码)来触发状态转换。

编写SCXML文件

首先,定义SCXML文件authentication-state-machine.scxml

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"initial="未登录"><state id="未登录"><transition event="尝试登录" target="登录中"/></state><state id="登录中"><transition event="登录成功" target="登录成功"/><transition event="登录失败" target="登录失败"/></state><state id="登录成功"/><state id="登录失败"/>
</scxml>

这个文件定义了用户认证的状态机模型。

Java中的状态机逻辑实现

接下来,咱们在Java中加载这个状态机,并根据用户行为触发事件:

import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.model.*;
import org.apache.commons.scxml2.io.SCXMLReader;import java.io.File;public class AuthenticationStateMachine {private SCXMLExecutor executor;public AuthenticationStateMachine() throws Exception {// 读取SCXML文件SCXML stateMachine = SCXMLReader.read(new File("path/to/authentication-state-machine.scxml"));// 初始化状态机this.executor = new SCXMLExecutor();this.executor.setStateMachine(stateMachine);this.executor.go();}// 触发事件public void fireEvent(String event) throws ModelException {this.executor.triggerEvent(new TriggerEvent(event, TriggerEvent.SIGNAL_EVENT));}// 获取当前状态public String getCurrentState() {return this.executor.getStatus().getStates().iterator().next().getId();}// 模拟用户登录过程public void simulateUserLogin(String username, String password) {System.out.println("用户正在尝试登录...");fireEvent("尝试登录");// 这里只是一个简单的示例,实际应用中应该有更复杂的逻辑if ("admin".equals(username) && "123456".equals(password)) {System.out.println("登录成功!");fireEvent("登录成功");} else {System.out.println("登录失败!");fireEvent("登录失败");}}// 测试状态机public static void main(String[] args) throws Exception {AuthenticationStateMachine authStateMachine = new AuthenticationStateMachine();System.out.println("当前状态: " + authStateMachine.getCurrentState());authStateMachine.simulateUserLogin("admin", "123456");System.out.println("当前状态: " + authStateMachine.getCurrentState());}
}

在这个例子中,咱们创建了一个AuthenticationStateMachine类,用来处理用户认证的状态机。这个类可以根据用户的登录尝试来触发不同的事件,从而改变状态机的状态。

第7章:高级功能与技巧

并行状态的使用

在某些情况下,咱们可能需要状态机同时处于多个状态,这就是并行状态。比如,在一个复杂的业务流程中,可能同时需要跟踪订单的状态和客户的满意度,这两个状态是独立的,可以同时存在。

SCXML中定义并行状态

在SCXML中,咱们可以使用<parallel>元素来定义并行状态。来看一个例子:

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"initial="订单处理"><state id="订单处理"><parallel><state id="订单状态"><state id="新建"/><state id="处理中"/><state id="完成"/></state><state id="客户满意度"><state id="未评价"/><state id="满意"/><state id="不满意"/></state></parallel></state>
</scxml>

这个SCXML文件定义了一个“订单处理”的并行状态机,它同时跟踪“订单状态”和“客户满意度”两个独立的状态。

历史状态的运用

历史状态是另一个有用的功能,它可以让状态机记住之前的状态。这在需要返回到之前状态的场景中非常有用,比如用户在一个复杂表单的多个步骤之间来回切换。

SCXML中定义历史状态

在SCXML中,可以使用<history>元素来定义历史状态。来看一个例子:

<scxml xmlns="http://www.w3.org/2005/07/scxml" version="1.0"initial="步骤一"><state id="步骤一"><transition event="下一步" target="步骤二"/></state><state id="步骤二"><history id="历史状态"/><transition event="返回" target="历史状态"/><transition event="下一步" target="步骤三"/></state><state id="步骤三"><transition event="返回" target="步骤二"/></state>
</scxml>

这个例子定义了一个包含历史状态的简单流程。当用户从“步骤二”返回时,状态机会记住之前的状态(“步骤一”或“步骤三”),并据此恢复。

Java中实现高级功能

有了SCXML的定义后,咱们还需要在Java代码中实现相应的逻辑。由于篇幅限制,这里就不详细展开了,但小黑可以给出个大概的指导:

  • 并行状态: 你需要在Java中分别管理每个并行状态的转换和事件。
  • 历史状态: 你可以利用SCXMLExecutor的状态管理功能来记录和恢复历史状态。

第8章:总结

状态机的优势
  • 清晰的逻辑: 状态机让复杂的状态转换和条件判断变得清晰可视。
  • 易于维护: 随着项目的扩展,状态机更易于维护和修改。
  • 减少错误: 明确的状态和转换规则有助于减少逻辑错误。

通过这个案例,咱们可以看到,状态机不仅仅是理论上的概念,在实际的开发工作中它能大显身手,特别是在处理复杂逻辑和流程时。从一个简单的状态转换到整个系统的状态管理,状态机都能提供清晰、高效的解决方案。

相关文章:

使用Apache Commons SCXML实现状态机管理

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;咱们程序员在开发过程中&#xff0c;经常会遇到需要管理不同状态和状态之间转换的场景。比如&#xff0c;一个在线购物的订单&#xff0c;它可能有“新建订单”、“已支付”、“配送中”、“已完成”等状态。在这…...

大数据技术原理与应用期末考试题

大数据技术原理与应用期末考试题 一、单选题 1.下面哪个选项属于大数据技术的“数据存储和管理”技术层面的功能? A、利用分布式文件系统、数据仓库、关系数据库等实现对结构化、半结构化和非结构化海量数据的存储和管理 B、利用分布式并行编程模型和计算框架,结合机器学习…...

解决jenkins的Exec command命令不生效,或者执行停不下来的问题

Jenkins构建完后将war包通过 Publish Over SSH 的插件发布到服务器上&#xff0c;在服务器上执行脚本时&#xff0c;脚本中的 nohup 命令无法执行&#xff0c;并不生效&#xff0c;我配置的Exec command命令是后台启动一个war包&#xff0c;并输出日志文件。 nohup java -jar /…...

【PHP】json_decode的第二个参数是什么意思

json_decode() 函数的第二个参数 $associative 是一个布尔值&#xff0c;用于控制 JSON 对象在 PHP 中的解码方式。当将其设置为 true 时&#xff0c;JSON 对象将被解码为关联数组&#xff1b;当设置为 false 时&#xff0c;JSON 对象将被解码为 stdClass 对象。默认值为 false…...

学生公寓安全用电管理系统应用案例

摘要&#xff1a;安全用电是学校公寓用电管理的首要任务&#xff0c;这就需要对一些恶性负载进行识别和控制&#xff0c;同时为了减少电工和后期管理人员的成本&#xff0c;引进了安全用电管理系统。本文在在描述了安全用电管理系统的工作原理和利用智能电表可实现的功能后,阐明…...

python实现简易的flask后端接口

先安装插件pip install flask 新建py脚本文件编码&#xff1a; # -*- coding: utf-8 -*- from flask import Flask from flask_cors import CORS # 跨域依赖&#xff0c;通过pip install flask-cors安装app Flask(__name__) cors CORS(app) # 跨域设置&#xff0c;这样设置…...

CSDN质量分批量查询

单个文章质量分查询地址&#xff08;点击右边地址&#xff09;&#xff1a; CSDN质量分查询 创作者身份认证审核标准 优质创作者申请条件&#xff1a; 粉丝数在5000以上近30日&#xff08;申请日算起&#xff09;原创文章数不少于4篇原创博文总数不少于100篇垂直领域原创数量…...

【MPC学习笔记】01:MPC简介(Lecture 1_1 Unconstrained MPC)

本笔记来自北航诸兵老师的课程 课程地址&#xff1a;模型预测控制&#xff08;2022春&#xff09;lecture 1-1 Unconstrained MPC 文章目录 0 MPC 简介0.1 案例引入0.2 系统模型0.3 MPC的优点0.4 MPC的缺点0.5 MPC的未来 1 详细介绍 0 MPC 简介 0.1 案例引入 MPC&#xff08;…...

c语言结构体学习上篇

文章目录 前言一、结构体的声明1&#xff0c;什么叫结构体?2&#xff0c;结构体的类型3,结构体变量的创建和初始化4&#xff0c;结构体的类型5&#xff0c;结构体的初始化 二、结构体的访问1&#xff0c;结构体成员的点操作符访问2&#xff0c;结构体体成员的指针访问 前言 昨…...

Linux: eBPF: bcc-tools:tcpdrop使用需要注意的问题

最近使用bcc-tools的时候注意到,bcc-tools(eBPF相关软件)的使用版本和内核的版本紧密程度非常高。因为要使用内核的函数或者结构体,所以就必须版本一致是必须的,不然会出现下面的警告或者错误: WARNING: tcp_drop() kernel function not found or traceable. The kernel …...

AI:113-基于卷积神经网络的图像风格迁移

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…...

15、Kubernetes核心技术 - 探针

目录 一、概述 二、探针类型 2.1、就绪探针&#xff08;Readiness Probe&#xff09; 2.2、存活探针&#xff08;Liveness Probe&#xff09; 三、探针探测方法 3.1、exec 3.2、httpGet 3.3、tcpSocket 四、探针配置项 五、探针使用 5.1、就绪探针&#xff08;Readin…...

GTK4 环境配置

1 安装gtk4包裹: # sudo yum install gtk4 gtk4-devel gtk4-devel-docs devhelp glib2 glib2-devel glib2-doc 2 安装 glade 4 git clone https://github.com/ag-python/cambalache.git 记住 把软件目录 复制到 一个你不会移动删除的地方(千万别删除这个软件文件夹 因为运行…...

Yolov8部署——segmentation部署以及批量推理

Yolov8部署——segmentation部署以及批量推理 参考:在windows上部署Yolov8主要参考下面两个仓库&#xff0c;https://github.com/xunzixunzi/tensorrt-cpp-api和https://github.com/xunzixunzi/YOLOv8-TensorRT-CPP&#xff0c;代码说是适合批量处理&#xff0c;但是代码中是以…...

再见2023,你好2024!

大家好&#xff0c;我是老三&#xff0c;本来今天晚上打算出去转一转&#xff0c;陆家嘴打车实在太艰难了&#xff0c;一公里多的路&#xff0c;司机走了四十分钟&#xff0c;还没到&#xff0c;再加上身体不适&#xff0c;咳嗽地比较厉害&#xff0c;所以还是宅在酒店里&#…...

【计算机毕业设计】SSM二手交易网站

项目介绍 该项目分为前后台&#xff0c;前台普通用户角色&#xff0c;后台管理员角色。 管理员主要功能如下&#xff1a; 登陆,商品分类管理,商品管理,商品订单管理,用户管理等功能。 用户角色主要功能如下&#xff1a; 包含以下功能&#xff1a;查看所有商品,用户登陆注册…...

纠删码ReedSolomon

随着大数据技术的发展&#xff0c;HDFS作为Hadoop的核心模块之一得到了广泛的应用。为了数据的可靠性&#xff0c;HDFS通过多副本机制来保证。在HDFS中的每一份数据都有两个副本&#xff0c;1TB的原始数据需要占用3TB的磁盘空间&#xff0c;存储利用率只有1/3。而且系统中大部分…...

C++音视频开发技巧汇总(持续更新)

1.录制PCM数据 有时候我们需要录制PCM数据到文件以测试录制数据是否正确&#xff0c;一般可以使用以下代码实现&#xff1a; FILE *pf; fopen_s(&pf, "rec.pcm", "wb"); fwrite(myPcmArr, 1, outBufferLen, pf); 录制pcm文件后可以使用Audacity来导…...

4462 4.曙曙献爱心

#include<bits/stdc.h> using namespace std; int n,m,k; int a[1001]; int s[1001]; int f[1001][1001];//f[i][j]&#xff0c;i个警察&#xff0c;j个点&#xff0c;能管理的最大人数 int main(){cin>>n>>m>>k;for(int i1;i<n;i){cin>>a[i…...

浅谈命令模式

命令模式是一种行为设计模式&#xff0c;用于将一个请求封装成一个对象&#xff0c;从而使得请求的发送者和接收者解耦&#xff0c;并支持对请求进行参数化、队列化、撤销和重做等操作。 在命令模式中&#xff0c;有一下介个关键角色&#xff1a; Command&#xff08;命令&am…...

Leetcode 3576. Transform Array to All Equal Elements

Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接&#xff1a;3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到&#xf…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

Java 8 Stream API 入门到实践详解

一、告别 for 循环&#xff01; 传统痛点&#xff1a; Java 8 之前&#xff0c;集合操作离不开冗长的 for 循环和匿名类。例如&#xff0c;过滤列表中的偶数&#xff1a; List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版​分享

平时用 iPhone 的时候&#xff0c;难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵&#xff0c;或者买了二手 iPhone 却被原来的 iCloud 账号锁住&#xff0c;这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...

django filter 统计数量 按属性去重

在Django中&#xff0c;如果你想要根据某个属性对查询集进行去重并统计数量&#xff0c;你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求&#xff1a; 方法1&#xff1a;使用annotate()和Count 假设你有一个模型Item&#xff0c;并且你想…...

抖音增长新引擎:品融电商,一站式全案代运营领跑者

抖音增长新引擎&#xff1a;品融电商&#xff0c;一站式全案代运营领跑者 在抖音这个日活超7亿的流量汪洋中&#xff0c;品牌如何破浪前行&#xff1f;自建团队成本高、效果难控&#xff1b;碎片化运营又难成合力——这正是许多企业面临的增长困局。品融电商以「抖音全案代运营…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Ascend NPU上适配Step-Audio模型

1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统&#xff0c;支持多语言对话&#xff08;如 中文&#xff0c;英文&#xff0c;日语&#xff09;&#xff0c;语音情感&#xff08;如 开心&#xff0c;悲伤&#xff09;&#x…...