禁止血压飙升:阿里大佬写的Controller太优雅了!

见过几千行代码的 controller吗?我见过。

见过全是 try catch 的 controller 吗,我见过。

见过全是字段校验的 controller 吗,我见过。

见过全是业务代码的 controller 吗?不好意思,我们公司很多业务写在 controller 的。

看见这些我真的血压高。

不优雅的 controller

@RestController @RequestMapping("/user/test") publicclassUserController{ privatestatic Logger logger = LoggerFactory.getLogger(UserController.class); @Autowired private UserService userService; @Autowired private AuthService authService; @PostMapping public CommonResult userRegistration(@RequestBody UserVo userVo){ if (StringUtils.isBlank(userVo.getUsername())){ return CommonResult.error("用户名不能为空"); } if (StringUtils.isBlank(userVo.getPassword())){ return CommonResult.error("密码不能为空"); } logger.info("注册用户:{}" , userVo.getUsername()); try { userService.registerUser(userVo.getUsername()); return CommonResult.ok(); }catch (Exception e){ logger.error("注册用户失败:{}", userVo.getUsername(), e); return CommonResult.error("注册失败"); } } @PostMapping("/login") @PermitAll @ApiOperation("使用账号密码登录") public CommonResult<AuthLoginRespVO> login(@RequestBody AuthLoginReqVO reqVO){ if (StringUtils.isBlank(reqVO.getUsername())){ return CommonResult.error("用户名不能为空"); } if (StringUtils.isBlank(reqVO.getPassword())){ return CommonResult.error("密码不能为空"); } try { return success(authService.login(reqVO)); }catch (Exception e){ logger.error("注册用户失败:{}", reqVO.getUsername(), e); return CommonResult.error("注册失败"); } } }

优雅的controller

@RestController @RequestMapping("/user/test") publicclassUserController1{ privatestatic Logger logger = LoggerFactory.getLogger(UserController1.class); @Autowired private UserService userService; @Autowired private AuthService authService; @PostMapping("/userRegistration") public CommonResult userRegistration(@RequestBody @Valid UserVo userVo){ userService.registerUser(userVo.getUsername()); return CommonResult.ok(); } @PostMapping("/login") @PermitAll @ApiOperation("使用账号密码登录") public CommonResult<AuthLoginRespVO> login(@RequestBody @Valid AuthLoginReqVO reqVO){ return success(authService.login(reqVO)); } }

代码量直接减一半呀,这还不算上有些直接把业务逻辑写在 controller 的,看到这些我真的直接吐血

改造流程

校验方式

这个 if 校验看得我哪哪都不爽。好歹给我写一个断言吧。Assert.notNull(userVo.getUsername(), "用户名不能为空");

这不香吗?确实不香。

使用 spring 提供的@Valid

在入参时使用@Valid注解,并且在 vo 中使用校验注解,如AuthLoginReqVO

复制代码@ApiModel(value = "管理后台 - 账号密码登录 Request VO") @Data @NoArgsConstructor @AllArgsConstructor @Builder publicclassAuthLoginReqVO{ @ApiModelProperty(value = "账号", required = true, example = "user") @NotEmpty(message = "登录账号不能为空") @Length(min = 4, max = 16, message = "账号长度为 4-16 位") @Pattern(regexp = "^[A-Za-z0-9]+$", message = "账号格式为数字以及字母") private String username; @ApiModelProperty(value = "密码", required = true, example = "password") @NotEmpty(message = "密码不能为空") @Length(min = 4, max = 16, message = "密码长度为 4-16 位") private String password; }

@Valid

在SpringBoot中,@Valid是一个非常有用的注解,主要用于数据校验。以下是关于@Valid的一些详细信息:

为什么使用 @Valid 来验证参数:在编写接口时,我们经常需要验证请求参数。通常,我们可能会写大量的 if 和 if else 代码来进行判断。但这样的代码不仅不优雅,而且如果存在大量的验证逻辑,这会使代码看起来混乱,大大降低代码可读性。为了简化这个过程,我们可以使用 @Valid 注解来帮助我们简化验证逻辑。

如果你近期准备面试跳槽,建议在ddkk.com在线刷题,涵盖 一万+ 道 Java 面试题,几乎覆盖了所有主流技术面试题,还有市面上最全的技术五百套,精品系列教程,免费提供。

@Valid 注解的作用:@Valid 的主要作用是用于数据效验,可以在定义的实体中的属性上,添加不同的注解来完成不同的校验规则,而在接口类中的接收数据参数中添加 @valid 注解,这时你的实体将会开启一个校验的功能。

@Valid 的相关注解:在实体类中不同的属性上添加不同的注解,就能实现不同数据的效验功能。

使用 @Valid 进行参数效验步骤:整个过程如下,用户访问接口,然后进行参数效验,因为 @Valid 不支持平面的参数效验(直接写在参数中字段的效验)所以基于 GET 请求的参数还是按照原先方式进行效验,而 POST 则可以以实体对象为参数,可以使用 @Valid 方式进行效验。如果效验通过,则进入业务逻辑,否则抛出异常,交由全局异常处理器进行处理。

@Validated与@Valid的区别@Validated@Valid的变体。通过声明实体中属性的groups,再搭配使用@Validated,就能决定哪些属性需要校验,哪些不需要校验。

全局异常处理

这个全局异常处理,可以根据自己的异常,自定义异常处理,并设置一个兜底的异常处理

@ResponseBody @RestControllerAdvice publicclassExceptionHandlerAdvice{ protected Logger logger = LoggerFactory.getLogger(getClass()); @ExceptionHandler(MethodArgumentNotValidException.class) publicCommonResult<Object> handleValidationExceptions(MethodArgumentNotValidExceptionex) { logger.error("[handleValidationExceptions]", ex); StringBuilder sb = new StringBuilder(); ex.getBindingResult().getAllErrors().forEach(error -> { String fieldName = ((org.springframework.validation.FieldError) error).getField(); String errorMessage = error.getDefaultMessage(); sb.append(fieldName).append(":").append(errorMessage).append(";"); }); return CommonResult.error(sb.toString()); } /** * 处理系统异常,兜底处理所有的一切 */ @ExceptionHandler(value = Exception.class) publicCommonResult<?> defaultExceptionHandler(Throwableex) { logger.error("[defaultExceptionHandler]", ex); // 返回 ERROR CommonResult return CommonResult.error(INTERNAL_SERVER_ERROR.getCode(), INTERNAL_SERVER_ERROR.getMsg()); } }

就这么多,搞定,这样就拥有了漂流优雅的 controller 了

在日常开发中,还有那些血压飙升瞬间

我拿出下图阁下如何面对

这个阁下又如何面对,我不说,你能知道这个什么吗【狗头】

总结

不是很明白为什么有些喜欢在 controller 写业务逻辑的,曾经有个同事问我(就是喜欢在 controller 写业务的),你这个接口写在那里,我需要调一下你这个接口。我满脸问号??不是隔壁的模块吗,为什么要调我的接口?直接引用的我的 service 去调方法就好了。

这个就是痛点,各写各的,冗余代码一堆。

曾经看到一个同事写一个保存的方法,虽然逻辑挺多,我滑动了好久都还没有方法还没有结束。一个方法整整几百行……

看过 spring 源码都知道,spring 源码难啃,就是因为 spring 无限往下套娃,基本每个方法干每个方法的事情。比如我保存用户时,就只是保存用户,至于什么校验丢给校验的方法处理,什么发送消息丢给发送消息处理,这些就不能耦合在一起。

对于看到一些 if 下面一丢逻辑,然后 if 再一丢逻辑,看代码时很多情况不需要知道这个逻辑怎么实现的,知道入参出参就大概这里做什么了。即使想知道详细情况点进去就知道了。突出这个当前方法要做的事情就好了。

阿里的开发手册就推荐一个方法不能超过 80 行,超过可以根据业务具体调整一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1184707.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Office 2021安装包免费版永久使用,附永久破解工具+详细安装教程

一、Office 2021软件下载 软件名称:Office 2021 软件大小:5.21GB 安装环境:Win10\Win11 下载链接: (建议手机保存后到电脑端打开,无需任何密码) 夸克下载:https://pan.quark.cn/s/a10ffe56e295 二、Office 2021…

微调与安全隐私:AI定制时代的机遇与防线

引言:当AI定制遇上安全挑战 在AI技术飞速普及的今天,大模型早已从实验室走进实际应用场景。我们可能在工作中用AI生成行业报告,在生活中依赖智能助手解答问题,在创业项目中借助AI提升效率——但通用大模型往往存在…

阿里跳槽来的工程师,写个try catch的方式都这么优雅!

软件开发过程中&#xff0c;不可避免的是需要处理各种异常&#xff0c;就我自己来说&#xff0c;至少有一半以上的时间都是在处理各种异常情况&#xff0c;所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块&#xff0c;不仅有大量的冗余代码&#xff0c;而…

Redis 分片集群 完整性能测试报告

目录标题redis-2ffca4ed 分片集群 完整性能测试报告目录一、测试概述1.1 测试目标1.2 测试工具1.3 测试架构二、环境配置2.1 集群信息2.2 Redis 组件状态2.3 Predixy 配置演变三、测试阶段总结3.1 测试时间线3.2 各阶段关键指标3.3 性能提升总览四、详细性能数据4.1 初始测试 (…

接口防刷处理,这样实现更优雅!

前言本文为描述通过Interceptor以及Redis实现接口访问防刷Demo这里会通过逐步找问题&#xff0c;逐步去完善的形式展示原理通过ip地址uri拼接用以作为访问者访问接口区分通过在Interceptor中拦截请求&#xff0c;从Redis中统计用户访问接口次数从而达到接口防刷目的如下图所示工…

安克创新与飞书联合发布“安克 AI 录音豆” 手指可握仅重 10 克

2026 年 1 月 19 日&#xff0c;安克创新与飞书联合发布了最新 AI 硬件——安克 AI 录音豆&#xff0c;飞书提供了该产品的软件 AI 适配与服务。这款产品以极轻的"磁吸纽扣”形态实现无感随身佩戴&#xff0c;基于飞书 AI 能力&#xff0c;支持声纹识别、实时转写与翻译、…

深入探讨大数据领域数据工程的发展趋势

好的&#xff0c;请看这篇关于大数据领域数据工程发展趋势的深度技术博客。数据工程的未来图景&#xff1a;从ETL到智能数据网格的演进之路 引言&#xff1a;我们正站在数据洪流的十字路口 想象一下&#xff0c;你是一家大型电商公司的首席数据官。每天&#xff0c;你的系统需要…

【技术收藏】风控系统的革命:大模型如何让审核员和初级算法工程师失业?

文章分享了风控系统中使用大模型替代人工审核的经验&#xff0c;发现大模型能在100-200ms内高效完成风险文本标注&#xff0c;通过优化prompt即可解决问题&#xff0c;极大简化了原有流程。这种"发现问题->修改prompt->上线"的模式使审核员和初级算法工程师面临…

自己写一个分布式定时任务框架+负载均衡+OpenAPI异步调用!

项目背景目前的定时任务框架已经很成熟&#xff0c;从QuartZ到xxl-job&#xff0c;再到近几年出现的PowerJob&#xff0c;既然有这么多的好的实现&#xff0c;为什么还是选择重写一个定时任务框架呢&#xff1f;开发中遇到这样的场景&#xff0c;业务层面需要频繁的创建修改定时…

(TETCI 2024) 从 U-Net 到 Transformer:即插即用注意力模块解析

小伙伴们好&#xff0c;我是小嬛。专注于人工智能、计算机视觉领域相关分享研究。【目标检测、图像分类、图像分割、目标跟踪等项目都可做&#xff0c;相关领域论文辅导也可以找我&#xff1b;需要的可联系&#xff08;备注来意&#xff09;】-------正文开始--------论文题目&…

如何加快 SQL 查询速度的同时保持 SQL 的简洁性?

在本文中&#xff0c;我们将讨论如何提高SQL查询速度的同时&#xff0c;还能保持SQL语句的简洁。在进入主题之前&#xff0c;我们先了解一下查询的实际处理过程&#xff1a;1. 查询处理过程查询处理过程被定义为通过一系列从数据库中提取数据的过程。这涉及将SQL语句的转换为数…

MyBatis-Flex来了!完爆MyBatis-Plus?

Mybatis-Flex 是一个优雅的 Mybatis 增强框架&#xff0c;它非常轻量、同时拥有极高的性能与灵活性。我们可以轻松的使用 Mybaits-Flex 链接任何数据库&#xff0c;其内置的 QueryWrapper^亮点 帮助我们极大的减少了 SQL 编写的工作的同时&#xff0c;减少出错的可能性。总而言…

25年的关键词:失业、工伤、外包、投资回血……

引言 「2025」 年就这么稀里糊涂的过去咯, 前不久正巧听到播客不禁感慨, 于世界而言「2025」这一年属实精彩: 年初的 Deepseek、宇树机器人爆火特朗普上台后各种折腾, 关税战一度引起全球股市暴跌, 而最后又好像啥也没发生一样后面泡泡马特爆火、小红书出圈...之后又有雷军塌…

即插即用系列 | CVPR 2025 CATANet:一种用于轻量级图像超分辨率的高效内容感知 Token 聚合网络

论文题目&#xff1a;CATANet: Efficient Content-Aware Token Aggregation for Lightweight Image Super-Resolution 论文原文 (Paper)&#xff1a;https://arxiv.org/abs/2503.06896 官方代码 (Code)&#xff1a;https://github.com/EquationWalker/CATANet GitHub 仓库链接&…

牛掰,MySQL 8.2 支持读写分离了!

MySQL InnoDB ReplicaSet启动 MySQL Router 8.2结论我们一直在等待的 MySQL 读/写分离功能 现在终于可以使用了&#xff01;在规模上&#xff0c;我们在副本之间分配读取&#xff0c;但这必须在应用程序中以某种方式进行管理&#xff1a;指向在某个地方写入并在其他地方读取。在…

【PFJSP问题】自适应双种群协同鸡群算法ADPCCSO求解置换流水车间调度问题PFSP【含Matlab源码 14995期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;Matlab武动乾坤博客之家&#x1f49e;…

洛谷 P3746 [六省联考 2017] 组合数问题

题目链接 题目求 \(\displaystyle \sum _ {i = 0} [x ^ {ik + r}] (1 + x) ^ {nk}\),定义多项式的循环卷积为两个多项式相乘后,把所有 \(x ^ i\) 的项合并到 \(x ^ {i \bmod k}\)。快速幂加速即可。 时间复杂度 \(\t…

公司弃用 Nginx,选择这款工具!

Cloudflare 公司宣布弃用 nginx&#xff0c;转用自研的新一代方向代理服务 Pingora&#xff0c;并号称比nginx更快、更高效、更安全&#xff0c;下面通过 Cloudfare 官方网站的一篇文章来了解下 Pingora 比 Nginx 强在哪里&#xff1f;简介今天&#xff0c;我们很高兴有机会在此…

【DPFSP问题】自适应双种群协同鸡群算法ADPCCSO求解分布式置换流水车间调度DPFSP【含Matlab源码 14996期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;Matlab武动乾坤博客之家&#x1f49e;…

洛谷 P3747 [六省联考 2017] 相逢是问候

题目链接 欧拉降幂最多只会迭代到第 \(k = \text O (\log p)\) 次模数就会变成 \(1\)(证明见这里)。故一个数被操作超过 \(k\) 次就会变为一个定值。 于是用线段树维护出操作还没有满 \(k\) 次的位置,每次暴力修改并…