当前位置: 首页 > news >正文

Controller 层优化四步曲

Controller 层优化四步曲

前言

在开发过程中,Controller 层作为系统与外界交互的桥梁,承担着接收请求、解析参数、调用业务逻辑、处理异常等职责。

然而,随着业务复杂度的增加,Controller 层的代码往往会变得臃肿且难以维护。

为了提升代码的可读性、可维护性以及系统的健壮性,我们可以通过以下四个步骤对 Controller 层进行改造:

  1. 统一返回结构
  2. 统一包装处理
  3. 参数校验
  4. 自定义异常与统一拦截异常

1.统一返回结构

在前后端分离的架构中,统一的返回结构能够显著提升接口的可读性和可维护性。

通过定义统一的返回格式,前端开发人员可以更清晰地判断接口调用是否成功,而不需要依赖返回值的具体内容。

定义返回数据结构

首先,我们可以定义一个通用的返回结构,包含状态码、状态信息以及返回的数据。

以下是一个示例:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result<T> {private Integer code;private String message;private T data;public static <T> Result<T> success(T data) {return new Result<>(200, "操作成功", data);}public static <T> Result<T> error(String message) {return new Result<>(500, message, null);}
}

在这个结构中,code 表示状态码,message 表示状态信息,data 则是具体的返回数据。

通过这种方式,所有的接口都可以返回统一的格式,便于前端处理。

2.统一包装处理

为了进一步简化 Controller 层的代码,我们可以使用 Spring 提供的 ResponseBodyAdvice 来统一处理返回值的包装。

这样,Controller 层只需要返回业务数据,而不需要手动封装返回结构。

使用 ResponseBodyAdvice 进行统一包装

@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,Class<? extends HttpMessageConverter<?>> selectedConverterType,ServerHttpRequest request, ServerHttpResponse response) {if (body instanceof Result) {return body;}return Result.success(body);}
}

通过这种方式,所有的 Controller 返回值都会被自动包装成 Result 对象,减少了重复代码。

3. 参数校验

参数校验是保证系统健壮性的重要手段。通过将参数校验逻辑从业务代码中剥离出来,不仅可以减少代码的耦合度,还能提升代码的可读性。

使用 @Validated 进行参数校验

Spring 提供了 @Validated 注解,可以方便地对请求参数进行校验。

我们可以在 DTO 对象中定义校验规则,并在 Controller 方法中使用 @Validated 注解进行校验。

@Data
public class UserDTO {@NotBlank(message = "用户名不能为空")private String username;@NotBlank(message = "密码不能为空")@Length(min = 6, max = 20, message = "密码长度必须在6到20之间")private String password;@Email(message = "邮箱格式不正确")private String email;
}@RestController
@RequestMapping("/user")
public class UserController {@PostMapping("/register")public Result<String> register(@RequestBody @Validated UserDTO userDTO) {// 业务逻辑return Result.success("注册成功");}
}

通过这种方式,参数校验的逻辑与业务逻辑完全解耦,代码更加清晰。

自定义异常与统一拦截异常

在实际开发中,系统可能会抛出各种异常。

为了提升系统的健壮性,我们可以自定义异常,并通过统一的异常拦截器来处理这些异常。

自定义异常

我们可以根据业务需求定义不同的异常类,例如 BusinessExceptionForbiddenException

public class BusinessException extends RuntimeException {public BusinessException(String message) {super(message);}
}public class ForbiddenException extends RuntimeException {public ForbiddenException(String message) {super(message);}
}

统一异常拦截

通过 @RestControllerAdvice@ExceptionHandler,我们可以统一处理系统中的异常,并返回统一的错误信息。

@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(BusinessException.class)public Result<String> handleBusinessException(BusinessException ex) {return Result.error(ex.getMessage());}@ExceptionHandler(ForbiddenException.class)public Result<String> handleForbiddenException(ForbiddenException ex) {return Result.error("无权访问");}@ExceptionHandler(Exception.class)public Result<String> handleException(Exception ex) {return Result.error("系统异常,请稍后重试");}
}

通过这种方式,所有的异常都会被统一处理,并返回给前端统一的错误格式。

总结

通过对 Controller 层的改造,我们可以显著提升代码的可读性、可维护性以及系统的健壮性。

统一的返回结构、自动化的参数校验、自定义异常与统一拦截异常,这些措施不仅减少了重复代码,还使得代码更加清晰和易于维护。

在实际开发中,我们可以根据具体的业务需求,进一步优化和扩展这些策略。

– 欢迎点赞、关注、转发、收藏【我码玄黄】,各大平台同名。

相关文章:

Controller 层优化四步曲

Controller 层优化四步曲 前言 在开发过程中&#xff0c;Controller 层作为系统与外界交互的桥梁&#xff0c;承担着接收请求、解析参数、调用业务逻辑、处理异常等职责。 然而&#xff0c;随着业务复杂度的增加&#xff0c;Controller 层的代码往往会变得臃肿且难以维护。 …...

Python数据分析-Python语法基础,IPython和Jupyter-Notebooks(二)

title: ‘Python数据分析:Python语法基础&#xff0c;IPython和Jupyter Notebooks&#xff08;二&#xff09;’ tags: python数据分析 categories:python数据分析 keywords:python数据分析 cover: …/img/404_icecream_whale.png description: 本文介绍python的基础语法和jup…...

Nginx 开发总结

文章目录 1. Nginx 基础概念1-1、什么是 Nginx1-2、Nginx 的工作原理1-3、Nginx 的核心特点1-4、Nginx 的常见应用场景1-5、Nginx 与 Apache 的区别1-6、 Nginx 配置的基本结构1-7、Nginx 常见指令 2. Nginx 配置基础2-1、Nginx 配置文件结构2-2、全局配置 (Global Block)2-3、…...

centos7安装SVN

[rootVM-16-3-centos ~]# yum install subversion -y [rootVM-16-3-centos ~]# svnserve --version // 创建目录 [rootVM-16-3-centos ~]# mkdir -p /opt/svn/repos // 创建新的空版本库&#xff0c;执行后会在repos文件夹下建立多个文件&#xff0c;待修改 [rootVM-16-3-cento…...

LTV预估 | 多视角对比学习框架CMLTV

&#x1f604; cmltv的loss好多哟&#xff0c;花样好多哟&#xff5e; 文章目录 1 精简总结2 背景&挑战3 方法4 实验 ✅【arxiv-2023 华为 CMLTV】《Contrastive Multi-view Framework for Customer Lifetime Value Prediction》 论文链接&#xff1a; https://arxiv.or…...

llama.cpp LLM_ARCH_DEEPSEEK and LLM_ARCH_DEEPSEEK2

llama.cpp LLM_ARCH_DEEPSEEK and LLM_ARCH_DEEPSEEK2 1. LLM_ARCH_DEEPSEEK and LLM_ARCH_DEEPSEEK22. LLM_ARCH_DEEPSEEK and LLM_ARCH_DEEPSEEK23. struct ggml_cgraph * build_deepseek() and struct ggml_cgraph * build_deepseek2()References 不宜吹捧中国大语言模型的同…...

C语言自定义数据类型详解(二)——结构体类型(下)

书接上回&#xff0c;前面我们已经给大家介绍了如何去声明和创建一个结构体&#xff0c;如何初始化结构体变量等这些关于结构体的基础知识。下面我们将继续给大家介绍和结构体有关的知识&#xff1a; 今天的主题是&#xff1a;结构体大小的计算并简单了解一下位段的相关知识。…...

DeepSeek学术写作测评第二弹:数据分析、图表解读,效果怎么样?

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 针对最近全球热议的DeepSeek开源大模型&#xff0c;娜姐昨天分析了关于论文润色、中译英的详细效果测评&#xff1a; DeepSeek学术写作测评第一弹&#xff1a;论文润色&#…...

深入理解 Python 中的 `__all__`:控制模块的公共接口

在 Python 编程中&#xff0c;模块化设计是构建可维护和可扩展代码的关键。模块不仅帮助我们组织代码&#xff0c;还能通过隐藏实现细节来提高代码的可读性和安全性。Python 提供了多种机制来控制模块的可见性&#xff0c;其中 __all__ 是一个非常重要但常被忽视的特性。本文将…...

虚幻基础07:蓝图接口

能帮到你的话&#xff0c;就给个赞吧 &#x1f618; 文章目录 作用原理事件函数 作用 实现对象间的通知。 A 通知 B 做什么。 原理 将接口抽象为蓝图&#xff0c;使得任意蓝图都能直接访问。 只需要再传入对象地址&#xff0c;就能执行对象的功能。 事件 黄色&#xff1a;…...

数据结构---哈希表

基本概念 哈希函数&#xff08;Hash Function&#xff09;是一种将输入的数据&#xff08;通常是任意大小的&#xff09;映射到固定大小的输出&#xff08;通常是一个固定长度的值&#xff09;的函数。这个输出值通常称为“哈希值”&#xff08;Hash Value&#xff09;或“哈希…...

DataWhale组队学习 leetCode task4

1. 滑动窗口算法介绍 想象你正在用一台望远镜观察一片星空。望远镜的镜头大小是固定的&#xff0c;你可以通过滑动镜头来观察不同的星区。滑动窗口算法就像这台望远镜&#xff0c;它通过一个固定或可变大小的“窗口”来观察数组或字符串中的连续区间。 滑动操作&#xff1a;就像…...

【ESP32】ESP-IDF开发 | WiFi开发 | UDP用户数据报协议 + UDP客户端和服务器例程

1. 简介 UDP协议&#xff08;User Datagram Protocol&#xff09;&#xff0c;全称用户数据报协议&#xff0c;它是一种面向非连接的协议&#xff0c;面向非连接指的是在正式通信前不必与对方先建立连接&#xff0c; 不管对方状态就直接发送。至于对方是否可以接收到这些数据内…...

【PyQt5】数据库连接失败: Driver not loaded Driver not loaded

报错内容如下&#xff1a; 可以看到目前所支持的数据库驱动仅有[‘QSQLITE’, ‘QMARIADB’, ‘QODBC’, ‘QODBC3’, ‘QPSQL’, ‘QPSQL7’] 我在网上查找半天解决方法未果&#xff0c;其中有一篇看评论反馈是可以使用的&#xff0c;但是PyQt5的版本有点低&#xff0c;5.12…...

Unity游戏(Assault空对地打击)开发(1) 创建项目和选择插件

目录 前言 创建项目 插件导入 地形插件 前言 这是游戏开发第一篇&#xff0c;进行开发准备。 创作不易&#xff0c;欢迎支持。 我的编辑器布局是【Tall】&#xff0c;建议调整为该布局&#xff0c;如下。 创建项目 首先创建一个项目&#xff0c;过程略&#xff0c;名字请勿…...

Rust:如何动态调用字符串定义的 Rhai 函数?

在 Rust 中使用 Rhai 脚本引擎时&#xff0c;你可以动态地调用传入的字符串表示的 Rhai 函数。Rhai 是一个嵌入式脚本语言&#xff0c;专为嵌入到 Rust 应用中而设计。以下是一个基本示例&#xff0c;展示了如何在 Rust 中调用用字符串传入的 Rhai 函数。 首先&#xff0c;确保…...

A星算法两元障碍物矩阵转化为rrt算法四元障碍物矩阵

对于a星算法obstacle所表示的障碍物障碍物信息&#xff0c;每行表示一个障碍物的坐标&#xff0c;例如2 , 3; % 第一个障碍物在第二行第三列&#xff0c;也就是边长为1的正方形障碍物右上角横坐标是2&#xff0c;纵坐标为3&#xff0c;障碍物的宽度和高度始终为1.在rrt路径规划…...

【C++】设计模式详解:单例模式

文章目录 Ⅰ. 设计一个类&#xff0c;不允许被拷贝Ⅱ. 请设计一个类&#xff0c;只能在堆上创建对象Ⅲ. 请设计一个类&#xff0c;只能在栈上创建对象Ⅳ. 请设计一个类&#xff0c;不能被继承Ⅴ. 请设计一个类&#xff0c;只能创建一个对象&#xff08;单例模式&#xff09;&am…...

单细胞分析基础-第一节 数据质控、降维聚类

scRNA_pipeline\1.Seurat 生物技能树 可进官网查询 添加链接描述 分析流程 准备:R包安装 options("repos"="https://mirrors.ustc.edu.cn/CRAN/") if(!require("BiocManager")) install.packages("BiocManager",update = F,ask =…...

多项日常使用测试,带你了解如何选择AI工具 Deepseek VS ChatGpt VS Claude

多项日常使用测试&#xff0c;带你了解如何选择AI工具 Deepseek VS ChatGpt VS Claude 注&#xff1a;因为考虑到绝大部分人的使用&#xff0c;我这里所用的模型均为免费模型。官方可访问的。ChatGPT这里用的是4o Ai对话&#xff0c;编程一直以来都是人们所讨论的话题。Ai的出现…...

Magisk完整实践指南:从Root权限获取到系统级定制

Magisk完整实践指南&#xff1a;从Root权限获取到系统级定制 【免费下载链接】Magisk The Magic Mask for Android 项目地址: https://gitcode.com/GitHub_Trending/ma/Magisk Magisk作为Android系统Root权限管理的主流解决方案&#xff0c;提供了系统级定制能力而无需修…...

S2-Pro模型管理利器:Ollama国内镜像源加速下载与使用

S2-Pro模型管理利器&#xff1a;Ollama国内镜像源加速下载与使用 1. 为什么需要国内镜像源 如果你在国内使用Ollama管理S2-Pro等大模型&#xff0c;可能经常遇到下载速度慢、连接不稳定甚至完全无法拉取模型的问题。这是因为默认的模型仓库位于海外服务器&#xff0c;受网络环…...

Cohere Transcribe:20亿参数14语言开源语音识别模型发布

Cohere Transcribe&#xff1a;20亿参数14语言开源语音识别模型发布 【免费下载链接】cohere-transcribe-03-2026 项目地址: https://ai.gitcode.com/hf_mirrors/CohereLabs/cohere-transcribe-03-2026 导语&#xff1a;Cohere正式发布开源语音识别模型Cohere Transcri…...

查询参数拼接

export function objectToQueryString(params) {return Object.entries(params).filter(([key, value]) > value ! undefined && value ! null) // 过滤掉 undefined 和 null.map(([key, value]) > ${encodeURIComponent(key)}${encodeURIComponent(value)}).joi…...

aibye爱毕业推出六大顶尖平台评测,智能润色与高效创作功能一键实现,科研领域不可或缺的AI助手

工具名称 核心功能 特色优势 Aibiye 论文生成降AI率 全学科覆盖、仿写优化、自动图表生成 Aicheck AI检测文献综述辅助 精准查新、3分钟高效成文 GPT学术版 润色/翻译/代码解释 多模型协同、PDF深度解析 摆平论文 大纲生成降重改写 三步出稿、本硕博通用 QuillB…...

I3C协议学习总结

I3C可以使用推挽式&#xff0c;节省功耗&#xff0c;速度更快SDR 单数据传输速率&#xff0c; SCL时钟频率可达到12.5MHz所有符合I3C标准的设备都必须要拥有一个总线特性寄存器1. I3C 协议模式概览 (Section 5)文档首先列出了 I3C 支持的几种主要通信模式&#xff1a;SDR (Sing…...

FastAPI异步测试终极指南:如何快速模拟HTTP请求进行高效测试

FastAPI异步测试终极指南&#xff1a;如何快速模拟HTTP请求进行高效测试 【免费下载链接】fastapi FastAPI framework, high performance, easy to learn, fast to code, ready for production 项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi FastAPI异步测…...

KinhDown:突破百度网盘限速的效率革命

KinhDown&#xff1a;突破百度网盘限速的效率革命 【免费下载链接】baidupcs-web 项目地址: https://gitcode.com/gh_mirrors/ba/baidupcs-web 在数字化时代&#xff0c;云存储已成为我们工作与生活中不可或缺的一部分。然而&#xff0c;百度网盘对免费用户实施的严格限…...

大麦抢票神器:3步轻松实现演唱会门票自动化抢购终极指南

大麦抢票神器&#xff1a;3步轻松实现演唱会门票自动化抢购终极指南 【免费下载链接】ticket-purchase 大麦自动抢票&#xff0c;支持人员、城市、日期场次、价格选择 项目地址: https://gitcode.com/GitHub_Trending/ti/ticket-purchase 还在为抢不到心仪演唱会门票而烦…...

DeepSeek-Coder-V2:开源代码助手如何超越商业模型实现90%代码生成准确率?

DeepSeek-Coder-V2&#xff1a;开源代码助手如何超越商业模型实现90%代码生成准确率&#xff1f; 【免费下载链接】DeepSeek-Coder-V2 项目地址: https://gitcode.com/GitHub_Trending/de/DeepSeek-Coder-V2 还在为代码编写效率低下而苦恼吗&#xff1f;作为开发者的你…...