项目设计
文章平均质量分 88
smart哥
一名有10余年经验的互联网老兵,历经从传统软件公司到大型互联网公司的洗礼,早年在中兴通讯等大型通信公司担任项目leader,后随着互联网的崛起,先后在前美团支付等大型互联网公司担任架构师。对互联网架构底层技术有相当的研究和独特的见解,在多个领域有着丰富的实战经验。
展开
-
快速改善代码的几个小建议
本文举例的代码,仅做案例讨论。影响代码质量最大的因素其实是开发进度,写得不好有时未必是能力不够。原创 2023-12-25 09:05:20 · 987 阅读 · 0 评论 -
浅谈Redis分布式锁(下)
在上一篇我们自定义了一个Redis分布式锁,用来解决多节点定时任务的拉取问题(避免任务重复执行):加锁操作不是原子性的(setnx和expire两步操作不是原子性的,中间宕机会导致死锁)// 1.先setnxif (lock!// 2.再expire} else {/*** 尝试上锁:setNX + expire* @param lockKey 锁* @param value 对应的值* @param expireTime 过期时间* @param timeUnit 时间单位。原创 2023-12-24 10:06:38 · 1021 阅读 · 0 评论 -
浅谈Redis分布式锁(中)
我们在不久前介绍了SpringBoot定时任务,最近又一起探究了如何使用Redis实现简单的消息队列,都是一些不错的小知识点。为了能跟前面的内容产生联动,这次我们打算把Redis分布式锁相关的介绍融合进定时任务的案例中,学起来更带劲~原创 2023-12-24 09:52:16 · 855 阅读 · 0 评论 -
浅谈Redis分布式锁(上)
明白了“JVM锁”名字的由来,我们再来聊什么是“锁”,以及怎么“锁”。有时候我们很难阐述清楚某个事物是什么,但很容易解释它能干什么,JVM锁也是这个道理。JVM锁的出现,就是为了解决线程安全问题。所谓线程安全问题,可以简单地理解为数据不一致(与预期不一致)。什么时候可能出现线程安全问题呢?多线程环境有共享数据有多条语句操作共享数据/单条语句本身非原子操作(比如i++虽然是单条语句,但并非原子操作)原创 2023-12-23 10:02:56 · 954 阅读 · 0 评论 -
异步消息原理
在日常开发中,偶尔需要在主业务逻辑之外做一些附加操作,比如下单成功后通知商家、课程报名成功后通知老师、简历投递成功后通知HR。结果[main] INFO - 插入投递记录完毕...[main] INFO - 【发送消息】HR你好,用户:mx, 投递你的岗位:叉车师傅[main] INFO - 【保存消息】保存到数据库, 用户:mx, 岗位:叉车师傅[main] INFO - com.bravo.happy.AsyncNotifyTest - 耗时:3019毫秒。原创 2023-12-23 09:57:00 · 860 阅读 · 0 评论 -
Thymeleaf发送邮件
此时可以结合SpringBoot Mail + Thymeleaf,以Thymeleaf为页面模板,把需要替换的数据交给模板引擎渲染成静态页面,最后作为邮件的text发送即可。而且个别情况下,我们还需要根据用户的性别分别显示♂、♀,也就是需要按条件显示。对于消息提醒,目前的软件开发越来越倾向于发送短信或使用IM,但邮件依旧有着不可代替的作用,比如正式的面试邀请及offer发放等。稍微提一下模板路径的问题:Thymeleaf默认目录是templates,默认模板后缀是.html,所以可以都省略。原创 2023-12-22 08:20:36 · 584 阅读 · 0 评论 -
自定义权限管理:RBAC
这无疑会加大我们的工作量,但“自动化”与“精细控制”本身确实存在一定的取舍。有更好的做法欢迎留言~原创 2023-12-22 08:12:59 · 896 阅读 · 0 评论 -
自定义权限管理:用户即角色
还是一样,只贴出核心代码。原创 2023-12-22 08:06:37 · 557 阅读 · 0 评论 -
自定义权限管理:登录拦截
在大家的印象中,对于一个系统而言,需要登录的接口占多数还是不需要登录的接口占多数呢?答案是不一定。如果是后台接口,那么基本都是要登录的,而对于前台接口或者APP,那就有可能五五开了。比如很多APP都提供了游客模式,下载APP能浏览一些问题和回答,但要发表文章或评论时,就会提醒你登录。为什么要问这个问题呢?具体选哪种,取决于你的系统属于哪种。本文假定大部分接口无需登录,只对部分接口做限制。代码几乎一样,大家可以自己改改。这里只贴出核心代码,一切工具类封装请参考小册其他章节。原创 2023-12-21 08:51:36 · 429 阅读 · 0 评论 -
自定义权限管理系统概述
今天我们来聊聊如何自定义一个简单易用的权限管理系统。虽然市面上已经有很多出色的权限管理框架,比如Spring Security或者Shiro,但很多时候我们并不需要那么多功能,特别是Spring Security,学习成本太高了!我曾经有一位同事,为了做用户权限管理,硬是引入了当时大家都不太熟悉的Spring Security,然后整了一个多星期,合并代码后直接把整个组的接口都拦截了,我直接好家伙。关键是他也不知道哪里配错了,搞了很久还是没解决,最终只好回滚代码,耽误了大半天时间。原创 2023-12-21 08:48:04 · 955 阅读 · 0 评论 -
如何设计用户评论表
上一篇提到树形结构是非常经典的一种表设计模式,看似平平无奇,实则包罗万象。今天,我们借助“用户评论”的需求,再来领略一把树形结构的魅力。原创 2023-12-21 08:22:48 · 2508 阅读 · 1 评论 -
如何设计树形结构
我以前接触过一个前端插件,叫zTree。这个插件的作用是把接口返回的数据以树形结构的形式展示出来:--1.准备一个Div,设置id-->// 2.需要的数据name:"父节点1 - 展开",open:true,name:"父节点11 - 折叠",{ name:"叶子节点111"},{ name:"叶子节点112"},{ name:"叶子节点113"},{ name:"叶子节点114"}},name:"父节点12 - 折叠",{ name:"叶子节点121"},原创 2023-12-20 08:37:47 · 1710 阅读 · 0 评论 -
AOP与日志(下)
一般来说,前者的数据被保存在log文件中,只是面向开发者,普通用户不易阅读,而后者被称为“用户行为日志”,通常还会额外提供查询接口和专门的页面,方便管理员查看操作记录。今天,我们就来聊聊所谓的“用户行为日志”。本文的处理是把所有参数都转为JSON存储,遇到保存文章等大文本数据时会报错。处理办法是:代码中进行长度处理或者调大content的长度(也可以改为text)上面的代码主要提供一个思路,大家可以根据实际需求扩展或改编。原创 2023-12-20 08:23:00 · 496 阅读 · 0 评论 -
AOP与日志(上)
可以登录服务器看log,或者有些公司的运维会搭建专门的ELK日志系统,可以在页面上选择对应的机器并配合Lucene语句等进行日志查看。这个注解最重要的其实是@Import注解,它是Spring定义的注解,由Spring读取并执行:把对应的Bean实例化并加载到容器。但这个是局部的、特殊的日志,如果出错的接口刚好没有任何日志,线上出现问题时基本就是“抓瞎”,所以全局的、一般的日志记录很有必要。现在想想,当时的自己听到这么简单的问题,觉得捡了一个大便宜,甚至还暗暗佩服自己考虑得很周到:要先推断出对应的接口。原创 2023-12-20 08:21:10 · 790 阅读 · 0 评论 -
DTO/DO/VO分层与拷贝
阿里巴巴开发手册》以及网上各种博客或多或少都有提到诸如DTO、DO、BO、PO、VO等等,也提倡对实体类进行分层。至于为什么要分层,它们的理由是“避免暴露内部设计细节,只展示必要的字段”,但我个人最大的感受其实是“解耦”。我曾遇到一件无奈的事,接口已经开发完毕,前后端也联合好了,结果产品临时要大改,Service层的逻辑基本要推倒重来,连查的表都不一样了。好在得益于DTO和VO的隔离,并没有影响到其它层,前端甚至完全不知道后端全部重写了,Swagger文档也和原来一模一样...原创 2023-12-19 10:46:22 · 1008 阅读 · 0 评论 -
再看参数校验
业务代码总是变化的,没太多可说的,统一结果封装我们已经介绍过,今天我们来聊聊参数校验的琐事。老实说,参数校验很烦!其实对于上面两种方式,Spring都提供了解决方案。很多人只知道Spring Validation,却不知道简单好用的Assert。只要在全局异常处理IllegalArgumentException即可。但个人觉得还是自己封装自由度高一些,所以我们按照这个思路,写一个ValidatorUtils。原创 2023-12-19 10:38:00 · 1368 阅读 · 0 评论 -
我从阿里云学到的返回值处理技巧
要明确一点,SpringBoot其实只会处理@Controller/@RestController,包括Controller Bean的实例化及返回值处理。@CosmoController哪位?没听过。但我们可以学习@RestController的逆袭之路:看到没,SpringBoot准确来说只认@Controller+@ResponseBody,但@RestController为了让SpringBoot承认自己,直接把两位大哥带在身边了(注解上面加注解,并不是什么新鲜事,你看@Target)。原创 2023-12-19 10:23:24 · 1108 阅读 · 0 评论 -
如何处理异常
在resources/error下存放404.html和500.html,当本次请求状态码为404或500时,SpringBoot就会读取我们自定义的html返回,否则返回默认的错误页面。现在一般都是前后端分离,所以关于自定义错误页面就略过了。"data": {}// 请求成功后的处理逻辑当接口异常时,返回的JSON却没有code,会比较错愕。为了统一JSON响应格式,我们需要对异常进行处理。在代码中使用工具类封装(ApiResultTO/Result)用全局异常处理兜底。原创 2023-12-19 10:20:18 · 745 阅读 · 0 评论 -
统一结果封装
每家公司对于统一结果的封装各不相同,命名也大相径庭,有叫ResponseVO的,也有叫ResultVO的,还有叫ApiResultTO的,静态方法有success()、error(),也有buildSuccess()、buildFailed(),这些都不重要,归根结底是同一种东西。需要提一下的是,对于电商APP,你会发现大部分情况下它的“分页”都是采用“上滑”触发的,即本次请求的数据到底后,才会触发下一次请求。但接口除了返回单个对象,还可能返回列表,此时后端必须返回相关的分页信息,又怎么处理呢?原创 2023-12-18 11:06:17 · 950 阅读 · 0 评论