最近在看微软eShopOnContainers 项目,看到事件总线觉得不错,和大家分享一下
看完此文你将获得什么?
eShop中是如何设计事件总线的
实现一个InMemory事件总线eShop中是没有InMemory实现的,这算是一个小小小的挑战
发布订阅模式
发布订阅模式可以让应用程序组件之间解耦,这是我们使用这种模式最重要的理由之一,如果你完全不知道这个东西,建议你先通过搜索引擎了解一下这种模式,网上的资料很多这里就不再赘述了。
eShop中的EventBus就是基于这种模式的发布/订阅 。 发布订阅模式核心概念有三个:发布者、订阅者、调度中心 ,这些概念在消息队列中就是生产者、消费者、MQ实例 。
在eShop中有两个EventBus的实现:
基于RabbitMq的EventBusRabbitMQ
基于AzureServiceBus的EventBusServiceBus
。
从IEventBus
开始
先来看一看,所有EventBus的接口IEventBus
public interface IEventBus
{
void Publish(IntegrationEvent @event);
void Subscribe()
where T : IntegrationEvent
where TH : IIntegrationEventHandler;
void SubscribeDynamic(string eventName)
where TH : IDynamicIntegrationEventHandler;
void UnsubscribeDynamic (string eventName)
where TH : IDynamicIntegrationEventHandler;
void Unsubscribe()
where TH : IIntegrationEventHandler
where T : IntegrationEvent;
}
嗯,乍一看看是有点眼晕的,仔细看它的核心功能只有三个:
Publish 发布
Subscribe 订阅
Unsubscribe 取消订阅
这对应着发布订阅模式的基本概念,不过对于事件总线的接口添加了许多约束:
发布的内容(消息)必须是IntegrationEvent
及其子类
订阅事件必须指明要订阅事件的类型,并附带处理器类型
处理器必须是IIntegrationEventHandler
的实现类
Ok,看到这里先不要管Dynamic
相关的方法,然后记住这个两个关键点:
事件必须继承IntegrationEvent
处理器必须实现IIntegrationEventHandler
且T
是IntegrationEvent
子类
另外,看下 IntegrationEvent
有什么
public class IntegrationEvent
{
public IntegrationEvent()
{
Id = Guid.NewGuid();
CreationDate = DateTime.UtcNow;
}
public Guid Id { get; }
public DateTime CreationDate { get; }
}
IEventBusSubscriptionsManager是什么
public interface IEventBusSubscriptionsManager
{
bool IsEmpty { get; }
event EventHandler OnEventRemoved;
void AddDynamicSubscription(string eventName)
where TH : IDynamicIntegrationEventHandler;
void AddSubscription()
where T : IntegrationEvent
where TH : IIntegrationEventHandler;
void RemoveSubscription()
where TH : IIntegrationEventHandler
where T : IntegrationEvent;
void RemoveDynamicSubscription(string eventName)
where TH : IDynamicIntegrationEventHandler;
bool HasSubscriptionsForEvent() where T : IntegrationEvent;
bool HasSubscriptionsForEvent(string eventName);
Type GetEventTypeByName(string eventName);
void Clear();
IEnumerable GetHandlersForEvent() where T : IntegrationEvent;
IEnumerable GetHandlersForEvent(string eventName);
string GetEventKey();
}
这个接口看起来稍显复杂些,我们来简化下看看:
public interface IEventBusSubscriptionsManager
{
void AddSubscription()
void RemoveSubscription()
IEnumerable GetHandlersForEvent()
}
最终,这三个方法就是我们要关注的,添加订阅、移除订阅、获取指定事件的订阅信息。
SubscriptionInfo
是什么?
public bool IsDynamic { get; }
public Type HandlerType{ get; }
SubscriptionInfo
中只有两个信息,这是不是一个Dynamic类型的Event以及这个Event所对应的处理器的类型。
这是你可能会有另一个疑问:
这个和IEventBus
有什么关系?
IEventBusSubscriptionsManager
含有更多功能:查看是否有订阅,获取事件的Type,获取事件的处理器等等
IEventBusSubscriptionsManager
由IEventBus
使用,在RabbitMq和ServiceBus的实现中,都使用Manager去存储事件的信息,例如下面的代码:
public void Subscribe()
where T : IntegrationEvent
where TH : IIntegrationEventHandler
{
// 查询事件的全名
var eventName = _subsManager.GetEventKey();
//向mq添加注册
DoInternalSubscription(eventName);
// 向manager添加订阅
_subsManager.AddSubscription();
}
private void DoInternalSubscription(string eventName)
{
var containsKey = _subsManager.HasSubscriptionsForEvent(eventName);
if (!containsKey)
{
if (!_persistentConnection.IsConnected)
{
_persistentConnection.TryConnect();
}
using (var channel = _persistentConnection.CreateModel())
{
channel.QueueBind(queue: _queueName,
exchange: BROKER_NAME,
routingKey: eventName);
}
}
}
查询事件的名字是manager做的,订阅的时候是先向mq添加订阅,之后又加到manager中,manager管理着订阅的基本信息。
另外一个重要功能是获取事件的处理器信息,在rabbit mq的实现中,ProcessEvent方法中用manager获取了事件的处理器,再用依赖注入获得处理器的实例,反射调用Handle
方法处理事件信息:
private async Task ProcessEvent(string eventName, string message)
{
// 从manager查询信息
if (_subsManager.HasSubscriptionsForEvent(eventName))
{
using (var scope = _autofac.BeginLifetimeScope(AUTOFAC_SCOPE_NAME))
{
// 从manager获取处理器
var subscriptions = _subsManager.GetHandlersForEvent(eventName);
foreach (var subscription in subscriptions)
{
// Di + 反射调用,处理事件(两个都是,只是针对是否是dynamic做了不同的处理)
if (subscription.IsDynamic)
{
var handler = scope.ResolveOptional(subscription.HandlerType) as IDynamicIntegrationEventHandler;
dynamic eventData = JObject.Parse(message);
await handler.Handle(eventData);
}
else
{
var eventType = _subsManager.GetEventTypeByName(eventName);
var integrationEvent = JsonConvert.DeserializeObject(message, eventType);
var handler = scope.ResolveOptional(subscription.HandlerType);
var concreteType = typeof(IIntegrationEventHandler<>).MakeGenericType(eventType);
await (Task)concreteType.GetMethod("Handle").Invoke(handler, new object[] { integrationEvent });
}
}
}
}
}
IEventBusSubscriptionsManager的默认实现
在eShop中只有一个实现就是InMemoryEventBusSubscriptionsManager
类
这个类中有两个重要的字段
private readonly Dictionary> _handlers;
private readonly List _eventTypes;
他们分别存储了事件列表和事件处理器信息词典
接下来就是实现一个
基于内存的事件总线
了
我们要做什么呢?IEventBusSubscriptionsManager 已经有了InMemory的实现了,我们可以直接拿来用,所以我们只需要自己实现一个EventBus就好了
先贴出最终代码:
public class InMemoryEventBus : IEventBus
{
private readonly IServiceProvider _provider;
private readonly ILogger _logger;
private readonly ISubscriptionsManager _manager;
private readonly IList _events;
public InMemoryEventBus(
IServiceProvider provider,
ILogger logger,
ISubscriptionsManager manager)
{
_provider = provider;
_logger = logger;
_manager = manager;
}
public void Publish(IntegrationEvent e)
{
var eventType = e.GetType();
var handlers = _manager.GetHandlersForEvent(eventType.FullName);
foreach (var handlerInfo in handlers)
{
var handler = _provider.GetService(handlerInfo.HandlerType);
var method = handlerInfo.HandlerType.GetMethod("Handle");
method.Invoke(handler, new object[] { e });
}
}
public void Subscribe()
where T : IntegrationEvent
where TH : IIntegrationEventHandler
{
_manager.AddSubscription();
}
public void SubscribeDynamic(string eventName) where TH : IDynamicIntegrationEventHandler
{
throw new NotImplementedException();
}
public void Unsubscribe()
where T : IntegrationEvent
where TH : IIntegrationEventHandler
{
_manager.RemoveSubscription();
}
public void UnsubscribeDynamic(string eventName) where TH : IDynamicIntegrationEventHandler
{
throw new NotImplementedException();
}
}
首先构造函数中声明我们要使用的东西:
public InMemoryEventBus(
IServiceProvider provider,
ILogger logger,
ISubscriptionsManager manager)
{
_provider = provider;
_logger = logger;
_manager = manager;
}
这里要注意的就是IServiceProvider provider
这是 DI容器,当我们在切实处理事件的时候我们选择从DI获取处理器的实例,而不是反射创建,这要做的好处在于,处理器可以依赖于其它东西,并且可以是单例的
public void Subscribe()
where T : IntegrationEvent
where TH : IIntegrationEventHandler
{
_manager.AddSubscription();
}
public void Unsubscribe()
where T : IntegrationEvent
where TH : IIntegrationEventHandler
{
_manager.RemoveSubscription();
}
订阅和取消订阅很简单,因为我们是InMemory的所以只调用了manager的方法。
接下来就是最重要的Publish方法,实现Publish有两种方式:
使用额外的线程和Queue让发布和处理异步
为了简单起见,我们先写个简单易懂的同步的
public void Publish(IntegrationEvent e)
{
// 首先要拿到集成事件的Type信息
var eventType = e.GetType();
// 获取属于这个事件的处理器列表,可能有很多,注意获得的是SubscriptionInfo
var handlers = _manager.GetHandlersForEvent(eventType.FullName);
// 不解释循环
foreach (var handlerInfo in handlers)
{
// 从DI中获取类型的实例
var handler = _provider.GetService(handlerInfo.HandlerType);
// 拿到Handle方法
var method = handlerInfo.HandlerType.GetMethod("Handle");
// 调用方法
method.Invoke(handler, new object[] { e });
}
}
OK,我们的InMemoryEventBus就写好了!
要实践这个InMemoryEventBus,那么还需要一个IntegrationEvent
的子类,和一个IIntegrationEventHandler
的实现类,这些都不难,例如我们做一个添加用户的事件,A在添加用户后,发起一个事件并将新用户的名字作为事件数据,B去订阅事件,并在自己的处理器中处理名字信息。
思路是这样的:
写一个 AddUserEvent:IntegrationEvent
,里面有一个UserId和一个UserName
。
写一个AddUserEventHandler:IIntegrationEventHandler
,在Handle
方法中输出UserId和Name到日志。
注册DI,你要注册下面这些服务:
IEventBus=>InMemoryEventBus
ISubscriptionsManager=>InMemorySubscriptionsManager
AddUserEventHandler=>AddUserEventHandler
在Startup中为刚刚写的事件和处理器添加订阅(在这里已经可以获取到IEventBus实例了)
写一个Api接口或是什么,调用IEventBus的Publish方法,new 一个新的AddUserEvent
作为参数传进去。
OK!到这里一个切实可用的InMemoryEventBus就可以使用了。
你可能感兴趣的:(看eShopOnContainers学一个EventBus)
JVM八股文系列一:JVM基础知识
suikasa
JVM八股文 java jvm
一.JVM基础知识1.JVM从编译到执行1.1Java程序的执行过程一个Java程序,首先经过javac编译成.class文件,然后JVM将其加载到方法区,执行引擎将会执行这些字节码。执行时,会翻译成操作系统相关的函数。JVM作为.class文件的翻译存在,输入字节码,调用操作系统函数。过程如下:Java文件->编译器>字节码->JVM->机器码。JVM也就是Java虚拟机。它能识别.class后
高级java每日一道面试题-2025年3月03日-微服务篇[Eureka篇]-Eureka自我保护机制是什么?
java我跟你拼了
java每日一道面试题 java 微服务 eureka SpringCloud SpringBoot 自我保护机制 出发条件
如果有遗漏,评论区告诉我进行补充面试官:Eureka自我保护机制是什么?我回答:在Java高级面试中,Eureka的自我保护机制(Self-PreservationMode)是一个非常重要且常被提及的话题。理解这一机制的工作原理及其应用场景对于构建高可用性的微服务架构至关重要。以下是结合提供的内容对Eureka自我保护机制的详细解析和综合概述:自我保护机制的概念Eureka的自我保护机制是一种容错
史上最全JVM面试八股文合集
Java小海.
面试 java 职场和发展 程序人生 后端
简述JVM内存模型线程私有的运行时数据区:程序计数器、Java虚拟机栈、本地方法栈。线程共享的运行时数据区:Java堆、方法区。简述程序计数器程序计数器表示当前线程所执行的字节码的行号指示器。程序计数器不会产生StackOverflowError和OutOfMemoryError。简述虚拟机栈Java虚拟机栈用来描述Java方法执行的内存模型。线程创建时就会分配一个栈空间,线程结束后栈空间被回收。
一文了解ThreadLocal
Key~美好的每一天
java 开发语言
什么是ThreadLocal?ThreadLocal是每个线程私有的,线程可以把自己的私有数据放到ThreadLocal里面,不用担心其他线程访问到自己ThreadLocal。通过set()方法将值存入ThreadLocal或者修改值,get()方法取出值,remove()方法移除值。ThreadLocal原理ThreadLocal类中有一个内部类ThreadLocalMap,它其实就是一个哈希表
【C++】仿函数的概念
无水先生
BOOST C++ c++
目录一、仿函数说明二、仿函数的定义三、更直观的例子四、仿函数实例五、仿函数仿函数(functor)在各编程语言中的应用5.1仿函数C5.2仿函数C++5.3仿函数C#5.4仿函数Java一、仿函数说明在我们写代码时有时会发现有些功能实现的代码,会不断的在不同的成员函数中用到,但是又不好将这些代码独立出来成为一个类的一个成员函数。但是又很想复用这些代码。写一个公共的函数,就要单立出一个函数,也不是很
C# 技术使用笔记:如何高效处理字符串
caifox菜狐狸
C# 技术使用笔记 c# 笔记 string StringBuilder Substring Replace Split
1.C#字符串基础概念1.1字符串不可变性在C#中,字符串具有不可变性,这意味着一旦创建了一个字符串对象,其内容就不能被修改。例如,当我们执行以下代码时:stringstr="Hello";str=str+"World";实际上,str+"World"并是修改了原来的"Hello"字符串,而是创建了一个全新的字符串对象"HelloWorld",并将str的引用指向了这个新对象,原来的"Hello"
uni-app全局弹窗的实现方案
-Dayer-
uni-app 前端 javascript 全局弹窗
背景为了解决uni-app任意位置出现弹窗解决方案一、最初方案受限于uni-app调用组件需要每个页面都引入注册才可以使用,此方案繁琐,每个页面都要写侵入性比较强二、改进方案app端:新建一个页面进行跳转,可以实现伪弹窗(其实是打开一个背景透明的页面)web端:全局挂载body插入一个弹窗三、初步实现方案就是利用条件编译,web端写组件、app端写页面,利用不同的生命周期,完成通用的逻辑四、详细实
一键秒连WiFi智能设备,uni-app全栈式物联开发指南。
豆豆(前端开发+ui设计)
前端
如何使用uni-app框架实现通过WiFi连接设备并进行命令交互的硬件开发。为了方便理解和实践,我们将提供相应的源代码示例,帮助开发者快速上手。1.硬件准备在开始之前,请确保你已经准备好以下硬件设备:支持WiFi连接的设备:如ESP8266、ESP32等。控制端设备:手机或电脑,安装有支持uni-app开发的开发环境(如HBuilderX)。网络环境:确保设备和控制端在同一个局域网内。2.uni-
webpack初识(js逆向)
shix .
js逆向知识点 webpack javascript 前端
webpack调试很多时候再看webpack的代码块的时候都一头雾水,不知道这个函数的具体逻辑在哪里,因为打包之后一些函数块是通过数字或者字符串进行调用的就像这样这里每个括号包括着的字符串都相当于一个函数,但是他们的逻辑在其他地方第二种情况:window["webpackJsonp"]大概长这样(=window["webpackJsonp"]||[]).push(["login"])作用就是把打包
JavaScript typeof 运算符详解
wjs2024
开发语言
JavaScripttypeof运算符详解概述在JavaScript中,typeof是一个一元运算符,用于检测给定变量的数据类型。它是JavaScript中最常用的类型检查方法之一。本文将详细解释typeof运算符的用法、返回值以及其局限性。typeof运算符的用法typeof运算符后面跟一个要检查类型的变量或表达式。它不区分大小写,以下是其基本用法:leta=10;console.log(typ
注意力机制:让AI拥有“黄金七秒记忆“的魔法----(点积注意力)
y江江江江
机器学习 大模型 人工智能 深度学习
注意力机制:让AI拥有"黄金七秒记忆"的魔法–(点积注意力)注意⼒机制对于初学者来说有点难理解,我们⼀点⼀点地讲。现在先暂时忘记编码器、解码器、隐藏层和序列到序列这些概念。想象我们有两个张量x1和x2,我们希望⽤注意⼒机制把它俩给衔接起来,让x1看⼀看,x2有哪些特别值得关注的地⽅。具体来说,要得到x1对x2的点积注意⼒,我们可以按照以下步骤进⾏操作。(1)创建两个形状分别为(batch_size
如何实现一个apply函数?
风茫
Javascript javascript apply
在JavaScript中,apply是一个非常有用的方法,它允许你调用一个函数,并显式地指定该函数内部的this值。与call方法不同,apply方法接受参数的方式是一个数组或类数组对象。我们将手动实现一个类似apply的函数,以深入理解其工作原理。实现步骤1.定义myApply方法首先,我们需要在Function.prototype上定义一个新的方法myApply,这样所有的函数都可以调用它。F
TCP/IP学习笔记(5) --IP选路
ox0080
Linux 网络 linux网络
静态IP选路一个简单的路由表选路是IP层最重要的一个功能之一。前面的部分已经简单的讲过路由器是通过何种规则来根据IP数据包的IP地址来选择路由。这里就不重复了。首先来看看一个简单的系统路由表。命令:routeprint|more对于一个给定的路由器,可以打印出五种不同的flag。U表明该路由可用。G表明该路由是到一个网关。如果没有这个标志,说明和Destination是直连的,而相应的Gatewa
深入理解指针5
很会做人
数据结构
一、回调函数是什么?回调函数就是一个通过指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,被调用的函数就是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。下面用代码进行理解当a等于1的时候才会打印hehe。#includevoidfunction(){printf("
利用 HAI 平台进行 DeepSeek 模型训练的详细指南
摘要本文旨在为非专业用户提供在HAI平台上进行DeepSeek模型训练的详细步骤。从创建项目、上传数据集、配置训练参数到启动训练任务并监控训练过程,本文将逐步指导用户完成整个流程。此外,本文还包含可运行的示例代码模块和相关章节配图,以帮助用户更好地理解和操作。引言HAI(HyperAI)平台是一个强大的AI模型训练平台,但对于非专业用户来说,其复杂性可能会成为使用的障碍。本文将详细介绍如何在HAI
FerretDB 2.0:开源 MongoDB 替代品的安装与使用指南
田猿笔记
MongoDB 开源 数据库 FerretDB
介绍FerretDB2.0是一个开源数据库,旨在作为MongoDB的替代品。它与MongoDB5.0+的驱动程序和工具兼容,适合需要避免MongoDB许可复杂性的开发者。它的核心特点是使用PostgreSQL作为后端,并通过DocumentDB扩展提升性能,研究表明某些工作负载可快20倍。安装与使用安装FerretDB2.0使用dockercompose需要以下步骤:创建docker-compos
LORA的魔法棒:在Stable Diffusion中挥洒注意力机制的优化咒语 ??
DTcode7
AI生产力 AI AIGC stable diffusion AI生产力 前沿
LORA的魔法棒:在StableDiffusion中挥洒注意力机制的优化咒语??欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。推荐:DTcode7的博客首页。一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞
05.静态代理设计模式
java
05.静态代理设计模式目录介绍01.静态代理模式基础1.1静态代理由来1.2静态代理定义1.3静态代理场景1.4静态代理思考02.静态代理原理与实现2.1罗列一个场景2.2用一个例子理解代理2.3案例演变分析03.静态代理分析3.1静态代理结构图3.2静态代理时序图04.代理模式优势4.1如何降低耦合4.2保护真实对象使用权限05.静态代理不足5.1静态代理类优缺点5.2静态代理缺乏灵活5.3静态
华为云认证 - 云学堂「集证」有礼
天氰色等烟雨
华为云
华为云最近又出了一个新活动,我看了一下,奖励比上次的要好很多,本来不想搞的,这下不得不考虑一下了~还是一样,得先报名才能参与活动!特别提醒一下,企业账号是不能参加这次活动的,大家要用个人账户来报名。按以往的经历,不是实名认证的账号也可以参与进来。活动地址如下:DeveloperEvents_DeveloperAlliance-HuaweiCloudMeetlike-mindeddevelopers
【设计模式】建造者模式
浅慕Antonio
设计模式 设计模式 建造者模式 c++
三、建造者模式3.3建造者模式建造者(Builder)模式也称构建器模式、构建者模式或生成器模式,同工厂模式或原型模式一样,也是一种创建型模式。建造者模式比较复杂,不太常用,但这并不表示不需要了解和掌握该模式。建造者模式通常用来创建一个比较复杂的对象(这也是建造者模式本身比较复杂的主要原因),该对象的构建一般是需要按一定顺序分步骤进行的。例如,建造一座房子(无论是平房、别墅还是高楼),通常都需要按
五、AIGC大模型_09手动实现ReAct_Agent
学不会lostfound
AI 人工智能 react_agent LangGraph Multi-Agent PlanAndExecute AIGC
0、前言在上一章节中,我们了解到:create_react_agent是LangGraph提供的一个预构建方法(fromlanggraph.prebuiltimportcreate_react_agent),它可以将语言模型(LLM)和一组工具(Tools)结合起来,创建一个能够根据用户输入自动调用工具的智能代理,这个代理可以根据用户的请求,决定是否需要调用某个工具,并将工具的输出反馈给用户这个函
Stream流与Guava工具类使用
小薛博客
guava 数据库 java
Stream流与Guava工具类使用小薛博客官方地址Stream流与Guava工具类使用1、StreamAPI1、了解StreamJava8中有两大最为重要的改变。第一个是Lambda表达式;另外一个则是StreamAPI(java.util.stream.*)。Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用S
C# 正则表达式的详细使用说明
生命不息-学无止境
C#理论知识 c# 正则表达式
正则表达式基础概念正则表达式是一种用于匹配文本模式的工具。它是由普通字符(例如字母、数字)和特殊字符(称为元字符)组成的字符串模式。在C#中,主要通过System.Text.RegularExpressions命名空间来使用正则表达式。元字符表格显示:分类正则表达式字符描述示例字符类.匹配除换行符之外的任意单个字符a.b可匹配aab、acb等[abc]匹配字符a、b或c中的任意一个[abc]可匹配
【转】C#正则表达式详解
weixin_30765475
c# javascript 操作系统 ViewUI
正则表达式通常包含字母文本(Literaltext)和元字符(metacharacter)字母文本指的是普通文本如"abcde"可匹配字符串中任何包含"abcde"的字符串。元字符则更加灵活运用通用的表达式匹配所有符合此表达式规律的字符串。C#正则表达式语法一、匹配单个字符[]——从中选择一个字符匹配中间支持的类型:单词字符([ae])、非单词字符([!?,;@#$*])、字母范围([A-Z])、
【项目实战】—— 高并发内存池
Ryan.Alaskan Malamute
开发语言 c++ 高并发内存池 缓存
文章目录什么是高并发内存池?项目介绍一、项目背景二、项目目标三、核心组件四、关键技术五、应用场景六、项目优势什么是高并发内存池? 高并发内存池是一种专门设计用于高并发环境下的内存管理机制。它的原型是Google的一个开源项目tcmalloc,全称Thread-CachingMalloc,实现了高效的多线程内存管理,用于替换系统的内存分配相关函数malloc和free。 在高并发系统中,大量的线
大数据和人工智能概念全面解析
就犯得上方法
一、大数据和人工智能大数据是伴随着信息数据爆炸式增长和网络计算技术迅速发展而兴起的一个新型概念。根据麦肯锡全球研究所的定义,大数据是一种规模大到在获取、存储、管理、分析方面大大超出了传统数据库软件工具能力范围的数据集合,具有海量的数据规模、快速的数据流转、多样的数据类型和价值密度低四大特征。大数据能够帮助各行各业的企业从原本毫无价值的海量数据中挖掘出用户的需求,使数据能够从量变到质变,真正产生价值
力扣hot100——283.移动零
码凡
算法 leetcode
283.移动零给定一个数组nums,编写一个函数将所有0移动到数组的末尾,同时保持非零元素的相对顺序。请注意,必须在不复制数组的情况下原地对数组进行操作。示例1:输入:nums=[0,1,0,3,12]输出:[1,3,12,0,0]示例2:输入:nums=[0]输出:[0]题解:对于此题可以从反方向来思考,需要将所有的零找出来则我们可以找出所有非零数,再将零添加到数组的末尾。题目要求在数组原地进行
力扣hot100——49.字母异位词分组
码凡
leetcode 算法
49.字母异位词分组给你一个字符串数组,请你将字母异位词组合在一起。可以按任意顺序返回结果列表。字母异位词是由重新排列源单词的所有字母得到的一个新单词。示例1:输入:strs=["eat","tea","tan","ate","nat","bat"]输出:[["bat"],["nat","tan"],["ate","eat","tea"]]示例2:输入:strs=[""]输出:[[""]]示例3:
参加AIGC四级考试的,建议先看下我的备考经验
Tester_孙大壮
AI培训师 AIGC
写在前面这是我2024年末看到AI快速发展,自己也想入局AI而准备的一个考试,但是真正考试下来发现这个考试真的特别简单,除了政府补贴,其他可能对自己没有任何的用处,我觉得这个在面试的时候也很难成为一个加分项,但是备考过程中可能会对一些AI的知识有框架式的了解,以下是我的备考经验,希望对你有帮助。我参加的是广州本地宝推荐的人社部AIGC考试。整体而言,考试难度不算特别大。以我的工作年限,符合报考四级
SpringBoot常用注解
AWen_X
言简意赅系列之Spring Java常用框架注解 spring boot java 后端 spring
SpringBoot常用注解SpringBoot框架提供了丰富的注解,极大地简化了应用开发。本文将SpringBoot常用注解按功能分组,并提供详细说明和使用示例。一、核心注解1.@SpringBootApplication这是SpringBoot应用的核心注解,标记在主类上,表明这是一个SpringBoot应用的入口。它是一个组合注解,相当于同时使用了以下三个注解:@Configuration:
Java实现的基于模板的网页结构化信息精准抽取组件:HtmlExtractor
yangshangchuan
信息抽取 HtmlExtractor 精准抽取 信息采集
HtmlExtractor是一个Java实现的基于模板的网页结构化信息精准抽取组件,本身并不包含爬虫功能,但可被爬虫或其他程序调用以便更精准地对网页结构化信息进行抽取。
HtmlExtractor是为大规模分布式环境设计的,采用主从架构,主节点负责维护抽取规则,从节点向主节点请求抽取规则,当抽取规则发生变化,主节点主动通知从节点,从而能实现抽取规则变化之后的实时动态生效。
如
java编程思想 -- 多态
百合不是茶
java 多态详解
一: 向上转型和向下转型
面向对象中的转型只会发生在有继承关系的子类和父类中(接口的实现也包括在这里)。父类:人 子类:男人向上转型: Person p = new Man() ; //向上转型不需要强制类型转化向下转型: Man man =
[自动数据处理]稳扎稳打,逐步形成自有ADP系统体系
comsci
dp
对于国内的IT行业来讲,虽然我们已经有了"两弹一星",在局部领域形成了自己独有的技术特征,并初步摆脱了国外的控制...但是前面的路还很长....
首先是我们的自动数据处理系统还无法处理很多高级工程...中等规模的拓扑分析系统也没有完成,更加复杂的
storm 自定义 日志文件
商人shang
storm cluster logback
Storm中的日志级级别默认为INFO,并且,日志文件是根据worker号来进行区分的,这样,同一个log文件中的信息不一定是一个业务的,这样就会有以下两个需求出现:
1. 想要进行一些调试信息的输出
2. 调试信息或者业务日志信息想要输出到一些固定的文件中
不要怕,不要烦恼,其实Storm已经提供了这样的支持,可以通过自定义logback 下的 cluster.xml 来输
Extjs3 SpringMVC使用 @RequestBody 标签问题记录
21jhf
springMVC使用 @RequestBody(required = false) UserVO userInfo
传递json对象数据,往往会出现http 415,400,500等错误,总结一下需要使用ajax提交json数据才行,ajax提交使用proxy,参数为jsonData,不能为params;另外,需要设置Content-type属性为json,代码如下:
(由于使用了父类aaa
一些排错方法
文强chu
方法
1、java.lang.IllegalStateException: Class invariant violation
at org.apache.log4j.LogManager.getLoggerRepository(LogManager.java:199)at org.apache.log4j.LogManager.getLogger(LogManager.java:228)
at o
Swing中文件恢复我觉得很难
小桔子
swing
我那个草了!老大怎么回事,怎么做项目评估的?只会说相信你可以做的,试一下,有的是时间!
用java开发一个图文处理工具,类似word,任意位置插入、拖动、删除图片以及文本等。文本框、流程图等,数据保存数据库,其余可保存pdf格式。ok,姐姐千辛万苦,
php 文件操作
aichenglong
PHP 读取文件 写入文件
1 写入文件
@$fp=fopen("$DOCUMENT_ROOT/order.txt", "ab");
if(!$fp){
echo "open file error" ;
exit;
}
$outputstring="date:"." \t tire:".$tire."
MySQL的btree索引和hash索引的区别
AILIKES
数据结构 mysql 算法
Hash 索引结构的特殊性,其 检索效率非常高,索引的检索可以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后才能访问到页节点这样多次的IO访问,所以 Hash 索引的查询效率要远高于 B-Tree 索引。
可能很多人又有疑问了,既然 Hash 索引的效率要比 B-Tree 高很多,为什么大家不都用 Hash 索引而还要使用 B-Tree 索引呢
JAVA的抽象--- 接口 --实现
百合不是茶
抽象 接口 实现接口
//抽象 类 ,方法
//定义一个公共抽象的类 ,并在类中定义一个抽象的方法体
抽象的定义使用abstract
abstract class A 定义一个抽象类 例如:
//定义一个基类
public abstract class A{
//抽象类不能用来实例化,只能用来继承
//
JS变量作用域实例
bijian1013
作用域
<script>
var scope='hello';
function a(){
console.log(scope); //undefined
var scope='world';
console.log(scope); //world
console.log(b);
TDD实践(二)
bijian1013
java TDD
实践题目:分解质因数
Step1:
单元测试:
package com.bijian.study.factor.test;
import java.util.Arrays;
import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;
import com.bijian.
[MongoDB学习笔记一]MongoDB主从复制
bit1129
mongodb
MongoDB称为分布式数据库,主要原因是1.基于副本集的数据备份, 2.基于切片的数据扩容。副本集解决数据的读写性能问题,切片解决了MongoDB的数据扩容问题。
事实上,MongoDB提供了主从复制和副本复制两种备份方式,在MongoDB的主从复制和副本复制集群环境中,只有一台作为主服务器,另外一台或者多台服务器作为从服务器。 本文介绍MongoDB的主从复制模式,需要指明
【HBase五】Java API操作HBase
bit1129
hbase
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.ha
python调用zabbix api接口实时展示数据
ronin47
zabbix api接口来进行展示。经过思考之后,计划获取如下内容: 1、 获得认证密钥 2、 获取zabbix所有的主机组 3、 获取单个组下的所有主机 4、 获取某个主机下的所有监控项  
jsp取得绝对路径
byalias
绝对路径
在JavaWeb开发中,常使用绝对路径的方式来引入JavaScript和CSS文件,这样可以避免因为目录变动导致引入文件找不到的情况,常用的做法如下:
一、使用${pageContext.request.contextPath}
代码” ${pageContext.request.contextPath}”的作用是取出部署的应用程序名,这样不管如何部署,所用路径都是正确的。
Java定时任务调度:用ExecutorService取代Timer
bylijinnan
java
《Java并发编程实战》一书提到的用ExecutorService取代Java Timer有几个理由,我认为其中最重要的理由是:
如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer线程并不捕获异常,所以 TimerTask抛出的未检查的异常会终止timer线程。这种情况下,Timer也不会再重新恢复线程的执行了;它错误的认为整个Timer都被取消了。此时,已经被
SQL 优化原则
chicony
sql
一、问题的提出
在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句的优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统
java 线程弹球小游戏
CrazyMizzz
java 游戏
最近java学到线程,于是做了一个线程弹球的小游戏,不过还没完善
这里是提纲
1.线程弹球游戏实现
1.实现界面需要使用哪些API类
JFrame
JPanel
JButton
FlowLayout
Graphics2D
Thread
Color
ActionListener
ActionEvent
MouseListener
Mouse
hadoop jps出现process information unavailable提示解决办法
daizj
hadoop jps
hadoop jps出现process information unavailable提示解决办法
jps时出现如下信息:
3019 -- process information unavailable3053 -- process information unavailable2985 -- process information unavailable2917 --
PHP图片水印缩放类实现
dcj3sjt126com
PHP
<?php
class Image{
private $path;
function __construct($path='./'){
$this->path=rtrim($path,'/').'/';
}
//水印函数,参数:背景图,水印图,位置,前缀,TMD透明度
public function water($b,$l,$pos
IOS控件学习:UILabel常用属性与用法
dcj3sjt126com
ios UILabel
参考网站:
http://shijue.me/show_text/521c396a8ddf876566000007
http://www.tuicool.com/articles/zquENb
http://blog.csdn.net/a451493485/article/details/9454695
http://wiki.eoe.cn/page/iOS_pptl_artile_281
完全手动建立maven骨架
eksliang
java eclipse Web
建一个 JAVA 项目 :
mvn archetype:create
-DgroupId=com.demo
-DartifactId=App
[-Dversion=0.0.1-SNAPSHOT]
[-Dpackaging=jar]
建一个 web 项目 :
mvn archetype:create
-DgroupId=com.demo
-DartifactId=web-a
配置清单
gengzg
配置
1、修改grub启动的内核版本
vi /boot/grub/grub.conf
将default 0改为1
拷贝mt7601Usta.ko到/lib文件夹
拷贝RT2870STA.dat到 /etc/Wireless/RT2870STA/文件夹
拷贝wifiscan到bin文件夹,chmod 775 /bin/wifiscan
拷贝wifiget.sh到bin文件夹,chm
Windows端口被占用处理方法
huqiji
windows
以下文章主要以80端口号为例,如果想知道其他的端口号也可以使用该方法..........................1、在windows下如何查看80端口占用情况?是被哪个进程占用?如何终止等. 这里主要是用到windows下的DOS工具,点击"开始"--"运行",输入&
开源ckplayer 网页播放器, 跨平台(html5, mobile),flv, f4v, mp4, rtmp协议. webm, ogg, m3u8 !
天梯梦
mobile
CKplayer,其全称为超酷flv播放器,它是一款用于网页上播放视频的软件,支持的格式有:http协议上的flv,f4v,mp4格式,同时支持rtmp视频流格 式播放,此播放器的特点在于用户可以自己定义播放器的风格,诸如播放/暂停按钮,静音按钮,全屏按钮都是以外部图片接口形式调用,用户根据自己的需要制作 出播放器风格所需要使用的各个按钮图片然后替换掉原始风格里相应的图片就可以制作出自己的风格了,
简单工厂设计模式
hm4123660
java 工厂设计模式 简单工厂模式
简单工厂模式(Simple Factory Pattern)属于类的创新型模式,又叫静态工厂方法模式。是通过专门定义一个类来负责创建其他类的实例,被创建的实例通常都具有共同的父类。简单工厂模式是由一个工厂对象决定创建出哪一种产品类的实例。简单工厂模式是工厂模式家族中最简单实用的模式,可以理解为是不同工厂模式的一个特殊实现。
maven笔记
zhb8015
maven
跳过测试阶段:
mvn package -DskipTests
临时性跳过测试代码的编译:
mvn package -Dmaven.test.skip=true
maven.test.skip同时控制maven-compiler-plugin和maven-surefire-plugin两个插件的行为,即跳过编译,又跳过测试。
指定测试类
mvn test
非mapreduce生成Hfile,然后导入hbase当中
Stark_Summer
map hbase reduce Hfile path实例
最近一个群友的boss让研究hbase,让hbase的入库速度达到5w+/s,这可愁死了,4台个人电脑组成的集群,多线程入库调了好久,速度也才1w左右,都没有达到理想的那种速度,然后就想到了这种方式,但是网上多是用mapreduce来实现入库,而现在的需求是实时入库,不生成文件了,所以就只能自己用代码实现了,但是网上查了很多资料都没有查到,最后在一个网友的指引下,看了源码,最后找到了生成Hfile
jsp web tomcat 编码问题
王新春
tomcat jsp pageEncode
今天配置jsp项目在tomcat上,windows上正常,而linux上显示乱码,最后定位原因为tomcat 的server.xml 文件的配置,添加 URIEncoding 属性:
<Connector port="8080" protocol="HTTP/1.1"
connectionTi