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

EventListener与EventBus

EventListener

JDK

JDK1.1开始就提供EventListener,一个标记接口,源码如下:

/*** A tagging interface that all event listener interfaces must extend.*/
public interface EventListener {
}

JDK提供的java.util.EventObject

public class EventObject implements Serializable {protected transient Object source;
}

用户需要定义继承自EventObject的事件对象,然后定义具体的Listener接口继承EventListener。事件源通过添加监听器(addXXXListener方法)手动管理事件的订阅和发布,需要用户手动调用监听器的回调方法,事件管理逻辑往往由开发者编码完成。

典型场景:主要用于早期GUI应用开发(如AWT和Swing),用于组件间的事件通信。

优点:轻量级,易于理解;适合简单场景或单一模块。

缺点:

  • 需显式注册和管理事件监听器,手动处理事件流转,容易导致代码复杂度增加;
  • 缺乏高级特性,如事件异步处理、条件过滤等。

Spring

@EventListener

当在实现某些特定业务逻辑时,通常可通过发送事件的方式实现解耦,这也是观察者模式的一种体现。从Spring 4.2开始提供注解@EventListner,不再需要单独编写监听器类,只需在Spring Bean方法上标记@EventListener即可。

源码如下:

@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface EventListener {@AliasFor("classes")Class<?>[] value() default {};@AliasFor("value")Class<?>[] classes() default {};String condition() default "";
}

解读:

  • value和classes:作用相同,表示监听的一个或一组事件,用于支持方法中同一个父类的事件;
  • condition:支持Spring EL表达式,用来做Event中的变量或者方法判断。

Event的整个生命周期,从Publisher发出,经过applicationContext容器通知到EventListener,都是发生在单个Spring容器中。

事件可直接使用ApplicationEvent,或继承它。源码如下:

public abstract class ApplicationEvent extends java.util.EventObject {// 事件发生时间private final long timestamp;public ApplicationEvent(Object source) {super(source);this.timestamp = System.currentTimeMillis();}public ApplicationEvent(Object source, Clock clock) {super(source);this.timestamp = clock.millis();}
}
示例

多个监听器,监听Account创建,完成不同的业务逻辑。

创建Event事件监听

/*** 账号监听,处理账号创建成功的后续逻辑*/
@Component
public class AccountListener {@EventListener@Asyncpublic void processAccountCreatedEvent1(AccountCreatedEvent event) {// 1. 发送邮件、短信}@EventListener@Order(100)public void processAccountCreatedEvent2(AccountCreatedEvent event) {// 2. 添加积分等,@Order(100)用来设定执行顺序}
}

使用ApplicationEventPublisher发送事件:

@Autowired
private ApplicationEventPublisher publisher;public boolean save(Account account) {// 数据库保存成功if (true) {publisher.publishEvent(new AccountCreatedEvent(account));}return false;
}

一个发布者可对应多个监听者:

@EventListener(value = {AccountCreatedEvent.class, AccountUpdatedEvent.class}, condition = "#event.account.age > 10")
public void processAccountCreatedEvent2(AccountEvent event) {// 业务逻辑
}

监听执行顺序:可使用@Order(100)来标记事件的执行顺序,异步情况下只保证按顺序将监听器丢入进线程池,具体执行顺序得看线程。

监听异步执行:使用@Async标记即可,前提条件:使用@EnableAsync开启Spring异步。

优点:

  • 更加简洁,方法注解即声明监听;
  • 支持异步处理,条件过滤,功能更强大;
  • 与其他Spring特性(如AOP和事务)集成更好。

缺点:

  • 不如ApplicationListener明确(可能难以追踪监听器逻辑);
  • 依赖注解,可能不适合部分代码风格偏向接口设计的团队。

ApplicationListener

Spring提供两种事件监听机制:

  • 基于@EventListener注解:
  • 基于ApplicationListener泛型接口:早期提供,实现onApplicationEvent方法

通过上下文来发布一个事件,监听器收到订阅的事件作相应的处理,Spring提供的方便高效的事件驱动模型。

ApplicationListener源码:

@FunctionalInterface
public interface ApplicationListener<E extends ApplicationEvent> extends java.util.EventListener {void onApplicationEvent(E event);default boolean supportsAsyncExecution() {return true;}static <T> ApplicationListener<PayloadApplicationEvent<T>> forPayload(Consumer<T> consumer) {return event -> consumer.accept(event.getPayload());}}

简单使用:

@Component
public class MyEventListener implements ApplicationListener<MyEvent> {@Overridepublic void onApplicationEvent(MyEvent event) {System.out.println("Received event: " + event.getMessage());}
}

优点:

  • 明确,适合固定、简单的监听逻辑;
  • 提供对所有事件的统一入口,可基于事件类型实现复杂的分发逻辑。

缺点:

  • 相对冗长,代码侵入性高(必须实现接口);
  • 不支持直接使用条件过滤和异步处理;
  • 扩展性和灵活性低。

@EventListener与ApplicationListener

特性ApplicationListener@EventListener
定义方式实现ApplicationListener接口使用@EventListener注解
写法复杂度必须实现接口注解方式更简洁
类型绑定泛型绑定到特定事件类型自动通过方法参数类型推断
条件过滤不支持支持(condition属性)
异步处理需手动实现多线程支持@Async开箱即用
事务集成支持,但需手动配置与Spring的事务注解自然集成
适用场景简单、固定事件监听逻辑更现代化、复杂事件管理逻辑
引入版本早期版本已有Spring 4.2+

JDK与Spring

特性JDK EventListenerSpring @EventListener
触发方式显式调用监听器基于事件发布自动触发
实现方式通过接口通过注解声明
事件管理手动注册、调用自动管理(基于Spring容器)
适用场景简单GUI或模块内部通信企业级应用、跨模块解耦
异步支持不支持支持
条件过滤不支持支持
事务集成不支持支持
复杂性简单,手动管理较高,但更自动化和灵活

EventBus

使用异步的方式来发送事件,或触发另外一个动作,即Publish/Subscribe Event。

EventBus有不同的实现框架,一般都指Guava EventBus。

框架

Guava EventBus包路径下:
在这里插入图片描述
类之间的关系如:
在这里插入图片描述
EventBus组成部分:

  1. EventBus、AsyncEventBus:事件发送器
  2. Event:事件承载单元
  3. SubscriberRegistry:订阅者注册器,将订阅者注册到Event上,即将有注解Subscribe的方法和Event绑定起来
  4. Dispatcher:事件分发器,将事件的订阅者调用来执行
  5. Subscriber、SynchronizedSubscriber:订阅者,并发订阅还是同步订阅

原理

EventBus是基于注册监听的方式来运行的,首先需将EventBus实例化,然后才会有事件及监听者:

// 同步
EventBus eventBus = new EventBus();

注册监听者,底层就是将类eventListener中所有注解有Subscribe的方法与其Event对放在一个map中(一个Event可以对应多个Subscribe的方法):

eventBus.register(eventListener);

在高并发的环境下使用AsyncEventBus时,发送事件可能会出现异常,因为它使用的线程池,当线程池的线程不够用时,会拒绝接收任务,就会执行线程池的拒绝策略,如果需要关注是否提交事件成功,就需要将线程池的拒绝策略设为抛出异常,并且try-catch来捕获异常:

try {eventBus.post(new LoginEvent("user", "pass"));
} catch (Exception e) {// log
}

内部的订阅通知模型,无需使用事件+事件listener模型,只有一个事件类。

示例

一个简单的实例,值得一提的是,注册和发布事件,与消费事件不在一个类里:

// 事件类中方法以@Subscribe注解
class EventBusChangeRecorder {@Subscribepublic void recordCustomerChange(ChangeEvent e) {// 业务逻辑System.out.println("事件触发");}
}
// 创建事件总线
EventBus eventBus = new EventBus();
// 注册事件
eventBus.register(new EventBusChangeRecorder());
ChangeEvent event = new ChangeEvent(new EventBusChangeRecorder());
// 发布事件
eventBus.post(event);
// 需要异步执行可使用EventBus的子类AsyncEventBus

另外,EventBus也可作为Spring Bean使用,可被注入:

@Service
public class TestService implements InitializingBean {@Resourceprivate MyListener myListener;@Resourceprivate EventBus eventBus;public void postEvent() {eventBus.post(new LoginEvent("johnny", "success"));}@Overridepublic void afterPropertiesSet() throws Exception {eventBus.register(myListener);}
}

源码

EventBus的register方法:

void register(Object listener) {Multimap<Class<?>, Subscriber> listenerMethods = findAllSubscribers(listener);for (Entry<Class<?>, Collection<Subscriber>> entry : listenerMethods.asMap().entrySet()) {Class<?> eventType = entry.getKey();Collection<Subscriber> eventMethodsInListener = entry.getValue();CopyOnWriteArraySet<Subscriber> eventSubscribers = subscribers.get(eventType);if (eventSubscribers == null) {CopyOnWriteArraySet<Subscriber> newSet = new CopyOnWriteArraySet<>();eventSubscribers = MoreObjects.firstNonNull(subscribers.putIfAbsent(eventType, newSet), newSet);}eventSubscribers.addAll(eventMethodsInListener);}
}

事件发送:执行指定事件类型的订阅者(包含method),从订阅者中获取指定事件的订阅者,然后按照规则(同步、异步)执行指定的方法,如果事件没有监听者,就当作死亡事件来对待。EventBus的post方法:

public void post(Object event) {Iterator<Subscriber> eventSubscribers = subscribers.getSubscribers(event);if (eventSubscribers.hasNext()) {dispatcher.dispatch(event, eventSubscribers);} else if (!(event instanceof DeadEvent)) {// the event had no subscribers and was not itself a DeadEventpost(new DeadEvent(this, event));}
}

EventBus的dispatcher为PerThreadQueuedDispatcher,其dispatch方法如下:

@Override
void dispatch(Object event, Iterator<Subscriber> subscribers) {checkNotNull(event);checkNotNull(subscribers);Queue<Event> queueForThread = queue.get();queueForThread.offer(new Event(event, subscribers));if (!dispatching.get()) {dispatching.set(true);try {Event nextEvent;while ((nextEvent = queueForThread.poll()) != null) {while (nextEvent.subscribers.hasNext()) {nextEvent.subscribers.next().dispatchEvent(nextEvent.event);}}} finally {dispatching.remove();queue.remove();}}
}

dispatchEvent方法:

// Dispatches event to this subscriber using the proper executor.
final void dispatchEvent(final Object event) {executor.execute((Runnable) () -> {try {invokeSubscriberMethod(event);} catch (InvocationTargetException e) {bus.handleSubscriberException(e.getCause(), context(event));}});
}

execute方法由Executor来执行。EventBus的executor为MoreExecutors.directExecutor()

public static Executor directExecutor() {return DirectExecutor.INSTANCE;
}enum DirectExecutor implements Executor {INSTANCE;@Overridepublic void execute(Runnable command) {command.run();}
}

其execute方法直接执行线程的run方法,即同步调用run方法。另外,invokeSubscriberMethod方法如下:

void invokeSubscriberMethod(Object event) throws InvocationTargetException {try {method.invoke(target, checkNotNull(event));} catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {// 省略catch代码}
}

因此,整个执行过程如下:
在这里插入图片描述
整个过程都是同步方式执行,EventBus是同步的。

AsyncEventBus

AsyncEventBus是异步EventBus,其dispatcher为LegacyAsyncDispatcher,executor为自己指定的线程池,如

@Configuration
public class ConfigBean {@Beanpublic EventBus executorService() {BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(20);ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 20, 30, TimeUnit.SECONDS, workQueue);return new AsyncEventBus(executor);}
}

运行流程如下:
在这里插入图片描述

AllowConcurrentEvents

Guava提供的注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@ElementTypesAreNonnullByDefault
public @interface AllowConcurrentEvents {
}

注解判断逻辑位于Subscriber.isDeclaredThreadSafe方法内:

private static boolean isDeclaredThreadSafe(Method method) {return method.getAnnotation(AllowConcurrentEvents.class) != null;
}

此方法被create()方法调用:

static Subscriber create(EventBus bus, Object listener, Method method) {return isDeclaredThreadSafe(method)? new Subscriber(bus, listener, method): new SynchronizedSubscriber(bus, listener, method);
}

解读:如果订阅者方法上有注解@AllowConcurrentEvents,则返回Subscriber(异步),否则,返回SynchronizedSubscriber(同步)。即没有使用注解AllowConcurrentEvents的订阅者,在并发环境中是串行执行,会影响性能。

SynchronizedSubscriber是同步的,从其类名可知,从其实现的invokeSubscriberMethod方法里也可看出:

@Override
void invokeSubscriberMethod(Object event) throws InvocationTargetException {synchronized (this) {super.invokeSubscriberMethod(event);}
}

拓展

EventListener和EventBus

相同点:都是基于事件驱动模式,都可用于实现解耦的组件通信。

不同点:

  • 功能:
    • EventListener:订阅事件并执行操作的组件;粒度更细,聚焦于局部业务逻辑;一般是自定义类或方法,绑定到特定事件类型;
    • EventBus:管理事件的发布、订阅、流转;侧重于全局管理事件,通常是单例模式或共享对象。
  • 实现方式:
    • EventListener:Spring的@EventListener是一种更广义的事件监听机制,可配合ApplicationEvent或自定义事件;
    • EventBus:Guava EventBus通过注解定义事件处理器,自动绑定到特定事件类型。

联系:EventListener通常依赖EventBus进行注册,接收由EventBus发布的事件。

EventBus对比MQ

特性EventBusMQ
使用范围单JVM跨进程、分布式
通信模式内存中发布-订阅发布-订阅、点对点
可靠性无内置持久化或重试机制支持持久化、重试、消息确认
延迟低延迟相对稍高(取决于网络和队列机制)
复杂性简单,适合轻量场景较高,需要额外运维

Guava EventBus现状

  • 局限性:
    基于内存的轻量级工具,仅适用于单JVM内的事件管理;在分布式跨服务场景下,无法满足可靠性、持久性和扩展性要求。
  • 依然适用的场景:
    • 轻量化需求:在小型项目中,快速实现解耦的优秀选择;
    • 单JVM内部事件管理:用于模块间事件流转(如前端事件或服务内异步操作);
    • 开发测试:在测试环境中模拟事件驱动的逻辑。

Netflix EventBus

除了Guava EventBus外,Netflix也提供一套框架:

<dependency><groupId>com.netflix.netflix-commons</groupId><artifactId>netflix-eventbus</artifactId><version>0.3.0</version>
</dependency>

参考

  • EventBus原理深度解析

相关文章:

EventListener与EventBus

EventListener JDK JDK1.1开始就提供EventListener&#xff0c;一个标记接口&#xff0c;源码如下&#xff1a; /*** A tagging interface that all event listener interfaces must extend.*/ public interface EventListener { }JDK提供的java.util.EventObject&#xff1…...

Facebook为什么注册失败了?该怎么解决?

有时候用户在尝试注册Facebook账号时可能会遇到各种问题&#xff0c;导致注册失败或遇到困难。小编会为大家分析Facebook注册失败的可能原因&#xff0c;并提供解决方法&#xff0c;帮助大家顺利完成注册流程。 一、Facebook注册失败的可能原因 1. 账号信息问题&#xff1a; …...

前端数据可视化思路及实现案例

目录 一、前端数据可视化思路 &#xff08;一&#xff09;明确数据与目标 &#xff08;二&#xff09;选择合适的可视化图表类型 &#xff08;三&#xff09;数据与图表的绑定及交互设计 &#xff08;四&#xff09;页面布局与样式设计 二、具体案例&#xff1a;使用 Ech…...

【DVWA】Brute Force暴力破解实战

问尔辈 何等样人 自摸心头 再来求我&#xff1b;若汝能 克存忠孝 持身正直 不拜何妨 1.Brute Force(Low) 相关的代码分析 if( isset( $_GET[ Login ] ) ) {// Get username$user $_GET[ username ];// Check the database$query "SELECT * FROM users WHERE user $…...

23种设计模式速记法

前言 在软件开发的过程中&#xff0c;设计模式作为解决常见问题的通用模板&#xff0c;一直是开发者的重要工具。尤其是在面临复杂系统架构和需求变化时&#xff0c;设计模式不仅能够提升代码的可复用性和扩展性&#xff0c;还能大大提高团队之间的协作效率。然而&#xff0c;…...

第7章硬件测试-7.3 功能测试

7.3 功能测试 7.3.1 整机规格测试7.3.2 整机试装测试7.3.3 DFX测试 功能测试包括整机规格、整机试装和整机功能测试&#xff0c;是整机结构和业务相关的测试。 7.3.1 整机规格测试 整机规格测试包括尺寸、重量、温度、功耗等数据。这些测试数据与设计规格进行比对和校验&…...

动态规划子数组系列一>等差数列划分

题目&#xff1a; 解析&#xff1a; 代码&#xff1a; public int numberOfArithmeticSlices(int[] nums) {int n nums.length;int[] dp new int[n];int ret 0;for(int i 2; i < n; i){dp[i] nums[i] - nums[i-1] nums[i-1] - nums[i-2] ? dp[i-1]1 : 0;ret dp[i…...

《Python浪漫的烟花表白特效》

一、背景介绍 烟花象征着浪漫与激情&#xff0c;将它与表白结合在一起&#xff0c;会创造出别具一格的惊喜效果。使用Python的turtle模块&#xff0c;我们可以轻松绘制出动态的烟花特效&#xff0c;再配合文字表白&#xff0c;打造一段专属的浪漫体验。 接下来&#xff0c;让…...

什么是RESTful API,有什么特点

RESTful API 概述 什么是 RESTful API&#xff1f; RESTful API 是基于 Representational State Transfer&#xff08;表现层状态转移&#xff09;架构风格的 Web 服务接口。REST 是一种设计风格&#xff0c;而不是具体的协议或标准。它定义了一组约束和最佳实践&#xff0c;…...

友思特新闻 | 友思特荣获广州科技创新创业大赛智能装备行业赛初创组优胜企业!

2024年11月19日&#xff0c;第十三届中国创新创业大赛&#xff08;广东广州赛区&#xff09;暨2024年广州科技创新创业大赛智能装备行业赛颁奖典礼隆重举行。 赛事奖项介绍&#xff1a;广州科技创新创业大赛智能装备行业赛 第十三届“中国创新创业大赛&#xff08;广东广州赛区…...

CSS中calc语法不生效

问题起因 在使用calc时发现无法生效&#xff0c;写法是&#xff1a; height:calc(100vh-100px);页面无效果&#xff0c;加空格后就发现有效果了&#xff1a; height:calc(100vh - 100px);这是为什么&#xff1f; calc是什么&#xff1f; css3 的计算属性&#xff0c;用于动态…...

国标GB28181视频平台EasyCVR视频融合平台H.265/H.264转码业务流程

在当今数字化、网络化的视频监控领域&#xff0c;大中型项目对于视频监控管理平台的需求日益增长&#xff0c;特别是在跨区域、多设备、高并发的复杂环境中。EasyCVR视频监控汇聚管理平台正是为了满足这些需求而设计的&#xff0c;它不仅提供了全面的管理功能&#xff0c;还支持…...

ES6 模板字符串详解

ES6 模板字符串详解 ES6&#xff08;ECMAScript 6&#xff09;引入了模板字符串&#xff08;Template Literals&#xff09;&#xff0c;这是一种新的字符串字面量语法&#xff0c;使用反引号&#xff08;&#xff09;来定义字符串。模板字符串不仅支持多行字符串&#xff0c;…...

浏览器插件启动本地程序

浏览器插件支持启动本地程序&#xff0c;且支持win、mac、linux多个平台&#xff0c;使用的是nativeMessaging。nativeMessaging官方api说明。nativeMessaging支持启动本地程序且进行通信。 我们直接拿官方提供的例子进行说明&#xff0c;github地址。 以win为例 1、添加注册…...

Ubuntu ESP32开发环境搭建

文章目录 ESP32开发环境搭建安装ESP-IDF搭建一个最小工程现象 ESP32开发环境搭建 最近有个小项目需要用到能够联网的mcu驱动&#xff0c;准备玩玩esp的芯片&#xff0c;记录下ESP32开发环境搭建的过程。 ESP-IDF 是乐鑫科技为其 ESP32 系列芯片提供的官方开发框架。这个框架主…...

【gitlab】部署

直接RPM安装 部署的方式是&#xff1a;使用外部的nginx作为代理&#xff0c;使用https方式。 1、下载安装文件 gitlab-ce-17.0.3-ce.0.el7.x86_64.rpm 2、安装 yum install gitlab-ce-17.0.3-ce.0.el7.x86_64.rpm 或者安装yum源在线安装: 添加镜像源&#xff1a;新建 /et…...

vue中路由缓存

vue中路由缓存 问题描述及截图解决思路关键代码及打印信息截图 问题描述及截图 在使用某一平台时发现当列表页码切换后点击某一卡片进入详情页后&#xff0c;再返回列表页时页面刷新了。这样用户每次看完详情回到列表页都得再重新输入自己的查询条件&#xff0c;或者切换分页到…...

Github 2024-11-18 开源项目周报 Top15

根据Github Trendings的统计,本周(2024-11-18统计)共有15个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Python项目8TypeScript项目4Jupyter Notebook项目2Go项目2Shell项目1OpenHands: 人工智能驱动的软件开发代理平台 创建周期:195 天开发语言:P…...

GRCNN使用onnxruntime和tensorrt推理

下载GRCNN项目&#xff1a;https://github.com/skumra/robotic-grasping.git 导出onnx模型&#xff1a; import torchnet torch.load("trained-models/jacquard-rgbd-grconvnet3-drop0-ch32/epoch_42_iou_0.93") x torch.rand(1, 4, 300, 300).cuda() torch.onnx.…...

java中的this关键字

&#x1f389;&#x1f389;&#x1f389;欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的技术是JavaScript与Vue.目前正在往全栈方向前进, 如果我的博客给您带来了帮助欢迎您关注我,我将会持续不断的更新文章!!!&#x1f64f;&#x1f64f;&#x1f64f; 文章目录…...

Easyexcel(3-文件导出)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09; 响应头设置 通过设置文件导出的响应头&#xff0c;可以自定义文件导出的名字信息等 //编码格式为UTF-8 response.setC…...

iOS应用网络安全之HTTPS

移动互联网开发中iOS应用的网络安全问题往往被大部分开发者忽略, iOS9和OS X 10.11开始Apple也默认提高了安全配置和要求. 本文以iOS平台App开发中对后台数据接口的安全通信进行解析和加固方法的分析. 1. HTTPS/SSL的基本原理 安全套接字层 (Secure Socket Layer, SSL) 是用来…...

openharmony napi调试笔记

一、动态库的编译 使用的编译环境是ubuntu20.04 1、使用vscode配置openharmony sdk交叉编译环境 首先下载openharmony的sdk&#xff0c;如native-linux-x64-4.1.7.5-Release.zip 解压后native目录下就是交叉编译用的sdk 在要编译的源代码目录下新建.vscode目录&#xff0c…...

springboot基于微信小程序的农产品交易平台

摘 要 随着网络科技的发展&#xff0c;利用小程序对基于微信小程序的农产品交易平台进行管理已势在必行&#xff1b;该系统将能更好地理解用户需求&#xff0c;优化基于微信小程序的农产品交易平台策略&#xff0c;提高基于微信小程序的农产品交易平台效率和质量。本文讲述了基…...

Spring Boot 注解

Spring Boot 是基于 Spring 框架的开发框架&#xff0c;提供了许多注解来简化配置和开发。以下是一些常见的 Spring Boot 注解&#xff0c;包括它们的作用和简单介绍&#xff1a; 1. SpringBootApplication 作用&#xff1a;标识一个 Spring Boot 应用的入口点。它是一个组合…...

P8692 [蓝桥杯 2019 国 C] 数正方形:结论,组合数学

题目描述 在一个 NNNN 的点阵上&#xff0c;取其中 44 个点恰好组成一个正方形的 44 个顶点&#xff0c;一共有多少种不同的取法&#xff1f; 由于结果可能非常大&#xff0c;你只需要输出模 10971097 的余数。 如上图所示的正方形都是合法的。 输入格式 输入包含一个整数 …...

Spring Boot开发—— 实现订单号生成逻辑

文章目录 1. UUID2. 数据库序列或自增ID3. 时间戳 随机数/序列4. 分布式唯一ID生成方案 几种常见的解决方案 UUID 实例代码数据库序列或自增ID时间戳 随机数/序列分布式唯一ID生成方案 Snowflake ID结构类定义和变量初始化构造函数ID生成方法辅助方法 在 Spring Boot 中设计…...

React中Redux的基本用法

Redux是React中使用较多的状态管理库&#xff0c;这篇文章主要介绍了Redux的基本用法&#xff0c;快来看看吧 首先我们需要新建一个React项目&#xff0c;我使用的ReactTS&#xff0c;文件结构如下 Redux的相关使用主要在store文件中 Store&#xff1a;存储整个应用的状态Act…...

unity3d————基础篇小项目(设置界面)

代码示例&#xff1a; 设置界面 using System.Collections; using System.Collections.Generic; using UnityEngine;public class SettingPanel : BasePanel<SettingPanel> {public UIButton btnClose;public UISlider sliderMusic;public UISlider sliderSound;public…...

推荐几个 VSCode 流程图工具

Visual Studio Code&#xff08;简称VSCode&#xff09;是一个由微软开发的免费、开源的代码编辑器。 VSCode 发布于 2015 年&#xff0c;而且很快就成为开发者社区中广受欢迎的开发工具。 VSCode 可用于 Windows、macOS 和 Linux 等操作系统。 VSCode 拥有一个庞大的扩展市…...

vs做网站如何输出/百度推广云南总代理

转载自「LeanCloud通讯」公众号 作者&#xff1a;LeanCloud 郑鹏2018 年 12 月&#xff0c;Google 发布了 Flutter 1.0 正式版&#xff0c;似乎再次点燃了人们对移动跨平台开发的热情。上一次出现类似的情况&#xff0c;是在 15 年年初&#xff0c;Facebook 发布 React Native …...

重庆网站建设公司下载/官网排名优化

Floyd算法的思想是典型的动态规划&#xff0c;状态方程的定义如下&#xff1a;...

wordpress标题数据表/外贸网站制作推广

Mahout版本&#xff1a;0.7&#xff0c;hadoop版本&#xff1a;1.0.4&#xff0c;jdk&#xff1a;1.7.0_25 64bit。 本篇是ItemBased Collaborative Filtering的算法综述&#xff0c;即总结前面几篇blog&#xff0c;分析该算法的数据流&#xff0c;主要使用的数据是《mahout i…...

哪里可以做网站平台/百度人工客服电话怎么转人工

thinkphp5使用无限极分类来源&#xff1a;中文源码网 浏览&#xff1a; 次 日期&#xff1a;2019年11月5日【下载文档: thinkphp5使用无限极分类.txt 】(友情提示:右键点上行txt文档名->目标另存为)thinkphp5使用无限极分类本文实例为大家分享了thinkphp5使用无限极分…...

上上海海网网站站建设/好用的百度网盘搜索引擎

前面一样的我就不写了,请先看这里zookeeper伪分布配置 1.接着那篇,修改drguo3的zoo.cfg文件(两处) # The number of milliseconds of each tick tickTime=2000 # The number of ticks that the initial # synchronization phase can take initLimit=10 # The number of …...

网站开发人员名片/如何宣传网站

每一个oracle数据库都有一个控制文件。控制文件是一个小型的二进制文件&#xff0c;可以记录数据库的物理结构&#xff0c;包含以下的内容&#xff1a;数据库名称、相关数据文件和联机重做日志文件的名称和位置、数据库创建的时标、当前日志的序号、检验点信息。 无论何时打开数…...