1、设置文件上传大小的限制:
yml配置文件设置:
1 | yaml复制代码spring: |
2、前端页面:
3、control层
1 | less复制代码package com.jf3q.study.control; |
4、如果有拦截器的话,拦截器设置下放行
1 | typescript复制代码@Override |
5、效果如下:
有什么不懂得可以q我1913284695
本文转载自: 掘金
开发者博客 – 科技是第一生产力
1、设置文件上传大小的限制:
yml配置文件设置:
1 | yaml复制代码spring: |
2、前端页面:
3、control层
1 | less复制代码package com.jf3q.study.control; |
4、如果有拦截器的话,拦截器设置下放行
1 | typescript复制代码@Override |
5、效果如下:
有什么不懂得可以q我1913284695
本文转载自: 掘金
www.jianshu.com/p/41ea7a430… 包含了 业界常用的4-5种
www.ibm.com/support/kno… IBM参考
www.jboss.org/drools/docu… drools 官方文档
blog.csdn.net/lifetragedy… 教程简介
google的表达式引擎aviator
juel.sourceforge.net/guide/start… 流程引擎中常用来,各种rpc http等接口的调用
www.ibm.com/developerwo… 基于rete算法的规则引擎
www.ibm.com/developerwo… IBM06年的使用
本文转载自: 掘金
1 | xml复制代码<!-- SpringRetry --> |
1 | java复制代码package org.springframework.retry; |
1 | java复制代码FixedBackOffPolicy fixedBackOffPolicy = new FixedBackOffPolicy(); |
1 | java复制代码// 指数回退(秒),第一次回退1s,第二次回退2s,第三次4秒,第四次8秒 |
1 | java复制代码// 重试策略 |
1 | java复制代码import com.codecoord.util.PrintUtil; |
1 | java复制代码@RestController |
1 | java复制代码18:27:20.648 - http-nio-8888-exec-1 - open |
1 | java复制代码import org.springframework.retry.annotation.Retryable; |
1 | java复制代码import org.springframework.retry.annotation.EnableRetry; |
1 | java复制代码@RequestMapping("/retryAnnotation") |
1 | java复制代码18:46:48.721 - http-nio-8888-exec-1 - 方法调用.. |
1 | java复制代码@Target({ ElementType.METHOD, ElementType.TYPE }) |
1 | java复制代码@Target(ElementType.TYPE) |
1 | java复制代码@Component |
1 | java复制代码// 初始延迟2秒,然后之后验收1.5倍延迟重试,总重试次数4 |
1 | java复制代码/** |
1 | java复制代码@RestController |
本文转载自: 掘金
现有测试服务器A 和 测试服务器 B,需要实现从测试服务器A向测试服务器B进行mongoDB 数据库的迁移。
可以使用 mongoDB 的导出工具 mongoexport 和导入工具 mongoimport 实现。
官方英文文档链接 mongoDB mongoexport ,mongoDB mongoimport
mongoexport 参数项
1 | sql复制代码general options: |
导出集合为 .csv 文件
1 | css复制代码mongoexport --db users --collection contacts --csv --fieldFile fields.txt --out /opt/backups/contacts.csv |
导出集合为 .json 文件
1 | css复制代码mongoexport --db sales --collection contacts --out contacts.json --journal |
mongoimport 参数选项
1 | sql复制代码general options: |
mongoimport 导入 .csv 文件
1 | css复制代码mongoimport --db users --collection contacts --type csv --file /opt/backups/contacts.csv |
mongoimport 导入 .json 文件
1 | css复制代码mongoimport --collection contacts --file contacts.json --journal |
进入找到服务器A的 mongodb 安装目录下
例如:cd /usr/local/mongodb/bin
1 | bash复制代码./mongoexport -d DataBaseName -c CollectionName -o bak.dat |
其中,DataBaseName 为数据库名称,CollectionName 为集合名称,bak.dat 为导出后的名称
导出后的bak.dat将在 mongoexport所在的目录下。
例如:
1 | bash复制代码./mongoexport -d user -c guset -o guset.dat |
将数据库 user 下的集合 guset 导出到 mongoexport 所在的目录下,并将其命名为 guset.dat
移动导出的数据文件到另外一台服务器的mongo 目录下
1 | bash复制代码sudo mv /tmp/bak.dat /db/mongo/bin |
注:bak.dat 问原来服务器导出的数据文件。
进入 mongoDB 安装目录。
1 | bash复制代码cd /db/mongo/bin |
使用
1 | bash复制代码./mongoimport -h 127.0.0.1:port -u xxx -p xxx-d DataBaseName -c CollectionName bak.dat |
其中,DataBaseName 为数据库名称,CollectionName 为集合名称,bak.dat 为导入的集合
实例操作
1 | sql复制代码./mongoimport -h 127.0.0.1:27017 -u user -p user -d guset -c guset bak.dat |
操作结束。
其中有写到
Do not use mongoimport and mongoexport for full instance, production backups because they will not reliably capture data type information. Use mongodump and mongorestore as described in “Backup Strategies for MongoDB Systems” for this kind of functionality.
即不要将 mongoimport 和 mongoexport 用于完整实例生产备份,因为它们无法可靠地捕获数据类型信息。使用 mongodump 和 mongorestore ,如“MongoDB系统的备份策略”中所述,以实现此类功能。
mongoDB mongodump 文档
本文转载自: 掘金
·因为redis是单线程的,使用keys命令,如果redis中的key非常庞大,那么这条命令执行时间非常长,这个时候就会阻塞到其他命令的执行,所以要redis也提供给我们另一个scan命令来解决这种常见的场景,
这两个优势就帮助我们解决了上面的难题,不过scan命令也并不是完美的,它返回的结果有可能重复,因此需要客户端去重。但是这个问题很好解决,我们可以用Set集合巧妙的处理。
Redis Scan 命令用于迭代数据库中的数据库键。
SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程。
SCAN 返回一个包含两个元素的数组, 第一个元素是用于进行下一次迭代的新游标, 而第二个元素则是一个数组, 这个数组中包含了所有被迭代的元素。如果新游标返回 0 表示迭代已结束。
如下代码表示,从redis服务器中,扫描1000个有指定前缀的key,放入到set集合中,count是每次扫描的key个数,并不是结果集个数
1 | vbnet复制代码 Set<String> keys = redisTemplate.execute((RedisCallback<Set<String>>) connection -> { |
本文转载自: 掘金
分享一波在读者群,应届生大佬的校招面试经历,目前手上已经拿到了 字节意向书,蚂蚁转正offer ,大佬是我在蚂蚁认识的一位师弟,个人能力很强,职业规划很清晰,源码钻研也很深入,给大家分享一波他的字节SP面经。
楼主是周天下午4点到7点连续三面,第二天早上发的意向书,效率很快
感觉全部是怼着简历问的,八股文问的比较少,全部是基于项目 实习的基础上去问的!感觉参考价值不是特别高,还是发出来给大家看看!
netty的rpc框架,针对这个进行展开提问Reactor线程模型netty怎么实现实现reactor线程模型的rpc调用的时候调用远程方法像调用本地方法一样是用了什么(这里我回答了网络连接的底层,结果面试官问的代码层面的动态代理)动态代理怎么实现的?有哪两种动态代理(JDK、cglib)?有什么区别?select、poll、epollrocketmq源码,接下来对mq展开提问rocketmq事务消息底层自增id有什么好处(我回答了和uuid相比,节省磁盘空间,作为聚簇索引提升查询效率)支付宝实习项目)rocketmq延时消息底层实现,应用场景epoll 水平触发和边缘触发json序列化工具有哪些?protobuf吗?和json比有什么好处呢?dubbo是怎么实现的吗?序列化方式是什么呢?zookeeper讲讲?CP还是AP?eruka呢? 服务调用需要ap还是cp?分析一下场景?单表最多不放超过2000w行数据呢?商汤实习项目、数学建模项目)认证、授权、熔断、限流都是怎么实现的?限流算法?(令牌桶等)限流方式?(nginx、网关)JWT了解吗?进程通信方式?哪种通信方式最快?线程安全问题?返回error怎么排查?(ping对应的ip)128.0.0.1怎么办?(肯定是对应的浏览器缓存映射、或者本级host被修改,面试官说就是这个)好了各位,以上就是这篇文章的全部内容了,我后面会每周都更新几篇高质量的大厂面试和常用技术栈相关的文章。感谢大伙能看到这里,如果这个文章写得还不错, 求三连!!! 感谢各位的支持和认可,我们下篇文章见!
我是 九灵 ,有需要交流的童鞋可以 加我wx,Jayce-K,关注公众号:Java 补习课,掌握第一手资料! 如果本篇博客有任何错误,请批评指教,不胜感激 !
本文转载自: 掘金
最近一年很多关于QUIC的文章层出,但是发现一个问题,这些文章都是在介绍QUIC或HTTP3是怎样的一个东西,以及它的优点和机制,将它夸的近乎上天了。然而有心的人估计会亲手做一些测试,就会发现这个被捧上天的东西性能居然还不如HTTP1.1,这是怎么回事呢?
最近我一直在做QUIC或者说HTTP3的相关工作,就一直在憋着写这样一篇文章,给和我当初有同样疑问的人一种变相的解答。
测试很简单,分为两台机器,均在同一局域网内。服务器使用Nginx的QUIC分支版本,即nginx-quic。客户端使用h2load(支持HTTP3版本的)做基准测试工具。在服务端使用netem模块对网络状况进行操控,模拟不同的网络环境。请求无请求体,响应体为Nginx默认612字节首页文件,那么简单来看下测试结果吧:
h2load的参数如下:-t 10 -c 100 -n 1000 -m 100,即10线程、100个连接、1000个请求,每个连接可以同时处理100个请求。
HTTP版本
延迟
丢包率
重复率
包损毁率
结果
HTTP1.1
-
-
-
-
总耗时406.49ms, 24601.15 req/s QPS,21.30MB/s 每秒传输
HTTP3
-
-
-
-
总耗时611.90ms, 16342.59 req/s QPS,12.98MB/s 每秒传输
HTTP1.1
100ms+-10
-
-
-
总耗时1.90s, 5275.52 req/s QPS,4.57MB/s 每秒传输
HTTP3
100ms+-10
-
-
-
总耗时3.65ms, 2740.22 req/s QPS,2.18MB/s 每秒传输
HTTP1.1
-
30%
-
-
总耗时33.64s, 297.28 req/s QPS,263.60KB/s 每秒传输
HTTP3
-
30%
-
-
总耗时19.82s, 504.45 req/s QPS,447.31KB/s 每秒传输
HTTP1.1
-
-
70%
-
总耗时443.55ms, 23065.39 req/s QPS,19.97MB/s 每秒传输
HTTP3
-
-
70%
-
总耗时419.98ms, 23810.43 req/s QPS,18.92MB/s 每秒传输
HTTP1.1
-
-
-
20%
总耗时14.46s, 691.61 req/s QPS,613.27KB/s 每秒传输
HTTP3
-
-
-
20%
总耗时4.12s, 2424.55 req/s QPS,1.93MB/s 每秒传输
HTTP1.1
100ms+-10
30%
-
-
总耗时30.64s, 326.42req/s QPS,289.44KB/s 每秒传输
HTTP3
100ms+-10
30%
-
-
总耗时17.16s, 582.89 req/s QPS,474.19KB/s 每秒传输
HTTP1.1
-
30%
70%
-
总耗时2.03s, 4914.90 req/s QPS,4.26MB/s 每秒传输
HTTP3
-
30%
70%
-
总耗时3.06s, 3264.89 req/s QPS,2.59MB/s 每秒传输
HTTP1.1
-
30%
-
20%
慢到没结果…
HTTP3
-
30%
-
20%
总耗时15.09s, 662.75req/s QPS,539.16KB/s 每秒传输
在这份测试结果中我给出的都是典型值,当然我也对这些值都做过大小调整看结果。从这份结果我们可以看出如下结论:
从上述结论中我们可以看到,并非任何时候HTTP3都优于HTTP1.1,但对弱网高丢包率、包损的情况下,QUIC或者说HTTP3的优势就非常明显了,这得益于其FEC机制和连接复用机制。然而生活中,弱网的环境其实非常多,例如地铁换站、电梯、部分楼宇内、以及一些网络覆盖不全面的城镇等等。因此QUIC更多的是一个对整体网络的兜底策略。
因此,如果使用nginx-quic的默认配置将所有的请求都升为HTTP3版本是不明智的,因为常规情况下HTTP1.1的性能优势是不可视而不见的。这也就引入了下一小节的组件。
由上面的结论,我们发现并非对每一个请求都升级是一个明智之举,因此就有了这个Nginx模块对版本升级进行自动化控制——ngx_http_autoquic_module
这个模块会根据TCP的网络状况来决定是否需要将HTTP版本升至HTTP3版本。而根据QUIC的统计情况来判断是否需要降级至HTTP1.1版本。由于降级并不像升级那样平滑,因此对降级增加了开关,让使用者可以选择是否允许降级。
目前对于浏览器,可以很好地支持升降级。但对于众多客户端而言,升降级与否还要看客户端所使用的HTTP库的处理逻辑。
感谢阅读,期待诸位的评论。
本文转载自: 掘金
本文并不是要安利你买一台NAS,而是从各个方面分析对比,让你能够根据自己的实际情况选择合适的私人数据存储方案。
另外,本文不打算介绍什么是NAS,我相信能够点开看这篇文章的同学多多少少对NAS这个概念都有一定的了解。
如果你正想为自己移动硬盘上的小哥哥小姐姐找个家,那么你就可以继续看下去了。。。
相信上了年纪的我们硬盘上多多少少都有一些或者很多重要的资料,比如私照,视频,未美颜的照片(纯属调侃),工作资料,私人数据等等。那么这些数据睡在移动硬盘中不是很好么,为什么还要什么存储方案尼?接下来让我给你闹闹。
如果某一天你的硬盘罢工了尼(前段时间就有个在医院上班的朋友找到我,说他们医院的一台电脑硬盘坏了,上面有他们医院10几年的资料,甚至很多Level级别很高的资料,问我能不能修复,然后就没有然后了),此时如果你的硬盘能够正常修复还好(此时花多少钱你应该都不会觉得心疼),如果彻底罢工了,你会不会心都凉了半截,会不会寝食难安,哈哈哈,貌似有点夸张了。
就算你的硬盘不罢工,但是睡在硬盘上的资料,特别是照片(我们这个年纪娃娃的照片应该特别多,不过我见过很多朋友用通过发朋友圈的方式将照片存在微信和QQ上,但是却不能放太多私照,你懂得),你有没有觉得使用起来很不方便,在现在这个互联网这么发达的时代,不应该是人在哪里,资料就在哪里么。所以你可以把硬盘一直带上身上,然后再背一个电脑。。。。嘿嘿嘿。。开个玩笑。
所以我们都想我们的数据存在这么一个地方:
1、随时随地都能够读取到(PC或者手机);
2、资料能够抵抗一定的风险,不会因为一块硬盘罢工之后数据就丢失了(专业点说:叫具有容灾能力)
3、且资料具有绝对的安全性和私密性,不存在泄露的风险。
那么目前能够做到这些且比较常用的方案有三个:网盘(云盘)、路由器硬盘、NAS。接下来我们分别看看这三个方案各有什么特点。
本文不会介绍路由器硬盘和NAS的具体搭建方式。
本文不安利选择什么方式,仅仅为大家做一些比较分析。
网盘也叫云盘,由云服务商提供服务。购买容量和速度都需要买会员,你懂得。在买了会员的情况下,还是比较方便的。PC和手机都有相应的应用能够随时随地的读取。且云盘本身是具有容灾的(但是貌似也不是绝对的,你可以去百度下,就会发现很多关于某度盘上数据丢失无法恢复的情况,具体原因就不知道了。但作为一个程序员来看我觉得很正常,因为if else必定是有bug的)。使用云盘的优缺点如下。
优点:
1、很容易入手,交钱就OK
2、不存在任何维护费用,也无需自己维护折腾
缺点:
1、读写速度(上传下载速度)应该只有20M/s(没有具体研究过,买不起会员)。
2、不建议存在私照(云盘都声称不看你的内容,你信不信我不知道,反正我是不信)
3、存在数据丢失的可能(可能性应该不会很大,但是万一尼,人家可是不陪得哦)
4、存在云盘关闭的可能(前两年关闭了很多云盘,如360,金山等)
5、播放视频不方便(比如通过电视播放、内网分享等),只能手机、PC在线播放
这种方案比较便宜(后面会对比三种方案的价格),需要自己买有个能够挂硬盘的路由器,然后再买一个硬盘(比如10T的)。这样就可以组装成一个数据存储方案了,具体组装方式大家可以百度。组装完成之后通过相应的App能够做到手机端访问。
优点:
1、比较便宜(便宜的几百就可以搞定)
2、读写速度快,内网应该可以达到千兆数据(100M/s上下)。外网则依赖你的网络带宽。
3、视频播放方便,电视可以直接连接
缺点:
1、数据没有容灾,单硬盘存在硬盘罢工的风险(没有用过,但是我觉得数据应该是可以备份到对应的云盘的,只是需要购买空间)
2、功能比较简单,只能够提供基本的视频播放、照片查看备份、文件共享等
3、外网访问应该比较麻烦,且数据可能需要经过第三方服务器,存在安全风险(人家肯定声称不看的,还是那句话,不管你信不信反正我是不信的)。
4、搭建、维护和配置需要一定的动手能力。
由于没有使用过路由器硬盘,所以功能不是很了解。大部分内容都是百度看的,可能存在分析不够全面或者有误的地方,请大家批评指正。
简单的理解就是私人云盘,即自己在家搭建属于自己的云盘。如何搭建就涉及到两种情况了,即大家说的黑NAS或者白NAS(黑群or白裙)。黑NAS:即自己购买各种硬件(主机,硬盘架等),然后通过安装盗版或者开源的NAS系统,来构建NAS。白NAS:即直接购买官方正版NAS服务器(就一个小黑盒子),然后直接使用即可。
优点:(从白NAS的角度考虑)
1、安装简单、维护简单
2、使用简单,功能丰富(有各种App支持各种功能),大部分功能都能够在手机上操作,照片管理、视频管理、文件管理等。
3、具有数据容灾(可以做磁盘阵列,即raid0, raid1, raid5, raid10),比如:raid1的情况下,一个硬盘挂了,另一个硬盘上还有数据。
4、具有完整的操作系统,是一台小型的服务器。能够支撑一个小型公司的基本办公(邮件系统,ERP系统等,内部网站,甚至是对外网站)和数据存储需求。
5、支持Docker(不是所有NAS都有,当然有钱就有,哈哈哈),能够搭建服务器,所以你可以为所欲为。
6、数据非常安全,可以存放大量的小哥哥小姐姐。所有数据都存在自己的硬盘中,且不会经过第三方服务器。
7、速度快,能够跑满千兆网络(内网),外网则依赖你的网络带宽。
8、具有完整的权限管理策略,可以新建各种成员和人群划分。
9、能够做视频监控存储。
缺点:
1、搭建、维护和配置需要一定的动手能力。
2、成本比较高
网盘(云盘)适合的人群:
路由器硬盘适合的人群:
NAS适合的人群:
PS(有安利大家的嫌疑):其实有了NAS,手机存储只需要32G就够了。几年下来,一家人几部手机还是可以省很多钱。
所有分析都是扯淡,只要不care钱钱,通通安利上NAS,嘿嘿嘿……我X,前面好像不是这么说的尼….哈哈哈
如果你对本文有任何疑问或者高见,请添加公众号咱们一起探讨。偷偷告诉你,添加公众号可以获得”Java高级架构“上10G的视频和图文资料哦。
本文转载自: 掘金
刚来我现在这个公司的时候,还有再上一家公司去优化外包写的代码的时候。总会遇到一些问题,相信大家也跟我一样会遇到过这些问题:
我上面的一列,你有没有感触,发没发现就是你遇到过的所有的问题。其实,根本原因就是代码可读性差,没能很好的串联起代码内在的逻辑。可读性差的代码不仅代码难以理解,维护起来也是相当的头疼,最终导致交付效率变差。
今天就来讲一下如何快速提高代码的可读性
提升源代码的可读性主要有以下四大好处。
第一,更易于维护。代码写好后,需要调试、运行与修复 Bug,设计文档、需求文档和口头交流只能表达部分业务逻辑的意图,而代码则能反映出编程实现业务逻辑时的全部真实意图。可读性高的代码,能让阅读者在阅读时快速理解编写者的意图,即便逻辑复杂,也能在修改时准确地分析和理解,大大节省维护和修改代码的时间。
第二,更易于重构。现在很多项目之所以难以重构,就是因为代码的可读性太差。当你无法理解一段代码时,你会跳过它,而整个系统都难以理解的话,你可能就会选择重写而不是重构,因为重构必然会修改原有代码,这会引入一定的风险,一旦因为重构而导致故障,那么维护的人就要担责。所以说,可读性的高低在某种程度上决定了你重构意愿的大小。(这里我相信大部分人其实都碰到过入职接手别人的代码,可能因为那个人在你入职之前就离职了,也可能因为他跟你交接的时候并没有交接完整就匆匆的离职了,导致你对现有的代码并不熟悉,公司的业务发展,提了新需求要求你去改原本的代码,但是你这时候看不懂,所以你只能自己去重写一个方法,之后去调用你重写之后的接口,我相信大部分人都这么做过,我也这么做过)
第三,更易于测试。代码在修改时需要反复调试,如果代码的可读性很差,那么很多时候都需要写一些额外的 Mock 或测试接口来对原有的代码进行测试,不仅浪费时间,还容易造成误读。可读性高的代码,参数与输出都更清晰,在测试时能更精准地找到对应逻辑和问题点。
第四,更易于应用设计模式。设计模式除了在设计之初被使用外,其实更多时候都是在代码重构过程中被使用。在工作中,你会发现有的代码虽然写了很多嵌套的if-else,但命名和注释都写得很好,逻辑也很易读,在重构时就能通过设计模式很好地去优化。而有的代码虽然看上去很简洁,但使用了很多高级技巧或缩写命名,理解起来非常费时、费力,对于维护人员来说,自然不愿意考虑使用设计模式。
虽说编写文档能够表达软件开发意图,但事实上,你可能很讨厌写文档,这是因为大部分文档都与代码没有直接关系,并且随着代码的不断调试与修改,文档会变得越来越难以与最新的真实情况同步。
另外,你可能也没有太多时间阅读文档,需求上线、Bug 修复、多项目并发是现在程序员的日常现状。因为时间紧、任务重,你可能只能边改代码边学习,这时一份逻辑清晰的代码才是你真正需要的。
可以换个角度想想,假如你是代码使用者,你希望看到什么样的代码?很明显,没有人想要看到这样的代码
1 | java复制代码cName = InpList.get(0).replace(",", "."); |
而是,希望看到这样的代码(HttpClient 的某个代码片段):
1 | java复制代码/** |
所以说,在开发代码时,应该更注重代码表达的意图是否清晰,考虑使用一些方法和技巧,虽然会耗费一点时间,但是从整体来看,你会节省很多沟通与解释的时间,做到在真正的提升编码效率。
要想写出可读性高的代码,你可以从三个方面来入手。
下面我就来具体解释下。
命名在编程中至关重要,无论是变量名、类名还是方法名,好的名字能快速准确地传达要表达的含义,而缩写、自定义名称会让代码变得难以理解。我们先来看一段代码:
1 | java复制代码public class T { |
这段代码到底实现了什么功能?估计没有人能回答出来。如果编写者不是我,我肯定也无法理解这段代码。光凭看代码,几乎是无法理解这段代码的真实含义到底是什么的。
实际上,这个类是获取球队比赛得分的,除了通过球队直接获得比赛得分外,还可以通过球队里的某个球员来查找对应得分,具体修改如下:
1 | java复制代码/** |
从优化后的代码中,你就能直观地看到, “命名的优化加上注释的说明”一下子就让源代码的逻辑变得清晰起来,即便你没有学过编程,也能大致了解这段代码的逻辑和作用。
1 | java复制代码public List<User> getUsers(int id) { |
这段代码的含义是:想要通过 id 来查询员工的信息,如果 id找不到,就查询员工的领导,然后通过他领导下的员工信息来寻找,这时还需要判断员工年龄大于 35 岁且为男性。
这是我们最常使用的逻辑实现方式,俗称箭头型代码,但是随着判断条件逐渐增多,嵌套就会增多。代码逻辑越多,你就越容易搞不清楚逻辑是什么,因为看到最内层的代码时,你已经忘记前面每一层的条件判断是什么了。
那么,我们该如何去优化呢?其实很简单,就是改变控制流,先判断会出现失败的条件,一旦出现优先推出。优化后的代码如下:
1 | java复制代码public List<User> getStudents(int uid) { |
现在,代码逻辑是不是很清晰了?虽然这个快速失败方法很简单,但是非常有效。实际上,快速失败就是 KISS 原则一个很好的实践,这样能保证条件判断的逻辑简单清晰。只要 if 的嵌套超过三层,你就可以应用这个原则来改进控制流,让逻辑更清晰易懂。
除了改进表层和逻辑外,我们更应该尽量避免设计代码时的一些惯性思维,这里我总结出了“五个避免”,下面我们就来具体分析一下。
第一,要避免一次性代码。一次性编码最大的坏处在于,一旦需要修改,多处就得跟着修改,而多次修改又可能会出现遗漏的风险。一次性代码在越来越多的软件代码中出现,一个本质的原因就是多人协作开发的情况越来越多。由于编程是一件非标准化的事情,不同程序员可能对同一个逻辑的理解完全不同,而一旦每个人都只从自己的角度出发写一次性代码,那么同一个系统里的代码很快就会变得冗余与混乱。
第二,要避免复制粘贴代码。一方面,不同的人编码风格可能会有所不同,这会给阅读者在理解上造成一定的认知负担(需要来回切换判断标准)。另一方面,还会带来未知 Bug的风险。复制过来的代码,更多是关注输入和输出,一旦代码正常运行后,很少会去关注代码的内部逻辑,但是等出现问题后,再想去梳理逻辑反而变得更加困难(因为不知道详细的实现逻辑)
第三,避免写超长代码。超长代码带来的最大问题是:在阅读代码时,函数方法之间的跳转过多,思维很容易发生混乱,尤其对于一些命名相同但参数不同的方法,很容易出现修改错误的情况。从编写者的角度来看,你写超长代码,可能是觉得在一个文件里维护代码比较方便;但对于阅读者来说,他可能并不知道你是如何对代码进行职责划分的,更多时候他都会以为一个类里都是一个职责,但实际上一旦出现多个职责,加上逻辑跳转很多,阅读者基本上是会放弃阅读的。
第四,避免过度简化命名和表达式。在开发任务重的时候,我们通常会选用一些简化命名的方法,比如,num1、num2、num3 这类变量命名形式。虽然在写代码的时候,我们可能记得这些变量的含义,但是过一段时间后,如果没有注释或说明,几乎是不可能直接通过名字知道它们的作用的,还得借助上下文代码,这样不仅费时,而且还可能会出现理解错误的情况。
第五,避免写“是什么”的注释。代码的命名和结构如果能直接反映出来“是什么”的话,我们就不应该用注释去表达,因为看代码一眼就能明白,比如,获取用户信息的方法名——get 和 getFromUserInfo。
我们应该多写“为什么”的注释,比如,为什么要多加一个适配的方法,原因可能是线上 xxx 问题引起,或临时修复的Bug,后续可能随 xxx 接口调整而废弃,等等。在很多优秀的开源框架中,我们都能看到作者会在 interface 接口上写很多“为什么”的说明,就是为了帮助我们快速抓住代码的逻辑线索。
另外,写“为什么”的注释还有一个好处:尤其在早期快速迭代过程中,能给后来的维护者提供一个优化的切入点,而不至于交接代码后让维护代码的人看不懂、不敢动。
本文转载自: 掘金
1 | java复制代码 |
注:不会写
corn表达式的小伙伴,可以使用这个哦:https://cron.qqe2.com会帮你自动生成corn表达式,且能检测你的表达式是否合法。非常好用!
以上三种是使用频次比较多的。因为不接受参数,主要用户定时同步第三方基础数据的业务场景。
使用
@Scheduled需在pom中引用springboot的相关依赖,并在Application主入口函数中增加@EnableScheduling的注解。
基于注解的方式的任务配置起来很简单也很好用,但是由于不能传递参数,使用场景有限。那么就需要使用基于接口形式的定时任务了。
1 | yaml复制代码<dependency> |
1 | java复制代码@Service |
以上就是两种常用的定时任务,小伙伴们,你,学废了吗?
更多java原创阅读:javawu.com
本文转载自: 掘金