博客迁移
[2024-03-05 更新] 由于2023年10月份的 语雀P0级事故宕机8小时 事件,开始考虑博客的私有化部署方案。现已将博客内容全部迁移至 yupaits-notes 网站,后续文章将会发布至该网站,敬请期待。
[2020-08-23 更新] 由于个人博客维护起来比较耗费精力,后续技术博客内容将在 语雀平台 的知识库进行发布,同时已有的技术博客文章均已迁移完毕。
开发实战总结
总结了一些实际开发过程中需要注意的一些细节。(持续更新…)
MySQL
使用st_distance_sphere函数获取指定地点周边一定范围内的所有地点。
例如:district表中保存了各个城市(city_code)的经纬度信息(longitude、latitude),使用以下sql查询上海市(121.797447, 31.166809)周边300公里内的城市
123select distinct city_code, st_distance_sphere(Point(longitude, latitude), Point(121.797447, 31.166809)) as distance from district where st_distance_sphere(Point(longitude, latitude), Point(121.797447, 31.166809)) < 300000;
SQL join语法速记:
A inner join B on ... 取A和B的交集
A left join B on ... 取A全部,B没有的对应 ...
常见异常解决方案总结
本文是对日常代码开发调试过程中发现的一些常见异常的解决方法进行归纳,避免重复踩坑。
Java/Spring
Caused by: com.alibaba.fastjson.JSONException: default constructor not found.
解决方案:解析的目标类增加无参构造方法。
使用 frontend-maven-plugin 进行maven打包时出现以下错误:
Failed to execute goal com.github.eirslett:frontend-maven-plugin:1.6:install-node-and-npm (install node and npm) on project spider-web: Could not extract the npm archive: Could not extract archive: 'C:\Users\xxx\.m2\repository\com\github\eirslett\npm\5.7.1\npm-5.7.1.tar.gz': EOFExcept ...
Java流式API
Java8中新增了Stream接口定义了支持顺序和并行操作元素序列操作的一系列标准方法。
为了执行计算,流操作被组合成一个流管道。 流管道由源(可能是数组、集合、生成器函数、I/O 通道等)、零个或多个中间操作(将流转换为另一个流,例如filter(Predicate) ) 和终端操作(产生结果或副作用,例如count()或forEach(Consumer) )。 流是懒惰的; 对源数据的计算仅在终端操作启动时进行,源元素仅在需要时消费。
集合和流虽然有一些表面上的相似之处,但有不同的目标。 集合主要涉及对其元素的有效管理和访问。 相比之下,流不提供直接访问或操作其元素的方法,而是关注声明性地描述它们的源以及将在该源上聚合执行的计算操作。 但是,如果提供的流操作没有提供所需的功能,则可以使用iterator()和spliterator()操作来执行受控遍历。
流管道,可以看作是对流源的查询。 除非源明确设计用于并发修改(例如ConcurrentHashMap ),否则在查询流源时修改流源可能会导致不可预测或错误的行为。大多数流操作都接受描述用户指定行为的参数,例如上面示例 ...
yutool简介
简介yutool是一款组件式集成开发框架,提供了许多为了解决实际后端web服务问题的一些通用设计及其实现,开箱即用,按需整合。
模块划分yutool的模块主要分为两大部分:组件和插件。以下是其主要特点和当前已整合的组件和插件清单。部分组件和插件的设计思路可参考博客《基础组件设计》。
组件:将业务系统中比较复杂的公共逻辑抽象成可扩展的公共组件,方便应用程序快速接入,约定大于配置,使用时需要遵循组件的设计规范。
插件:轻量级,非必需,按需引入,灵活可扩展。
组件
组件
名称
主要特性
完成度
yutool-cache
缓存组件
支持二级缓存(本地缓存和分布式缓存),通过缓存注解控制缓存的刷新和过期
√
yutool-file-server
文件服务
文件的上传下载,支持租户隔离、防盗链
√
yutool-ldap
LDAP组件
主流的LDAP服务接入
yutool-mq
消息组件
消息队列,支持延迟队列、重试队列(目前仅支持RabbitMQ)
√
yutool-orm
ORM组件
整合了Spirng生态主流的Mybatis Plus和JPA框架,并加入了实际 ...
Java的Lambda表达式与函数式接口
Lambda表达式Java8开始支持lambda表达式,其结构为:
123(param1, param2, param3...) -> { // 执行体}
lambda表达式是函数式接口的具体实现,用于创建一个匿名类对象。
什么是匿名类?
Java中可以实现一个类包含另一个类,且不需要提供任何的类名直接实例化。匿名类主要用于创建一个对象执行特定的任务,使代码更加简洁。匿名类是不能有类名的类,不能被引用,只能在创建时用new语句来声明。其语法格式如下:
1234567class OuterClass { // 定义一个匿名类 Type obj1 = new Type() { // 匿名类代码 }}
Java8的::运算符用于方法引用,是lambda表达式的一种简写方式。具体为,当需要使用lambda表达式只调用一个已存在的方法时,就可以使用::运算符。
以下是方法引用的一些语法:
方法引用类型
语法
示例
静态方法引用
${className ...
消息中间件
消息中间件消息队列使用场景消息队列常见的使用场景,核心的有3个:解耦、异步、削峰。
解耦看这么个场景。A系统发送数据到BCD三个系统,通过接口调用发送。如果E系统也要这个数据呢?那如果C系统现在不需要了呢?A系统负责人几乎崩溃……
在这个场景,A系统跟其他各种乱七八糟的系统严重耦合,A系统产生一条比较关键的数据,很多系统都需要A系统将这个数据发送过来。A系统要时时刻刻考虑BCDE四个系统如果挂了该怎么办?要不要重发,要不要把消息存起来?
如果使用MQ,A系统产生一条数据,发送到MQ里面去,哪个系统需要数据自己去MQ里消费。如果新系统需要数据,直接从MQ里消费即可;如果某个系统不需要这条数据了,就取消对MQ的消费即可。这样下来,A系统就不需要考虑要给谁发送数据,不需要维护这个代码,也不需要考虑是否调用成功、失败超时等情况。
总结:通过一个MQ,Pub/Sub发布订阅消息这么一个模型,A系统就跟其它系统彻底解耦了。
异步再来看一个场景,A系统接收一个请求,需要在自己本地写库,还需要再BCD三个系统写库,自己本地写库要3ms,BCD三个系统分别写库要300ms、450ms、20 ...
通用可编排状态机引擎设计
参考文档:《高德打车通用可编排订单状态机引擎设计》
问题背景日常的业务开发工作中经常会遇到各种状态流转的场景,其中不乏一些状态多、链路长、逻辑复杂的情况,还存在多场景、多类型、多业务维度等业务特性。在保证状态流转稳定性的前提下,可扩展性和可维护性是我们需要重点关注和解决的问题。
当状态、类型、场景,以及其他一些维度组合时,每一种组合都可能会有不同的处理逻辑,也可能会存在共性的业务逻辑,这种情况下代码中各种if-else肯定是无法想象的。如何有效处理这种“多状态+多类型+多场景+多维度”的复杂状态流转业务,同时能保证整个系统的可扩展性和可维护性?
实现方案要解决“多状态+多类型+多场景+多维度”的复杂状态流转业务,我们从纵向和横向两个维度进行设计。纵向主要从业务隔离和流程编排的角度出发解决问题,而横向主要从逻辑复用和业务扩展的角度解决问题。
一、纵向解决业务隔离和流程编排状态模式解决多维度组合业务场景的业务隔离通常我们处理一个多状态或者多维度的业务逻辑,都会采用状态模式或者策略模式来结局,其核心其实可以概括为一个词“分而治之”,抽象一个基础逻辑接口、每一个状态或者类型都实现该接口,业务处 ...
历史数据清理
实现方式采用任务调度中心(如:xxl-job, saturn等)+ Java定时任务的方式,清理的时候可以通过动态配置要清理的表及数据范围,以实现灵活地进行历史数据地清除或者转移。
历史数据清理配置参数说明
参数
说明
默认值
备注
saveHistory
是否保存至历史表
否
设为true,会按预设的格式新建或者匹配到已存在的历史数据表,并将清理的数据转移到该历史数据表中。
dataSource
数据源
指定待清理数据所在的数据源标识
tableName
待清理数据表名
指定要清理那张表的数据
fieldName
时间索引字段名
指定按照那个字段来按时间范围进行清理,该字段必须是DATETIME类型并且已经创建了索引
keepDays
保留最近几天的数据
指定要保留几天的数据,在此之前的数据会被清理掉
batchSize
批量删除记录数
3000
清理的数据量大时,通过分批的方式进行删除,每批删除的数量
extraConditions
额外查询条件
用于限制待清理表的数据范围
historyTablePrefix
历史数据表名前缀
指 ...
分布式锁
背景在实际的开发工作中,有一些场景会使用到分布式锁,用于控制分布式系统多个节点同一时间只能有一个节点执行目标方法,解决了多节点同时执行导致的数据不一致、数据重复等问题。
实现方式使用Spring Boot Starter技术开发基于Redis的可插拔式分布式锁组件,采用注解+切面的方式将分布式锁自身的控制逻辑与业务代码解耦,侵入性小,使用起来更加简便。
分布式锁的设计
多个节点执行同一个目标方法时,方法想要获取分布式锁Redis Key相同的多个节点才会受同一个分布式锁的控制。
为了避免某个节点拿到锁执行代码逻辑时宕掉,锁无法释放导致其他节点一直拿不到锁,需要设置锁的过期时间,过期后自动释放掉。
由于网络连接不稳定导致节点获取不到锁时,需要通过重试机制来进行获取。
特殊情况下,有多个方法使用同一个锁,例如方法A和方法B都是比较耗时的计算任务,并且受同一个分布式锁控制,其中方法A自身是需要支持多节点并发计算用于提高处理速度,此时可以通过设计分布式锁的排他性并结合重试之后是否执行方法内的代码逻辑,以满足此种场景的要求。
分布式锁配置参数说明分布式锁相关的配置参数说明如下:
...
GoF的23种设计模式的分类和功能
设计模式分类设计模式有两种分类方法,即根据模式的目的来分和根据模式的作用范围来分。
1. 根据目的分类根据模式是用来完成什么工作来划分,这种方式可分为创建型模式、结构型模式和行为型模式3种。
创建型模式:用于描述”怎样创建对象”,它的主要特点是“将对象的创建与使用分离”。
结构型模式:用于描述如何将类或对象按某种布局组成更大的结构。
行为型模式:用于描述类或对象之间怎样互相协作共同完成单个对象都无法单独完成的任务,以及怎样分配职责。
2. 根据作用范围分类根据模式是主要用于类上还是主要用于对象上来分,这种方式可分为类模式和对象模式两种。
类模式:用于处理类与子类之间的关系,这些关系通过集成来建立,是静态的,在编译时便确定下来了。
对象模式:用于处理对象之间的关系,这些关系可以通过组合或聚合来实现,在运行时刻是可以变化的,更具动态性。
范围/目的
创建型模式
结构型模式
行为型模式
类模式
工厂方法
(类)适配器
模板方法;解释器
对象模式
单例;原型;抽象工厂;建造者
代理;(对象)适配器;桥接;装饰;外观;享元;组合
策略;命令;职责链;状 ...
设计模式概述
软件设计模式的概念和意义1. 软件设计模式的概念软件设计模式(Software Design Pattern),又称设计模式,是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。它描述了在软件设计过程中的一些不断重复发生的问题,以及该问题的解决方案。也就是说,它是解决特定问题的一系列套路,是前辈们的代码设计经验的总结,具有一定的普遍性,可以反复使用。其目的是为了提高代码的可重用性、代码的可读性和代码的可靠性。
2. 学习设计模式的意义设计模式的本质是面向对象设计原则的实际运用,是对类的封装性、继承性和多态性以及类的关联关系和组合关系的充分理解。 正确使用设计模式具有以下优点。
可以提高程序员的思维能力、编程能力和设计能力。
使程序设计更加标准化、代码编制更加工程化,使软件开发效率大大提高,从而缩短软件的开发周期。
使设计的代码可重用性高、可读性强、可靠性高、灵活性好、可维护性强。
软件设计模式的基本要素软件设计模式使人们可以更加简单方便地复用成功的设计和体系结构,它通常包含以下几个基本要素:模式名称、别名、动机、问题、解决方案、效果、结构、模式角色、合作关系、实现方 ...
30张图看懂《SCRUM捷径》
原文地址:30张图看懂《SCRUM捷径》 转载
《SCRUM捷径》可谓是经典中的经典,语言质朴,中文版的翻译质量也很高,没有任何长篇大论。文中Ilan 根据多年经验,用30个捷径来阐明组织如何能更好地实践Scrum这个轻量级框架。我在多次阅读过程中,对照近年走过的弯路,觉得字字玑珠,每次都能产生更加深刻的共鸣。之所以有这样的体会,是因为这些捷径我们大多数都听说过;说它不容易,是因为这世间有太多的道理知易行难。以下图片均是原创,文字多数出自中文翻译本,或精简、或摘抄、或提炼、或重排,虽仁者见仁,智者见智,但初衷仍是尊重作者观点,以期透过30张图一窥书中精彩。
#SCRUM捷径1# 虽然SCRUM不难推,但如何高效实施为自己打的广告牌撑腰,是完全不同的故事。即使已经设法建立了基本的SCRUM设置,但如果想把团队培养成“SCRUM法拉利”而不是”夏利”,则需要耐心、开放的心态、教训以及方便实用的经验指导!
#SCRUM捷径2# 几个Sprint的误用模式:第一、单独的测试Sprint. 第二、没完没了的Sprint0. 第三、长短不一的Sprint.
#SCRU ...
中通安全合规之人员安全实践
原文地址:中通安全合规之人员安全实践 转载
背景5月13日正式发布的“等保2.0”成为了最近安全圈子里的大新闻,同时也将等保和ISO27001等信息安全标准带上了新热度。作为国家关键信息基础设施企业,中通快递同样实施了等保,在实施等保的过程中我们系统地学习了信息安全管理体系,其中人员安全和合规是重要的组成部分。作为一家拥有几十万员工的企业,毫无疑问人是中通非常宝贵的资源,但同时人也是信息安全极其重要的要素,因此企业的人员安全和合规就显得尤为重要。
从生命周期的方法论来看,企业员工在企业内同样需要按照生命周期进行安全管理。从人员的入职到离职,在整个生命周期都应当伴随着人员安全管理。为了更好地保障人员安全和合规,中通安全围绕着企业人员的生命周期做了一些实践,在整个人员生命周期内针对不同的人员安全风险设计了安全流程,完成了整个人员安全生命周期的管理,大大降低了人员安全的风险。
企业人员安全的生命周期中通安全目前将人员安全生命周期分为三个阶段:人员入职阶段、人员在职阶段、人员离职阶段。在人员入职阶段主要对人员历史信息进行检查、设置入职门槛、避免问题人员的流入。在人员在职阶段,中通安全秉承 ...
互联网黑产:那些职业羊毛党到底如何月赚几十万?
原文地址:互联网黑产:那些职业羊毛党到底如何月赚几十万? 转载
世界上有没有一种职业
可以用最少成本赚最多的钱?
可以用最少时间获得最多的回报?
可以没有技能赚得却比有颜有才的人多?
甚至可以在四五线城市赚一二线城市的钱?
看这篇文章之前,相信你和我之前的答案一样,掷地有声两个字:“没有”,因为不劳而获躺赚都是骗人的。但看完文章,相信你也会和我一样感慨:“原来还真有”。
今天,我们就给大家介绍一群 生存在互联网灰色地带的职业羊毛党,他们有组织有纪律有完整产业上下游的去利用一些大型互联网公司的运营规则甚至漏洞,套取各种补贴和奖金,少的月收入一两万,多的月赚几十万。
这些人一般活跃在什么平台?有哪些曾经或现在很常见的薅羊毛手段?给你介绍五种。
1、套取新用户补贴,年收入百万要说这群职业羊毛党从什么时候就开始有了,应该就是从大型互联网公司有新用户补贴那天开始。
所以我们介绍的第一种方法就是 套取新用户补贴,这也是一种行之有效的手段。
一般情况下,一款App新用户注册都有补贴,多数是使用门槛很低的优惠券,比如买10块钱的东西就能减9块。如果用户每次买东西都想要优惠,那么每次用新手机号 ...
如何避免「三分钟热度」,找到人生的「热爱」
原文地址:如何避免「三分钟热度」,找到人生的「热爱」 转载
1. 很多人说,自己做事总“三分钟热度”。
从心理学角度看,什么是“三分钟热度”?
下面这张图是心理学家米哈里·契克森米哈赖的心流通道模型。
它正好描绘了一个人从事一项活动时,随着技巧的提升和挑战的增长,他对这项活动的体验发生了什么变化。
假设这张图所描绘的是小明打网球的情景。
刚开始时,小明不懂任何技巧,他唯一的挑战是把球打过去,这是A1。这种挑战没什么了不起,但小明还是打得很愉快,因为难度正适合他粗浅的技巧,但愉快的感觉不会持续太久。
这个阶段,小明所感受到的愉快,就是刚接触一项新事物时的“前三分钟热度”。
接下来又发生了什么,让小明的“热度”消失了呢?
原来,经过一段时间练习,他的技巧进步了,原先只是把球打过去的挑战,对他来说太小儿科了,于是他感到厌倦,这时,小明所处的阶段就是A2。
又或者,他碰到了比他熟练的对手,使他发现要接住对方的球是个挑战,这时,他对自己拙劣的技巧产生了焦虑,这时,小明所处的阶段就是A3。
前三分钟热度,是刚接触新事物时的浅层乐趣,这种乐趣,会随着你在这项活动中的不断深入而消失。
随 ...
技术人具备“结构化思维”意味着什么?
原文地址:技术人具备“结构化思维”意味着什么? 转载
阿里妹导读:在日常工作中,我们时常会碰到这样的情况,有的人讲事情逻辑非常混乱,罗列了很多事项,却把握不到重点,无法把一件事情说清楚。这种思维混乱是典型的缺少结构化思维的表现。结构化思维非常重要,不仅仅体现在表达上,也体现在在我们分析问题的过程中。具备结构化思维,才能将问题分析地更全面、更深刻。
什么是结构化思维?那么到底是什么是结构化思维呢?简单来说,结构化思维的定义就是:逻辑+套路。
表达要有逻辑所谓逻辑是指我们的结构之间必须是有逻辑关系的。例如,你说话的时候用“第一、第二、第三”这个逻辑顺序是合理的,但是,用“第一,第二,第四”就会显得很奇怪。当然,即使你用了”一、二、三”,也不一定就意味着你的内容有逻辑关系。想让内容有逻辑关系,我们要学会四种组织思想的逻辑关系:
1)演绎(因果)顺序:“大前提、小前提、结论”的演绎推理方式就是演绎顺序。比如,经典三段论:所有人都要死,苏格拉底是人,苏格拉底要死。
2)时间(步骤)顺序:“第一、第二、第三”,“首先、然后、再者”等,很多的时间顺序同时也是因果顺序。
3)空间(结构)顺序 ...
大家在寻找的高级程序员到底是什么样子的?
原文地址:大家在寻找的高级程序员到底是什么样子的? 转载
我们的中国文化,对“面子”看的特别重,所以你会发现身边到处都是高级XXX,听着倍儿有面子,程序员也不例外。
但是你真要问每个人,你认为的高级XXX是什么样子的。估计每个人都有不同的回答。
我还记得在我刚开始从事编程工作的时候,对坐在边上不远的那位我心目中的高级程序员的印象是:
工作至少有6、7年以上,能写一个用起来很方便、看起来很牛逼、但是不太容易让初级人员看懂的框架。
前两天,我把这个问题丢到群里,大家给出的答案中,占比最高的是以下几个。
有 N 年以上编程经验(大部分都说5年以上)
有出版过技术图书
对某领域内对常用框架原理有了解,并且实际使用超过2年
可以随时随地快速写出常见的一些算法
至少封装过一个被全局使用的开发框架
写出来的代码,阅读起来很好理解
能带领其他人员成功完成项目
你看,这件事对大家来说就是常说的,“一千个人眼中有一千个哈姆雷特”。
不过这也正常,毕竟像初级、中级、高级这种高度抽象的词汇,想要得到一个可描述的定义与人交流,必然需要夹杂着个人的主观因素。
但是很多行业都在这么进行分类,自然有它的 ...
遇到问题后的本能反应,会决定职场发展的高度?
原文地址:遇到问题后的本能反应,会决定职场发展的高度? 转载
怎么通俗的理解认知?
认知,是对待一个问题,本能的思考方式。
举个例子,老板抛出了一个问题,群里的Team Leader,本能之下可能有这样几类回复:
画外音:Team Leader,后文统一使用TL简写。
(1)这不是一个问题,不影响;
画外音:可能是怕给自己部门找麻烦。
(2)不是我部门的问题,另一个部门请看一下;
画外音:可能是怕老板追责,先把锅甩出去。
(3)我们先看一下,稍后反馈;
画外音:高下立判,不喜欢怎样的TL,就别做那样的TL。
管理认知,对待问题的本能反应,有可能决定一个管理者职场能够到达的高度。
职场人,常见的有这几类认知,对待同一个问题,ta们往往本能的做出不同的反应。
第一类:“抱怨型”这类员工/管理者,遇到问题,往往归咎外因,以“抱怨”为本能的应对。
例如:晋升没有成功,ta会认为,评委都是傻X,没有人是伯乐。
又例如:系统出了线上问题,ta的本能反应是,QA没有测试到位。
再例如:绩效不符合预期,ta会认为是TL的支持不够,同事不配合,下属不给力。
ta们充满负能 ...
阿里高级技术专家方法论:如何写复杂业务代码?
原文地址:阿里高级技术专家方法论:如何写复杂业务代码? 转载
阿里妹导读:张建飞是阿里巴巴高级技术专家,一直在致力于应用架构和代码复杂度的治理。最近,他在看零售通商品域的代码。面对零售通如此复杂的业务场景,如何在架构和代码层面进行应对,是一个新课题。结合实际的业务场景,Frank 沉淀了一套“如何写复杂业务代码”的方法论,在此分享给大家,相信同样的方法论可以复制到大部分复杂业务场景。
一个复杂业务的处理过程业务背景简单的介绍下业务背景,零售通是给线下小店供货的B2B模式,我们希望通过数字化重构传统供应链渠道,提升供应链效率,为新零售助力。阿里在中间是一个平台角色,提供的是Bsbc中的service的功能。
商品力是零售通的核心所在,一个商品在零售通的生命周期如下图所示:
在上图中红框标识的是一个运营操作的“上架”动作,这是非常关键的业务操作。上架之后,商品就能在零售通上面对小店进行销售了。因为上架操作非常关键,所以也是商品域中最复杂的业务之一,涉及很多的数据校验和关联操作。针对上架,一个简化的业务流程如下所示:
过程分解像这么复杂的业务,我想应该没有人会写在一个serv ...