[TOC]
特性
1.事件传递
2.线程调度
3.粘性事件,可以有多个,但需要自己移除
4.顺序事件
使用了静态方法和代理类,代码结构和demo有所不同
1.基础使用方式
注册注销
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
EventBus.register(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
EventBus.unRegister(this);
}
发送、接收
EventBus.post(new Btn3EventBean("msg:按钮3的消息"));
@Subscribe
public void btn3Event1(Btn3EventBean bean) {
show(bean.msg);
}
实现分析
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
}
定义保存注解方法的对象MethodInfo,保存注解方法和所在类对象,invoke用
public class MethodInfo {
//消息Bean类型
public Class type;
//注解方法
public Method method;
public MethodInfo(Class type, Method method) {
this.type = type;
this.method = method;
}
}
定义EventBus类,这是管理类,需要有:
注册注销,参数是类对象
读取类中带注解的方法并保存,参数是类对象
发送消息,参数是消息对象
执行注解方法
//保存带注解的方法
private Map> cacheMap;
public void register(Object getter) {
List list = cacheMap.get(getter);
if (list == null) {
list = findAnnotationMethod(getter);
cacheMap.put(getter, list);
}
}
public void unRegister(Object getter) {
if (cacheMap.containsKey(getter)) {
cacheMap.remove(getter);
}
}
private List findAnnotationMethod(Object getter) {
Log.e(TAG, "寻找带注解方法: " + getter.getClass().getName());
List list = new ArrayList<>();
return list;
}
public void post(Object setter) {
Log.e(TAG, "发送消息: " + setter.getClass().getName());
}
private void invoke() {
}
}
具体实现
启动一个activity时,调用注册register,寻找保存带注解方法(destroy时注销,删除映射),传入类对象,反射获取所有方法,找出带定义好的注解的方法,最好做下规范性验证,没有返回值&没有参数只有1个消息对象,保存类和带注解方法集合的映射
private List findAnnotationMethod(Object getter) {
Log.e(TAG, "寻找带注解方法: " + getter.getClass().getName());
List list = new ArrayList<>();
Class clazz = getter.getClass();
Method[] methods = clazz.getMethods();
for (Method method : methods) {
Subscribe subscribe = method.getAnnotation(Subscribe.class);
if (subscribe == null) {
continue;
}
//方法必须是返回void
if (!"void".equals(method.getGenericReturnType().toString())) {
throw new RuntimeException("method must return void");
}
//方法参数校验
Class[] paramsTypes = method.getParameterTypes();
if (paramsTypes.length != 1) {
throw new RuntimeException("method must has only one params");
}
//方法符合规则,加入缓存
MethodInfo methodInfo = new MethodInfo(paramsTypes[0], method);
list.add(methodInfo);
}
return list;
}
post发送一个消息,参数是消息对象,遍历map保存的所有MethodInfo,如果MethodInfo的消息类型(Class)和要发送的消息类型一致,就调用这个方法,完成消息传递
public void post(final Object setter) {
Log.e(TAG, "发送消息: " + setter.getClass().getName());
Set set = cacheMap.keySet();
for (final Object getter : set) {
List list = cacheMap.get(getter);
if (list != null) {
for (final MethodInfo info : list) {
//判断是否这个类的对象
if (info.type.isAssignableFrom(setter.getClass())) {
execute(info, getter, setter);
}
}
}
}
}
}
private void execute(MethodInfo info, Object getter, Object setter) {
try {
Log.e(TAG, "执行注解方法: " + info.method.getName());
info.method.invoke(getter, setter);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
这里用到反射,getter是方法所在的类对象,setter是消息对象,即注解方法的参数
线程调度实现
参考EventBus和实际场景,定义MethodMode
POSTING:发送者所在的线程
BACKGROUND:如果发送者在主线程,那么使用新线程执行注解方法,否则同POSTING
ASYNC:总是使用新线程执行注解方法
public enum ThreadMode {
POSTING,
MAIN,
BACKGROUND,
ASYNC
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Subscribe {
ThreadMode threadMode() default ThreadMode.POSTING;
}
public class MethodInfo {
//消息类型
public Class type;
//回调线程
public ThreadMode threadMode;
//回调方法
public Method method;
public MethodInfo(Class type, ThreadMode threadMode, Method method) {
this.type = type;
this.threadMode = threadMode;
this.method = method;
}
}
private List findAnnotationMethod(Object getter) {
...
//方法符合规则,加入缓存
MethodInfo methodInfo = new MethodInfo(paramsTypes[0], subscribe.threadMode(), method);
list.add(methodInfo);
}
return list;
}
private Handler handler;
private ExecutorService executorService;
private EventBus() {
cacheMap = new HashMap<>();
handler = new Handler(Looper.getMainLooper());
executorService = Executors.newCachedThreadPool();
}
public void post(final Object setter) {
Log.e(TAG, "发送消息: " + setter.getClass().getName());
Set set = cacheMap.keySet();
for (final Object getter : set) {
List list = cacheMap.get(getter);
if (list != null) {
for (final MethodInfo info : list) {
//判断是否这个类的对象
if (info.type.isAssignableFrom(setter.getClass())) {
switch (info.threadMode) {
case MAIN:
if (Looper.getMainLooper() == Looper.myLooper()) {
invoke(info, getter, setter);
} else {
handler.post(new Runnable() {
@Override
public void run() {
invoke(info, getter, setter);
}
});
}
break;
case POSTING:
invoke(info, getter, setter);
break;
case BACKGROUND:
if (Looper.getMainLooper() == Looper.myLooper()) {
executorService.execute(new Runnable() {
@Override
public void run() {
invoke(info, getter, setter);
}
});
} else {
invoke(info, getter, setter);
}
break;
case ASYNC:
executorService.execute(new Runnable() {
@Override
public void run() {
invoke(info, getter, setter);
}
});
break;
}
}
}
}
}
}
线程调度测试完成,连续发送几百次正常运行
粘性事件实现
EventBus中代码有点多了,将寻找注解方法、发送消息等具体操作放入到代理类EventHelper中去,删除getInstance()改用静态方法对外提供api,所有外部调用的api都在EventBus中
实现分析
需要一个列表保存粘性消息
需要发送粘性消息的方法,参数为消息对象
需要移除粘性消息的方法,参数为消息对象
发送粘性消息时,先匹配找到的注解方法,然后再每次有新类注册进来时,匹配新类中的注解方法
方法可以拒绝粘性消息
具体实现
/**
* 保存粘性事件
*/
private List cacheStickList = new ArrayList<>();
/**
* 发送粘性消息
* @param setter
*/
public static void postStick(Object setter){
helper.post(instance.cacheMap, setter);
if (!instance.cacheStickList.contains(setter)) {
instance.cacheStickList.add(setter);
}
}
/**
* 移除粘性消息
* @param setter
*/
public static void removeStick(Object setter){
if (instance.cacheStickList.contains(setter)) {
instance.cacheStickList.remove(setter);
}
}
在register方法中,增加匹配粘性消息的过程
/**
* 注册类时,与粘性消息匹配,然后在存入映射map
* @param getter 类对象
*/
public static void register(Object getter){
List list = instance.cacheMap.get(getter);
if (list == null) {
list = helper.findAnnotationMethod(getter);
//注册查找完一个类的注解方法后,匹配粘性消息
Map> map = new HashMap<>();
map.put(getter, list);
for (Object setter : instance.cacheStickList) {
helper.post(map, setter);
}
//将查找到的带注解方法放入map
instance.cacheMap.putAll(map);
}
}
Subscribe注解中增加属性refuseStick,是否拒绝接受粘性消息,默认接受,MethodInfo中也增加refuseStick属性
/**
* 执行注解方法
* @param info 方法封装对象
* @param setter 消息对象的封装
*/
private void invoke(MethodInfo info, Object setter) {
try {
if (EventBus.isStick(setter) && info.refuseStick) {
//是粘性消息,方法拒绝粘性消息,则不执行
return;
}
Log.e("------invoke"," priority = " + info.priority);
info.method.setAccessible(true);
info.method.invoke(info.getter, setter);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
测试已完成
顺序事件实现
实现分析
注解中增加优先级属性priority
方法封装MethodInfo中增加priority属性
发送时先全部找到,排序再发送
增加打断方法
具体实现
/**
* 取消事件在不同优先级方法中的传递
* @param setter 事件对象
*/
public static void cancelLowerPriority(Object setter) {
helper.cancelLowerPriority(setter);
}
拆分代理类中的post方法,分为:
查找匹配方法
根据优先级排序,执行
线程调度
反射执行
/**
* 发送消息
* @param setter 消息对象
*/
public void post(Map> cacheMap, final Object setter) {
List matchedMethods = new ArrayList<>();
Set set = cacheMap.keySet();
for (final Object getter : set) {
List list = cacheMap.get(getter);
if (list != null) {
for (final MethodInfo info : list) {
//判断是否这个类的对象
if (info.type.isAssignableFrom(setter.getClass())) {
matchedMethods.add(info);
}
}
}
}
execute(matchedMethods,setter);
}
/**
* 找到所有匹配的注解方法,执行
* 如果是顺序事件,判断是否被取消传递
* @param matchedMethods
* @param setter
*/
private void execute(List matchedMethods,Object setter){
sortByPriority(matchedMethods);
for (int i = 0; i < matchedMethods.size(); i++) {
if(cacheCancelList.contains(setter)){
break;
}
execute(matchedMethods.get(i),setter);
}
cacheCancelList.remove(setter);
}
/**
* 线程调度
*/
private void execute(final MethodInfo info,final Object setter){
switch (info.threadMode) {
...
}
}
/**
* 执行注解方法
* @param info 方法封装对象
* @param setter 消息对象的封装
*/
private void invoke(MethodInfo info, Object setter) {
try {
if (EventBus.isStick(setter) && info.refuseStick) {
//是粘性消息,方法拒绝粘性消息,则不执行
return;
}
Log.e("------invoke"," priority = " + info.priority);
info.method.setAccessible(true);
info.method.invoke(info.getter, setter);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
测试完成 顺序传递事件,不能使用线程调度,否则执行顺序不符合预期
补充
边想边敲,记录前部分可能会和实际有不同, 可以参考demo
测试完成
你可能感兴趣的:(手动实现事件总线框架EventBus)
Figure自研模型Helix发布,人形机器人迈向新纪元?(2)
广拓科技
机器人
Figure自研模型Helix发布,人形机器人迈向新纪元?Helix作为Figure公司自主研发的端到端人形机器人视觉-语言-动作(VLA)通用大模型,在技术层面实现了多项重大突破,为机器人的智能化发展开辟了新的道路。(一)工业领域变革Helix模型在工业领域展现出了巨大的应用潜力,有望引发工业生产方式的深刻变革。目前,Figure公司已与宝马签署合作协议,计划在宝马位于美国南卡罗来纳州的工厂内部
在Spring Boot项目中使用Redisson实现延迟执行
田猿笔记
spring boot spring boot java
提供一个完整的示例,演示如何在SpringBoot项目中使用Redisson实现延迟执行。1.添加Redisson依赖:在你的`pom.xml`文件中添加Redisson的依赖: org.redisson redisson-spring-boot-starter 3.16.42.配置Redisson:在`application.properties`或`application.yml`文件中配置R
工厂模式(分简单工厂模式、工厂方法模式、抽象工厂模式)
田翁野老
C++设计模式(创建型) 简单工厂模式 工厂方法模式 抽象工厂模式 c++
1、工厂模式概述:1.1简单工厂模式:简单工厂模式是一种创建型设计模式,它实现了创建对象的功能,但不使用任何具体类的名称。客户端通过调用工厂类的静态方法来创建一个具体的对象,无需关心对象创建的细节。1.2工厂方法模式:工厂方法模式是一种创建型设计模式,它提供了一个接口,用于创建对象,但将实际创建对象的过程推迟到子类中。这样,工厂方法模式允许在运行时根据需要动态地创建对象。1.3抽象工厂模式:抽象工
EasyX图形库基础使用教程(快速上手)
TT-Kun
Mine C++ EasyX图形库 c语言 c++
文章目录EasyX图形库基础使用教程(快速上手)前言:本文简单详细的介绍了EasyX图形库的常用函数和操作,帮助EasyX的快速上手1、绘制简单的图形窗口1.1头文件1.2创建图形化窗口initgraphy函数closegraph函数1.3窗口坐标2、设置图形窗口属性2.1颜色设置setbkcoloRGBcleardevice刷新3、使用EasyX实现基本绘图功能3.1line画线3.1circl
《C++ 小游戏:简易飞机大战游戏的实现》
TT-Kun
C++ Project Mine c++ 开发语言
文章目录《C++游戏代码解析:简易飞机大战游戏的实现》一、游戏整体结构与功能概述二、各个类和函数的功能分析(一)`BK`类-背景类(二)`hero_plane`类-玩家飞机类(三)`plane_bullet`类-玩家飞机发射的子弹类(四)`enemy_plane`类-敌方飞机类(五)`enemy_bullet`类-敌方飞机发射的子弹类(六)其他重要函数三、完整代码:`Plane.h``Plane.
【Golang 面试题】每日 3 题(六十五)
Pandaconda 的测开之路
# Golang 面试专栏 golang 开发语言 后端 面试 笔记 go 经验分享
✍个人博客:Pandaconda-CSDN博客专栏地址:http://t.csdnimg.cn/UWz06专栏简介:在这个专栏中,我将会分享Golang面试中常见的面试题给大家~❤️如果有收获的话,欢迎点赞收藏,您的支持就是我创作的最大动力193.Gochannel为什么是线程安全的?Gochannel是线程安全的,原因在于channel内部实现了同步机制,它可以保证在多个goroutine之间的
三七互娱游戏策划岗内推
飞300
游戏策划 业界资讯
【游戏策划】【美术设计】【市场推广】【游戏运营类】【技术开发】1、协助完成战斗体验设计,包括动作、特效、镜头等;2、负责战斗资源的需求文档撰写,对最终的战斗表现和打击感负责;3、协助完成职业的设计与制作,进行职业平衡性的调整;4、能够使用开发工具实现和调试战斗效果表现。内推码:DSYN9Z9M
【STL】5.<set/multiset>
零零时
c/c++ c++ 开发语言 算法 学习 数据结构 set multiset
set/multiset前言set/multiset容器一.set构造和赋值和删除二.set容器的大小与交换三.set容器的查找与统计四.set与multiset容器的区别前言stl系列主要讲述有关stl的文章,使用STL可以大大提高程序开发的效率和代码的可维护性,且在算法比赛中,STL可以帮助我们更方便地实现各种算法。提高我们的效率。set/multiset容器要使用set/multiset要头
Java——接口
六七_Shmily
java java python 开发语言
在Java中,接口(Interface)是一种特殊的引用类型,用于定义一组方法的规范(即方法签名),而不包含方法的实现。接口是Java实现多态和抽象的重要机制之一。以下是关于Java接口的详细说明:1.接口的定义接口使用interface关键字定义。它可以包含:抽象方法:没有方法体的方法。默认方法(Java8+):使用default关键字定义,可以有方法体。静态方法(Java8+):使用stati
Vue框架介绍
2301_80148369
vue.js 前端 javascript
一、Vue.js的定义Vue.js是一个开源的前端框架,由尤雨溪(EvanYou)于2014年首次发布。它专注于构建用户界面,允许开发者通过声明式的数据绑定和组件化开发模式来构建复杂的单页面应用(SPA)。Vue.js的设计目标是易于上手和灵活集成,既可以作为小型项目的轻量级库使用,也可以扩展为大型项目的完整框架。二、Vue.js的核心特性响应式数据绑定Vue.js通过响应式系统将数据和视图连接起
防御-day6-内容安全
小许不内卷
安全
一、文件过滤技术这里说的文件过滤技术,是指针对文件的类型进行的过滤,而不是文件的内容。想要实现这个效果,我们的设备必须识别出:承载文件的应用---承载文件的协议很多,所以需要先识别出协议以及应用。文件传输的方向---上传,下载文件的类型和拓展名---设备可以识别出文件的真实类型,但是,如果文件的真实类型无法识别,则将基于后缀的拓展名来进行判断,主要为了减少一些绕过检测的伪装行为。二、内容过滤技术文
第五章:工程化实践 - 第一节 - Tailwind CSS 与前端框架的集成
qianmoQ
Tailwind CSS:现代化开发实战指南 css 前端框架 前端
TailwindCSS可以与各种现代前端框架完美配合。本节将详细介绍如何将TailwindCSS集成到React、Vue和Angular等主流框架中,并介绍相关的最佳实践。React集成基础配置#创建React项目npxcreate-react-appmy-app--templatetypescript#安装TailwindCSSnpminstall-Dtailwindcsspostcssauto
【STL】4.<list>
零零时
c/c++ c++ list 开发语言 算法 数据结构 经验分享 笔记
list前言list容器一.list初始化二.常用函数三.排序总结前言stl系列主要讲述有关stl的文章,使用STL可以大大提高程序开发的效率和代码的可维护性,且在算法比赛中,STL可以帮助我们更方便地实现各种算法。提高我们的效率。list容器要使用list,要包含list头文件list(链表)完成的功能实际上和数据结构中的双向链表是极其相似的,list中的数据元素是通过链表指针串连起来逻辑意义上
DeepSeek预测2030年:全球 50% 的白领工作将由 AI Agent 辅助完成,金融、医疗等专业渗透率超 70%
未来AI编程
DeepSeek入门到精通 人工智能 金融
基于当前技术趋势、行业动态及搜索结果中的关键信息,对未来的发展进行多维度预测,涵盖人工智能、搜索行业、全球经济格局等领域:一、人工智能技术的革命性突破低成本高性能模型的普及DeepSeek-R1等国产大模型通过混合专家架构(MoE)和算法优化,以OpenAI1/70的训练成本实现同等性能,推动AI开发从“重训练”向“重推理”转型。这一模式将加速中小企业和新兴国家进入AI赛道,形成“算力平权”效应。
黑马es数据同步mq解决方案
Gungnirss
elasticsearch 大数据 搜索引擎 rabbitmq
方式一:同步调用优点:实现简单,粗暴缺点:业务耦合度高方式二:异步通知优点:低耦含,实现难度一般缺点:依赖mq的可靠性方式三:监听binlog优点:完全解除服务间耦合缺点:开启binlog增加数据库负担、实现复杂度高利用MQ实现mysql与elasticsearch数据同步利用课前资料提供的hotel-admin项目作为酒店管理的微服务。当酒店数据发生增、删、改时,要求对elasticsearch
RK3568平台(显示篇)显示系统基本概念
嵌入式_笔记
瑞芯微 linux
一.显示系统概述linux内核中包含两类图形显示设备驱动框架:FB设备:Framebuffer图形显示框架;DRM:直接渲染管理器(DirectRenderingManager),是linux目前主流的图形显示框架;在实际场景中,具体选择哪一种图形设备驱动框架取决于我们自己的业务需求。Frambebuffer驱动Frambebuffer驱动具有以下特征:直接控制显卡的帧缓冲区,提供基本的显卡输出功
使用Python实现数组数据转换为Excel表格
嘿何i
python excel pandas 开发语言
在数据分析和处理中,将Python中的数组或列表数据转换为Excel表格是一项常见的任务。本文将详细介绍如何使用Python编程语言和相关库,实现从数组数据到Excel表格的转换过程,包括必要的步骤、代码示例以及实际应用中的注意事项。引言:数组数据到Excel的转换需求在数据科学和工程中,我们经常需要将Python中的数据转换为Excel格式,以便于数据的可视化、共享和进一步分析。Python提供
检测加密货币挖矿活动的异常端口
扫地僧009
大数据安全分析 深度学习 机器学习 安全
以下是基于DeepSeek架构思想实现的服务器异常端口检测案例与代码示例。我们以检测加密货币挖矿活动的异常端口为例,使用无监督学习(自编码器)实现动态基线建模。案例背景某云服务器出现异常流量:正常端口:80(HTTP),443(HTTPS),22(SSH)异常端口:6666(检测到高频TCP长连接,疑似门罗币挖矿流量)目标:通过自编码器学习正常端口行为模式,自动标记6666端口的异常活动。代码实现
协程的基本实现原理详解以及在java中的使用
一个儒雅随和的男子
多线程 java 开发语言
前言接下来是Java中的协程实现。JDK17引入了虚拟线程(Fiber),属于用户态线程,由JVM管理。本文将深度讨论了第三方库如Quasar,Quasar通过字节码增强实现协程,使用Fiber类。并涉及到Kilim等库也是通过字节码生成实现的,以及Kotlin协程的代码示例,通过suspend函数和CoroutineScope管理。详细讲解了NtyCo库的实现,包括上下文切换和调度器。需要注意,
【go语言之http server源码分析】
不爱学习的王小小
golang http java
go语言之http源码分析go原生服务端ListenAndServeservereadRequeststartBackgroundReadfinishRequest在前面的文章go实现tcp升级到http中描述了如何从tcp升级到http。熟悉tcp都是知道,实现tcp需要socket,bind,listen,然后accept。然后对于io来说,有阻塞,非阻塞,多路复用,异步几种模式。对于阻塞和非
程序员初识宏观经济学
猿脑2.0
python
这是宏观经济学学习、核心内容概括、数据资源及实际作用的系统性总结:一、宏观经济学学习框架1.核心知识模块模块关键内容基础理论-国民收入核算(GDP、GNP)-总需求与总供给模型(AD-AS)-IS-LM模型与货币政策传导经济增长-索洛增长模型-内生增长理论(知识、技术的作用)-中国经济增长模式与挑战经济周期-经济波动的原因(需求冲击、供给冲击)-实际经济周期(RBC)与新凯恩斯主义理论失业与通胀-
程序员读点微观经济学
猿脑2.0
python
微观经济学学习路径、核心内容、数据来源、实际作用及案例实践的系统性总结:一、微观经济学学习框架1.核心知识模块模块关键内容基础理论-供需理论(均衡价格、弹性分析)-消费者行为(效用最大化、无差异曲线)-生产者行为(成本曲线、利润最大化)市场结构-完全竞争市场-垄断与寡头(价格歧视、博弈论)-垄断竞争(产品差异化)市场失灵与政策-外部性(污染、补贴)-公共物品与搭便车问题-信息不对称(逆向选择、道德
flowable设置流程回退到指定节点
猿脑2.0
python
Flowable是一个轻量级业务流程管理框架,支持BPMN(业务流程模型和符号)标准。在Flowable中实现流程回退到指定节点,可以通过以下几种方式:1.使用BoundaryEvent和IntermediateThrowEvent这种方式适用于在设计流程图时就考虑到了可能的回退情况。BoundaryEvent:可以添加一个BoundaryEvent到指定的任务上,用来捕获一个特定的事件(比如,错
架构师论文《论湖仓一体架构及其应用》
pccai-vip
架构 软考论文
软考论文-系统架构设计师摘要作为某省级商业银行数据中台建设项目技术负责人,我在2020年主导完成了从传统数据仓库向湖仓一体架构的转型。针对日益增长的支付流水、用户行为埋点及信贷审核影像文件等多模态数据处理需求,原有系统存在存储成本激增、实时分析能力不足等问题。新平台需整合12个核心业务系统数据资源,建设支持实时反欺诈、客户画像分析的高性能数据底座。本项目采用Iceberg+Spark架构实现湖仓一
深入剖析C语言中strstr函数的构建与实现
共享家9527
c语言
在C语言的字符串处理领域,strstr函数是一个非常实用的工具,它用于在一个字符串中查找另一个子字符串的首次出现位置。理解strstr函数的内部实现机制,不仅有助于我们更高效地使用它,还能加深对字符串处理算法的理解。今天,就让我们一起来深入探讨strstr函数的构建过程。一、strstr函数的功能与原型strstr函数的功能是在一个主字符串中查找一个子字符串的首次出现位置。如果找到,返回指向子字符
七.智慧城市数据治理平台架构
moton2017
大数据治理 大数据 数据架构 数据库 数据治理 大数据治理 数据分析 智慧城市数据治理
一、整体架构概览智慧城市数据治理平台架构描绘了一个全面的智慧城市数据治理平台,旨在实现城市数据的统一管理、共享和应用,为城市运行、管理和决策提供数据支撑。整体架构呈现出分层、模块化、集约化的特点,并强调数据安全和标准规范。智慧城市数据治理平台架构二、核心模块解析1.城市驾驶舱统一数据管理门户:作为数据资源的统一入口,提供数据检索、申请、使用等服务。公共数据开放门户:向社会开放公共数据,支持数据目录
OKHttp 3.10源码解析(四):连接机制
十 月
开源框架 Android
OKhttp的底层用的是Socket连接而不是URLConnection,所以整体来说还是比较复杂的,涉及到Http协议的封装和解封装、TLS/SSL安全协议的封装、Http2的封装等等,但还是非常值得我们去学习一下的,本篇文章不会对这些底层原理有详细的解析,但读完之后至少大概知道Http请求的底层是如何实现的一.HTTP请求的优化1.keep-alive机制我们知道,一个HTTP的请求需要经过三
Metasploit Pro 4.22.7-2025022001 发布,新增功能概览
metasploit
MetasploitPro4.22.7-2025022001(Linux,Windows)-专业渗透测试框架Rapid7Penetrationtesting,releasedFeb20,2025请访问原文链接:https://sysin.org/blog/metasploit-pro-4/查看最新版。原创作品,转载请保留出处。作者主页:sysin.org世界上最广泛使用的渗透测试框架知识就是力量,
销售易Neo CRM vs 金蝶云星空CRM:谁更适合你的企业?
saas
在当今竞争激烈的CRM市场中,销售易NeoCRM和金蝶云星空CRM作为国内知名的CRM解决方案,各自拥有独特的优势和特点。本文将从功能、用户体验、价格、市场评价以及适用场景等方面对这两款CRM系统进行对比总结和盘点。一、功能对比•销售易NeoCRM:o销售管理:提供从线索获取、商机管理到订单成交的完整销售漏斗管理,实现销售过程的标准化管理。o客户管理:提供全方位的客户画像功能,记录和追踪客户的所有
6款Vue后台管理系统模板
前端
收录一些开箱即用、使用简单、界面美观、功能强大的前端框架,帮助我们后端程序员快速提高学习、工作开发效率(注意:排名不分先后,都是十分优秀的开源前端框架和项目)。收录地址:https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2FYSG...vue-element-adminvue-element-admin是一个后台前端解决方案,它基于vu
jdk tomcat 环境变量配置
Array_06
java jdk tomcat
Win7 下如何配置java环境变量
1。准备jdk包,win7系统,tomcat安装包(均上网下载即可)
2。进行对jdk的安装,尽量为默认路径(但要记住啊!!以防以后配置用。。。)
3。分别配置高级环境变量。
电脑-->右击属性-->高级环境变量-->环境变量。
分别配置 :
path
&nbs
Spring调SDK包报java.lang.NoSuchFieldError错误
bijian1013
java spring
在工作中调另一个系统的SDK包,出现如下java.lang.NoSuchFieldError错误。
org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.l
LeetCode[位运算] - #136 数组中的单一数
Cwind
java 题解 位运算 LeetCode Algorithm
原题链接:#136 Single Number
要求:
给定一个整型数组,其中除了一个元素之外,每个元素都出现两次。找出这个元素
注意:算法的时间复杂度应为O(n),最好不使用额外的内存空间
难度:中等
分析:
题目限定了线性的时间复杂度,同时不使用额外的空间,即要求只遍历数组一遍得出结果。由于异或运算 n XOR n = 0, n XOR 0 = n,故将数组中的每个元素进
qq登陆界面开发
15700786134
qq
今天我们来开发一个qq登陆界面,首先写一个界面程序,一个界面首先是一个Frame对象,即是一个窗体。然后在这个窗体上放置其他组件。代码如下:
public class First { public void initul(){ jf=ne
Linux的程序包管理器RPM
被触发
linux
在早期我们使用源代码的方式来安装软件时,都需要先把源程序代码编译成可执行的二进制安装程序,然后进行安装。这就意味着每次安装软件都需要经过预处理-->编译-->汇编-->链接-->生成安装文件--> 安装,这个复杂而艰辛的过程。为简化安装步骤,便于广大用户的安装部署程序,程序提供商就在特定的系统上面编译好相关程序的安装文件并进行打包,提供给大家下载,我们只需要根据自己的
socket通信遇到EOFException
肆无忌惮_
EOFException
java.io.EOFException
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2281)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:
基于spring的web项目定时操作
知了ing
java Web
废话不多说,直接上代码,很简单 配置一下项目启动就行
1,web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="h
树形结构的数据库表Schema设计
矮蛋蛋
schema
原文地址:
http://blog.csdn.net/MONKEY_D_MENG/article/details/6647488
程序设计过程中,我们常常用树形结构来表征某些数据的关联关系,如企业上下级部门、栏目结构、商品分类等等,通常而言,这些树状结构需要借助于数据库完成持久化。然而目前的各种基于关系的数据库,都是以二维表的形式记录存储数据信息,
maven将jar包和源码一起打包到本地仓库
alleni123
maven
http://stackoverflow.com/questions/4031987/how-to-upload-sources-to-local-maven-repository
<project>
...
<build>
<plugins>
<plugin>
<groupI
java IO操作 与 File 获取文件或文件夹的大小,可读,等属性!!!
百合不是茶
类 File
File是指文件和目录路径名的抽象表示形式。
1,何为文件:
标准文件(txt doc mp3...)
目录文件(文件夹)
虚拟内存文件
2,File类中有可以创建文件的 createNewFile()方法,在创建新文件的时候需要try{} catch(){}因为可能会抛出异常;也有可以判断文件是否是一个标准文件的方法isFile();这些防抖都
Spring注入有继承关系的类(2)
bijian1013
java spring
被注入类的父类有相应的属性,Spring可以直接注入相应的属性,如下所例:1.AClass类
package com.bijian.spring.test4;
public class AClass {
private String a;
private String b;
public String getA() {
retu
30岁转型期你能否成为成功人士
bijian1013
成长 励志
很多人由于年轻时走了弯路,到了30岁一事无成,这样的例子大有人在。但同样也有一些人,整个职业生涯都发展得很优秀,到了30岁已经成为职场的精英阶层。由于做猎头的原因,我们接触很多30岁左右的经理人,发现他们在职业发展道路上往往有很多致命的问题。在30岁之前,他们的职业生涯表现很优秀,但从30岁到40岁这一段,很多人
【Velocity四】Velocity与Java互操作
bit1129
velocity
Velocity出现的目的用于简化基于MVC的web应用开发,用于替代JSP标签技术,那么Velocity如何访问Java代码.本篇继续以Velocity三http://bit1129.iteye.com/blog/2106142中的例子为基础,
POJO
package com.tom.servlets;
public
【Hive十一】Hive数据倾斜优化
bit1129
hive
什么是Hive数据倾斜问题
操作:join,group by,count distinct
现象:任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成;查看未完成的子任务,可以看到本地读写数据量积累非常大,通常超过10GB可以认定为发生数据倾斜。
原因:key分布不均匀
倾斜度衡量:平均记录数超过50w且
在nginx中集成lua脚本:添加自定义Http头,封IP等
ronin47
nginx lua csrf
Lua是一个可以嵌入到Nginx配置文件中的动态脚本语言,从而可以在Nginx请求处理的任何阶段执行各种Lua代码。刚开始我们只是用Lua 把请求路由到后端服务器,但是它对我们架构的作用超出了我们的预期。下面就讲讲我们所做的工作。 强制搜索引擎只索引mixlr.com
Google把子域名当作完全独立的网站,我们不希望爬虫抓取子域名的页面,降低我们的Page rank。
location /{
java-3.求子数组的最大和
bylijinnan
java
package beautyOfCoding;
public class MaxSubArraySum {
/**
* 3.求子数组的最大和
题目描述:
输入一个整形数组,数组里有正数也有负数。
数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。
求所有子数组的和的最大值。要求时间复杂度为O(n)。
例如输入的数组为1, -2, 3, 10, -4,
Netty源码学习-FileRegion
bylijinnan
java netty
今天看org.jboss.netty.example.http.file.HttpStaticFileServerHandler.java
可以直接往channel里面写入一个FileRegion对象,而不需要相应的encoder:
//pipeline(没有诸如“FileRegionEncoder”的handler):
public ChannelPipeline ge
使用ZeroClipboard解决跨浏览器复制到剪贴板的问题
cngolon
跨浏览器 复制到粘贴板 Zero Clipboard
Zero Clipboard的实现原理
Zero Clipboard 利用透明的Flash让其漂浮在复制按钮之上,这样其实点击的不是按钮而是 Flash ,这样将需要的内容传入Flash,再通过Flash的复制功能把传入的内容复制到剪贴板。
Zero Clipboard的安装方法
首先需要下载 Zero Clipboard的压缩包,解压后把文件夹中两个文件:ZeroClipboard.js
单例模式
cuishikuan
单例模式
第一种(懒汉,线程不安全):
public class Singleton { 2 private static Singleton instance; 3 pri
spring+websocket的使用
dalan_123
一、spring配置文件
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.or
细节问题:ZEROFILL的用法范围。
dcj3sjt126com
mysql
1、zerofill把月份中的一位数字比如1,2,3等加前导0
mysql> CREATE TABLE t1 (year YEAR(4), month INT(2) UNSIGNED ZEROFILL, -> day
Android开发10——Activity的跳转与传值
dcj3sjt126com
Android开发
Activity跳转与传值,主要是通过Intent类,Intent的作用是激活组件和附带数据。
一、Activity跳转
方法一Intent intent = new Intent(A.this, B.class); startActivity(intent)
方法二Intent intent = new Intent();intent.setCla
jdbc 得到表结构、主键
eksliang
jdbc 得到表结构、主键
转自博客:http://blog.csdn.net/ocean1010/article/details/7266042
假设有个con DatabaseMetaData dbmd = con.getMetaData(); rs = dbmd.getColumns(con.getCatalog(), schema, tableName, null); rs.getSt
Android 应用程序开关GPS
gqdy365
android
要在应用程序中操作GPS开关需要权限:
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
但在配置文件中添加此权限之后会报错,无法再eclipse里面正常编译,怎么办?
1、方法一:将项目放到Android源码中编译;
2、方法二:网上有人说cl
Windows上调试MapReduce
zhiquanliu
mapreduce
1.下载hadoop2x-eclipse-plugin https://github.com/winghc/hadoop2x-eclipse-plugin.git 把 hadoop2.6.0-eclipse-plugin.jar 放到eclipse plugin 目录中。 2.下载 hadoop2.6_x64_.zip http://dl.iteye.com/topics/download/d2b
如何看待一些知名博客推广软文的行为?
justjavac
博客
本文来自我在知乎上的一个回答:http://www.zhihu.com/question/23431810/answer/24588621
互联网上的两种典型心态:
当初求种像条狗,如今撸完嫌人丑
当初搜贴像条犬,如今读完嫌人软
你为啥感觉不舒服呢?
难道非得要作者把自己的劳动成果免费给你用,你才舒服?
就如同 Google 关闭了 Gooled Reader,那是
sql优化总结
macroli
sql
为了是自己对sql优化有更好的原则性,在这里做一下总结,个人原则如有不对请多多指教。谢谢!
要知道一个简单的sql语句执行效率,就要有查看方式,一遍更好的进行优化。
一、简单的统计语句执行时间
declare @d datetime ---定义一个datetime的变量set @d=getdate() ---获取查询语句开始前的时间select user_id
Linux Oracle中常遇到的一些问题及命令总结
超声波
oracle linux
1.linux更改主机名
(1)#hostname oracledb 临时修改主机名
(2) vi /etc/sysconfig/network 修改hostname
(3) vi /etc/hosts 修改IP对应的主机名
2.linux重启oracle实例及监听的各种方法
(注意操作的顺序应该是先监听,后数据库实例)
&nbs
hive函数大全及使用示例
superlxw1234
hadoop hive函数
具体说明及示例参 见附件文档。
文档目录:
目录
一、关系运算: 4
1. 等值比较: = 4
2. 不等值比较: <> 4
3. 小于比较: < 4
4. 小于等于比较: <= 4
5. 大于比较: > 5
6. 大于等于比较: >= 5
7. 空值判断: IS NULL 5
Spring 4.2新特性-使用@Order调整配置类加载顺序
wiselyman
spring 4
4.1 @Order
Spring 4.2 利用@Order控制配置类的加载顺序
4.2 演示
两个演示bean
package com.wisely.spring4_2.order;
public class Demo1Service {
}
package com.wisely.spring4_2.order;
public class