程序员周报写不出来怎么办? 2022-11-23 今天是 2022 年的第一个工作日,沉浸在假期中的打工人又要开启一年的打工之路了,毕竟只有我们好好努力,老板们才能更早的换车换房。 2021 年已经结束了,这几天陆陆续续的大家都在进行年终总结,大佬们也组织了各种跨年演讲。对于我们程序员来说,写周报都感觉已经很难了,还要写年终总结,简直不要太难。 说到写周报知乎上面就有一个网友提问,程序员周报写不出来怎么办?关注的人数已经达到 24 w 了,看来这个问题已经是个很常见的问题,很多人都写不出周报,觉得一周好像做了一些事情,但是又好像啥也没做,但是确实又做了,就是说不出来。 在阿粉看来,周报写不出来主要有两个原因: 程序员都比较务实。接手的每一个需求的底层实现都基本上知道,用到的一些东西要么就是很简单的一些 CRUD,要么就是一些开源的实现,很多事情处理起来很普通,所以在写周报的时候就不会把一些鸡毛蒜皮的小事当成噱头来封装汇报,毕竟在懂行的同事和领导眼中这个都很简单,特别是在一些技术出身的领导面前,这样更是班门弄斧,完全没必要,很有可能还会让别人觉得自己在炫耀。 再一个是程序员的工作很难用一些指标去衡量。程序员的周报不可能像产品或者业务人员....
Spring 的 Bean 明明设置了 Scope 为 Prototype,为什么还是只能获取到单例对象? 2022-11-23 Spring 作为当下最火热的Java 框架,相信很多小伙伴都在使用,对于 Spring 中的 Bean 我们都知道默认是单例的,意思是说在整个 Spring 容器里面只存在一个实例,在需要的地方直接通过依赖注入或者从容器中直接获取,就可以直接使用。 测试原型 对于有些场景,我们可能需要对应的 Bean 是原型的,所谓原型就是希望每次在使用的时候获取到的是一个新的对象实例,而不是单例的,这种情况下很多小伙伴肯定会说,那还不简单,只要在对应的类上面加上 @scope 注解,将 value 设置成 Prototype 不就行了。如下所示 HelloService.java package com.example.demo.service; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; /** *....
在阿里内部是如何 Debug 线上问题的? 2022-11-23 在日常工作中我们经常会遇到一些线上异常的情况,而且有些问题只有在线上才会出现,由于环境和数据不一样在本地和测试环境根本没办法复现,而且线上也没有输出日志,那么遇到这种情况我们往往要怎么去解决呢? 常规做法 如果实在遇到上面的情况,在本地和测试都无法复现,那最常规的做法就是拉个线上分支的版本,增加一些调试日志,然后在重新发布版本进行调试。运气好加一次日志就可以找到问题,运气不好的话可能还要发布好几次才能定位到问题。 高级做法 下载安装 arthas Arthas 是阿里开源的一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。 上面的 Arthas 这款工具的官方介绍,从中我们可以看到这个工具可以查看方法的出入参,异常以及监测方法的耗时,我们排查问题的时候最重要的就是想知道一些方法的入参和返回,有了入参和返回的数据我们就可以模拟出具体的场景从而解决线上的问题。 注意这里说的方法不单单是外层的接口方法,任何 Servi....
在 Java 日常开发中,排名前五的 Exception,保证你全部遇到过! 2022-11-23 说到 Java 中的 Exception 可以说是谁见谁恨,一旦遇见 Exceptio 说明我们的程序出了异常,我们都知道 Java 的异常都是 Throwable 对象,Throwable 有两个子类,分别是 Error 和 Exception,对于 Error 中我们常见的无非就是 OutOfMemoryError 和 StackOverflowError,而对于 Exception 我们常见的会稍微多几个。这篇文章给大家介绍在开发中 Top 5 的异常,相信每一个你都遇到过! 首先 Exception 又分为 RuntimeException (运行时异常)和 CheckedException (检查时异常),两者区别如下: RuntimeException:顾名思义,在程序运行的时候触发的异常,这种异常往往是没办法提前知道的,只有程序在运行的时候才能触发出来,通常情况下出现这种 Exception 基本上都是代码的逻辑错误。 CheckedException:编译期间可以检查到的异常,必须显式的进行处理(捕获或者抛出到上一层)。 这里只列表最常见的五个 Exception,包含....
每个后端都应该知道的八个提升 SQL 性能的 Tips 2022-11-23 作为一名后端程序员,可以说天天都要跟数据库打交道,不管使用的是 MySQL, Oracle 还是 SQL Server,毫无疑问都逃不开 SQL,所以日常工作中对于 SQL 的性能优化可谓说十分重要。今天阿粉就带大家看一下,每个后端程序员都应该知道的十个提升查询性能的技巧。 1、使用 Exists 代替子查询 子查询在日常的工作中不可避免一定会使用到,很多时候我们的用法都是这样的: SELECT Id, Name FROM Employee WHERE DeptId In (SELECT Id FROM Department WHERE Name like '%Management%'); 相信大家平常肯定都是这样来使用的,其实还有一种更好的方法,如下所示: SELECT Id, Name FROM Employee WHERE DeptId Exist (SELECT Id FROM Department WHERE Name like '%Management%'); 这里我们使用 exist 关键字而不是 In 关键字,当然如果在数据量不大的时候,两种方式都可以,但是当数据量......
一文带你了解 Spring 的@Enablexxx 注解 2022-11-23 前面的文章给大家介绍 Spring 的重试机制的时候有提到过 Spring 有很多 @Enable 开头的注解,平时在使用的时候也没有注意过为什么会有这些注解,今天就给大家介绍一下。 @Enable 注解 首先我们先看一下有哪些常用的 @Enable 开头的注解,以及都是干什么用的。 @EnableRetry:开启 Spring 的重试功能; @EnableScheduling:开启 Spring 的定时功能; @EnableAsync:开启 Spring 的异步功能; @EnableAutoConfiguration:开启 Spring 的自动装配功能; 上面这几个是我们经常会用到和看到的,都知道在使用相应的功能的时候,如果没有配置上面的注解功能都是不生效的。以我们前面的文章的 Spring 重试为例,我们需要在启动类上面配置 @EnableRetry ,否则自动重试注解 @Retryable 是不会生效的,如下所示,没看过的可以去看下,https://mp.weixin.qq.com/s/U_nm92ujCGArkii5ze7uaA。 @Import 注解 那有的小伙伴就要问了,这....
手把手带你编写属于自己的 starter 2022-11-23 前面的文章阿粉给大家介绍了 SpringBoot 的自动装配功能,相信大家对自动装配都有了很好的理解,那么今天阿粉通过一个示例来给大家演示一下如何编写一个自己的 starter。 再编写 starter 之前我们先了解一下什么是 starter,一个 starter 其实就是对一个功能的集成封装,然后对外提供一个依赖,让业务去使用,像我们熟悉的 Redis,mongo,mybatis 等。另外由于任何人都可以编写自己的 starter,那么为了区分官方的 starter 和个人的 starter,通常在命名上面会有一个规范。所以 SpringBoot 官方提出,第三方在建立自己的 Starter 的时候命名规则统一用xxx-spring-boot-starter,而官方提供的 Starter 统一命名方式为spring-boot-starter-xxx。 通过我们前面的文章,我们知道自动装配首先要有一个配置类,其次还要有 spring.factories 文件,所以这两步是必不可少的。接下来我们就实操一下。 编写配置类 编写配置类首先要添加一个自动装配的依赖,然后再编写对应的配置类和业....
求求你了,写代码考虑一下扩展,套用一点设计模式吧 2022-11-23 弱弱地问大家一下,你们遇到过的最烂的代码是什么样子的? 好奇的阿粉在知乎上面搜了一下,果不其然没有令人失望,这个问题被上千万的人浏览过,然后如你所见,二哥也关注了这个问题~ 阿粉最近就接手了一个遗留项目,整个项目的代码结构混乱,动不动就是一个大几千行的类文件,一个方法五六百行而且其中还充斥着各种 if-else,让人看着简直头皮发麻。 很多相似的逻辑就是整段的代码复制粘贴,没有任何封装的存在,注释什么的就更不存在了,几个类似的方法在不同的类中还互相的调用来调用去,看上去像是方法的重载,结果啥也不是。更坑人的这个服务存在很严重的性能问题,消息队列堆积严重,系统 FullGC 频繁,导致需要隔三岔五就进行重启,简直不能忍! 看了下代码的 Git 提交历史记录,发现都是一些好几年前都不知道是哪批人写的历史代码,在业内像这种情况的代码往往被称为屎山。 如果说像这样的屎山代码能正常运行并且也不需要迭代的话,那阿粉只会当它不存在,但是理想很丰满,现实却很骨干,需求总是不断变化的,而且历史的代码逻辑渐渐的也不在符合当前的业务,并且性能也远远跟不上,所以没办法只能硬着头皮往屎山上爬。 经过一段时间的艰....
作为后端程序员 Linux 应该掌握到什么程度? 2022-11-23 作为后端程序员如果你只觉得只要把业务代码写完,功能实现,项目上线后就万事大吉,后期的运维完全不用关心那你就大错特错了。高级的后端程序员不仅要能高效的开发,还要会高效的运维,在遇到线上问题的时候能快速响应并定位修复。 后端程序员不管在什么公司,基本上都是会以下三种情况中的一种: 开发加自主运维:公司没有专门的项目运维人员,后端程序员既做开发,又做运维; 开发加协助运维:公司有专门的项目运维人员,后端程序员以开发为主,日常协助运维; 开发加自助运维:公司有专门的自助运维工具,后端程序员兼顾开发和项目运维; 开发加自主运维 这三种情况一般也对应了不同的互联网公司,第一种是创业型的小公司,在创业型的小公司没有专业的运维人员,所以项目的开发上线完全由后端程序员自己上手,也包括后期服务的运维,往往创业型公司相关的工具和制度都不会特别完善,也不会有什么发布集成工具,基本上都是人为的手动拷贝 war 包或者 jar 上传到服务器上面,进行完全人工运维。 针对这种情况如果作为一个后端程序员不会 Linux 命令那基本上是无法胜任工作的,虽说常用的简单的命令大家可能都知道,但是当真正遇到线上问题的时候,往....
教你 Java 编程中五个奇技淫巧 2022-11-23 枯燥的编程中总得有些乐趣,今天我们不谈论那些高深的技能,教你几个在编程中的奇技淫巧,说不定在某些时候还能炫耀一番呢。 1、找到最大值和最小值 不使用 if else switch 和三元运算符,在给定的三元组中找到最大值和最小值:比如给定 3,14,8,在不使用 if else switch 和三元运算符的情况下找到最大值和最小值。 话不多说,我们先看代码 public static int findMax(int a, int b, int c) { int max = a; boolean b1 = (max < b) && ((max = b) > 0); b1 = (max < c) && ((max = c) > 0); return max; } public static int findMin(int a, int b, int c) { int min = a; boolean b1 = (min > b) && ((min = b) > 0); b1 = (min > c) &....
IntelliJ IDEA 的这个 BUG 存在三年了! 2022-11-23 Java 程序员使用最多的 IDE 那一定是 IntelliJ IDEA(如果你还在用 Eclipse 或者 MyEclipse 我建议你换换),阿粉作为一名Java 程序员日常工作中几乎天天使用,不知道你有没有遇到过这种场景,那就是如果远程仓库中多了新的分支,每次通过右下角的分支管理 fetch 了远程分支过后,在搜索框中找不到获取到的分支,而是要关闭窗口,重新再打开搜索一下才能进行 checkout 操作,而且移除了分支也是一样,不会动态更新。 虽然说问题不大,但是当分支多了操作的次数多了以后,还是很烦心的,一开始遇到的时候总觉得是自己使用的不对,或者软件的版本有问题,但是最近升级到最新版本过后,发现这个问题还是存在,无奈的 Google 了一下,不搜不知道一搜索才发现,原来这个 Bug 已经存在了三年了,而且还一直处于 Open 的状态。 这个 BUG 的描述跟我们的问题是完全一样的,说的是 fetch 结束过后,分支列表并没有更新。而且通过右边的面板我们可以看到,这还是一个未关闭的高优先级的 BUG。BUG 的完整链接地址我放在文末了,感兴趣的小伙伴可以去看看。而且在这个 BU....
程序员十大常规内卷操作,你学废了吗? 2022-11-23 现阶段内卷已经成为互联网行业的专有名词,在很多公司,内卷的程度则代表着员工的努力,本文尝试教授十招程序员内卷操作,学完过后,帮助你干啥啥不行,内卷第一名。 声明:本文内容纯属虚构,如有雷同,纯属巧合。 因学会本文内卷操作被老板开除的,一切与阿粉无关,请谨慎学习~ 第一招:同事不走我不走 既然要内卷,那么第一招必须是修炼基本功,内卷的第一基本功就是加班。有道是领导不走我不走,同事不走我不走! 在白天工作的时候,我们要学会利用时间,比如多带薪上上厕所,多带薪打打水,这里我们要注意千万不要买那种容量很大的水杯,我们要买一个小点的杯子,最好还不是保温的,这样就可以增加我们带薪打水以及带薪上厕所的次数。 当然对外的说法是我们要劳逸结合,毕竟程序员坐久了身体吃不消,我们要多走动走动,并且通过这种方式,我们也为后面的招式打好了基础。 第二招:加班后一定要发朋友圈 学会了第一招过后,我们经常会发现有些工作在白天是做不完的,当然这是我们故意为之,为了就是晚上加班的有事情做,但是这不能让其他人知道,对外我们要说:这个需求不合理,这个需求比较复杂。 晚上加班的时候,当发现有同事下班,我们一定要及时的说一声:....
Java 中如何加密配置文件中的数据库账号和密码 2022-11-23 作为程序员每天的开发工作都离不开跟数据库打交道,而且我们的应用程序往往都会配置数据库的链接,那你有没有想过,任何一个能接触到我们项目代码的人员,都可以看到配置文件里面的账号秘密? 相信很多人的项目里面配置文件都是类似这样写的 ############### Mysql配置 ######################### spring.datasource.type=com.zaxxer.hikari.HikariDataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://127.0.0.1:3306/abc?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=1....
Java19 带来的虚拟线程是怎样玩出花的 2022-11-23 我们都知道一个 Java 服务其实是一个进程,当这个服务遇到高并发场景的时候我们往往会考虑使用线程池来提高性能,JDK 中就自带线程池,关于 JDK 的线程池感兴趣可以去看一阿粉之前的文章 聊聊面试中的 Java 线程池。今天阿粉想跟大家聊的时候 Java19 中提到的虚拟线程 virtual threads。 基本概念 我们都知道 Java 中的线程跟操作系统的内核线程是一对一的,Java 线程的调度其实是依赖操作系统的内核线程的,这就导致了我们的线程切换和运行就需要进行上下文切换以及消耗大量的系统资源,同时我们也知道机器的资源是昂贵的并且也是有限的,我们不能也无法肆无忌惮的创建线程,因此线程往往会成为我们系统的瓶颈。 为了解决这个问题,Java19 中提出了一种虚拟线程的概念,为了区别,之前的线程被称为平台线程。要注意虚拟线程并不是用来直接取代平台线程的,虚拟线程是建议在平台线程之上的,一个平台线程可以对应多个虚拟线程,同时一个平台线程还是一一对应内核线程,因此上面的架构就变成了如下,一个 VT 代表一个虚拟线程。 如果有小伙伴对 GO 语言比较熟悉的话,就会想到 Java 中的虚....
程序员常用的几种序列化方式,总有一个是你在用的 2022-11-23 我们都知道程序在运行的过程中经常需要进行服务间的通信和交互,特别是在当下微服务的架构下,每个系统都会庞大那么为了提高服务间的通信效率以及数据传输的性能,我们往往都会将需要传输的数据进行序列化,然后再进行传输。 什么是序列化 关于序列化相信大家都很了解,在 Java 中我们经常就可以看到很多实体类或者 POJO 都会实现 Serializable 接口,有了解过 Serializable 接口的小伙伴应该都知道,这个接口是一个空接口,只是用来标记的。所谓序列化简单来说就是在传输对象之前将对象转换成二进制字节进行传输,接收端在收到二进制数据后再反序列化转化成普通对象。 所以说序列化最终的目的是为了对象可以跨平台存储和进行网络传输。之所以需要序列化是因为在网络传输的时候,我们需要经过 IO,而 IO 传输支持的就是字节数组这种格式,所以序列化过后可以更好的传输。另外反序列化就是根据字节数组反向生成对象,是一个逆向过程。 常见的序列化方式 既然知道了什么是序列化,那么接下来我们看看有哪些常见的序列化方式。 JSON 当下最流行的序列化方式无非是 JSON 了,而且 JSON 作为前后端交互使用....
Java 程序员面试逃不过的终极问题 2022-11-23 作为 Java 后端程序员如果要问你什么是面试过程中最逃不过的终极问题,你的回答是什么呢?不管是面试初级中级还是高级,阿粉相信大家在面试的时候都遇到过下面这样的问题。 面试官: 麻烦你说下 Java 运行时数据区域是怎么样子的?哪些部分是线程私有的哪些是线程共享的? 什么是垃圾回收器,以及垃圾回收器是如何判断哪些对象是需要回收的?常用的垃圾回收器都有哪些? CMS 和 G1 有什么区别? 什么是类的加载机制?什么是双亲委派? JDK 自带了哪些常用的故障处理工具命令? 等等等 类似的问题还可以有很多,而且网上的答案也大同小异,基本上所有网上能查到的答案最终的归宿都是来自于周志明周老师的那本《深入理解 Java 虚拟机》,也就是下面这本。(福利见文末) JVM 是大厂面试中非常重要的一环,不论是校招还是社招,面试国内的一些大厂,都会被问到很多 JVM 相关的问题,只有搞懂了 JVM 才有可能真正把 Java 语言 "吃透",而且学习 JVM这部分的内容,一定要注意要实战和理论结合。 这本书可以说是 Java 程序员必读的一本书,在某瓣上平分 9.5,这本书不仅是必读,而且也还是必须多读的....
从长远发展来看,我是应该学 Java 还是 C/C++ 或者是 Python? 2022-11-23 网上有一句话是这么说的:如果你不知道学什么语言的时候,那么就学 Java。 虽然听上去怪怪的,但是也还是有一定的道理的,首先 Java 的应用很广泛,脚手架很多,作为企业级的开发语言,社会上的工作岗位也是偏多的。另外虽然说Java 的体系很庞大,但是对于大部分日常工作来说,市面上的一些框架资料基本上也能撑撑场面就救火,但是成本相对会高很多,因为没有体系而且还要不断的试错。 对于很多想入门程序员的朋友来说,如果说只是想找个工作,那没必要想太多,建议直接学Java,因为学习 C++ 的难度和成本会比较高,Java 相对来说会比 C++ 容易上手一点,而且网上的资料也多一点,学起来会快很多,没必要现在浪费太多的时间去学一个很难的语言。但是如果喜欢做游戏,或者追求极致的话,可以考虑 C++,不过不太建议,不是因为 C++ 不好,而是因为会 C++ 的只有两种人,要么是大牛,要么是菜鸡。 对于很多刚入行或者想入行的朋友来说,既然选择了语言,那么接下来的就是寻找一个好的老师或者资料书籍进行一步步的深入学习。Java 领域最经典的入门书籍一定是那本《Java 编程思想》,但是说真的能有几个人把这本书....
微软宣布正式关闭 IE浏览器,历时 28 年的 IE 浏览器走向了终点 2022-11-23 提到 IE 浏览器大家能想到是什么呢?慢,慢,还是慢!近日有消息称微软将在 2022 年 6月 15 日正式关闭 IE 浏览器,届时更新了最新 Windows 系统的用户将无法在新系统上启用 IE 浏览器,只能说该来的总会来。 说真的阿粉从接触电脑以来除了在学校机房里面用 IE 浏览器之外,其他时候用的最多的就是通过 IE 浏览器下载 Chrome 浏览器,而它的价值也就停留在这里了,下载了 Chrome 浏览器以后,IE 再也没有被打开过,桌面上的快捷方式也被删掉了。 今天 IE 也终于迎来了它的末日,虽然 IE 比不了当下的 Chrome,Firefox 等浏览器,但是毕竟也是曾经的一哥,靠着强大的微软爸爸的系统强绑定,一度市场份额占据第一,而且很多政府单位的官网或者系统都还只支持 IE 访问。 之前微软就对 IE 浏览器停止了更新,现在是真正的准备放弃了,毕竟 IE 的名声已经就不回来了,索性推出 Edge,用一个新的产品来替代旧的。 熟悉的朋友可能知道,其实最开始的浏览器并不是 IE ,而是网景公司开发的 Netscape 浏览器,Netscape 浏览器定义了许多关于浏览器的....
关于 Java 的可变参数你真的了解吗? 2022-11-23 我们都知道 Java 支持可变参数的形式定义方法,这种语法糖在某些时候可以简化我们的代码,但是关于可变参数是如何实现的以及其他的更多细节,你真的知道吗?今天阿粉就带你来了解一下。 ![image-20220212232737739](/Users/silence/Library/Application Support/typora-user-images/image-20220212232737739.png)
Java 中九种 Map 的遍历方式,你一般用的是哪种呢? 2022-11-23 日常工作中 Map 绝对是我们 Java 程序员高频使用的一种数据结构,那 Map 都有哪些遍历方式呢?这篇文章阿粉就带大家看一下,看看你经常使用的是哪一种。 通过 entrySet 来遍历 1、通过 for 和 map.entrySet() 来遍历 第一种方式是采用 for 和 Map.Entry 的形式来遍历,通过遍历 map.entrySet() 获取每个 entry 的 key 和 value,代码如下。这种方式一般也是阿粉使用的比较多的一种方式,没有什么花里胡哨的用法,就是很朴素的获取 map 的 key 和 value。 public static void testMap1(Map<Integer, Integer> map) { long sum = 0; for (Map.Entry<Integer, Integer> entry : map.entrySet()) { sum += entry.getKey() + entry.getValue(); } System.out.println(sum); } 看过 HashMap 源码的同学.....