如何写得一手优雅规范的SpringBoot 接口?

导语

优雅的代码赏心悦目,你的代码触目惊心。

当编写 Spring Boot 接口时,优雅和规范是至关重要的。一个良好设计的接口能够提高代码的可读性、可维护性和可扩展性,从而为整个应用程序的开发和维护带来便利。

在本文中,我们将探讨如何通过遵循最佳实践和设计原则,编写出优雅规范的 Spring Boot 你的接口也可以像企业级项目接口一般规范且优雅。


严格遵循RESTful API 设计原则

  • 清晰一致的资源命名:使用准确反映 API 管理的资源的名词(例如,/articles、/users)。
@GetMapping("/articles/{id}")
public ResponseEntity<Product> getArticleById(@PathVariable Long id) {// ...
}
  • 标准化 HTTP 方法:遵循 CRUD 操作的 RESTful 约定(CREATE: POST、READ: GET、UPDATE: PUT、DELETE:DELETE)。
@PostMapping("/users")
public ResponseEntity<User> createUser(@RequestBody User user) {// ...
}
  • 有意义的状态代码:返回相应的 HTTP 状态代码,如成功 (2xx)、错误 (4xx) 或服务器问题 (5xx)。
@DeleteMapping("/articles/{id}")
public ResponseEntity<?> deleteArticle(@PathVariable Long id) {if (productService.deleteArticle(id)) {return ResponseEntity.noContent().build(); // 204 No Content} else {return ResponseEntity.notFound().build(); // 404 Not Found}
}

关于更多restful标准,参考https://en.wikipedia.org/wiki/REST


合理利用好 Spring Boot 注解

这里所谓得合理,不是很好定义,但本着高效、简洁、清晰得原则推荐。

  • @RestController:默认情况下,将控制器标记为返回 JSON 或其他结构化数据。

这是一个综合注解,是@Controller@ResponseBody的功能于一身,一个注解作两个注解的事情,简洁高效。

@RestController
public class HelloController {// .....
}
  • @RequestMapping:定义每个controller的基本路径。

这样做可以使代码更加整洁和易于维护。不需要在每个方法上都重复写基本路径部分,在类级别定义基本路径可以带来更清晰、更简洁、更易维护的代码结构,同时也有助于提高开发效率和代码质量。

@RestController
@RequestMapping("/user")
public class HelloController {// .....
}
  • 使用简化的请求方式注解。

在不同类型的方法上直接使用@GetMapping、@PostMapping、@PutMapping@DeleteMapping注解进行标识,而不是使用笼统的 @RequestMapping(method = RequestMethod.POST)

  • 使用@PathVariable获取请求的路径变量;
@RestController
@RequestMapping("/articles")
public class ArticleController {@GetMapping("/{id}")public ResponseEntity<Article> getArticleById(@PathVariable Long id) {// 根据文章的id查询文章Article article = articleService.findArticleById(id);if (article != null) {return ResponseEntity.ok(article);} else {return ResponseEntity.notFound().build();}}
}
  • 使用@RequestBody将请求正文内容反序列化为 Java 对象。
@RestController
@RequestMapping("/api")
public class UserController {@PostMapping("/users")public ResponseEntity<User> createUser(@RequestBody User user) {// 这里的 User 对象会从请求的 JSON 数据中反序列化得到userService.saveUser(user);return ResponseEntity.ok(user);}
}

关于依赖注入的使用建议

  • 使用构造函数注入方式

通过在类的构造函数中接受依赖对象作为参数来进行注入。这种方式可以确保依赖在对象创建时被注入,提高了代码的可测试性和可维护性。

@RestController
public class ProductController {private final ProductService productService;public ProductController(ProductService productService) {this.productService = productService;}// ... other controller methods
}

针对接口的异常处理

  • @ControllerAdvice的使用
@ControllerAdvice
public class ApiExceptionHandler {@ExceptionHandler(ArticleNotFoundException.class)public ResponseEntity<ErrorResponse> handleArticleNotFound(ArticleNotFoundException ex) {// ... create error response with detailsreturn ResponseEntity.status(HttpStatus.NOT_FOUND).body(errorResponse);}
}

使用DTO代替POJO的直接使用

对于数据传输对象,建议对pojo进行dto的封装,而不是使用原实体。提高代码的可读性、可维护性和数据封装性。

public class ArticleDto {private Long id;private String title;private String contents;// more
}

接口安全的建议

  • 使用SpringSecurity等安全框架进行认证授权,包括令牌机制的使用,如JWT
  • 对接口进行常见的漏洞检查并采取防范措施,比如XSSSQL注入等。
  • 使用https进行网络通信;

关于版本控制

  • 使用路径版本控制(例如,/api/v1/articles)或基于标头的版本控制。

使用版本控制 API 来管理更改并保持与客户端的兼容性。

@RestController
@RequestMapping("/api/products")
public class ProductController {@GetMapping("/details")public ResponseEntity<String> getProductDetails(@RequestHeader("Accept-Version") String version) {if ("v1".equals(version)) {return ResponseEntity.ok("Product details for version 1");} else if ("v2".equals(version)) {return ResponseEntity.ok("Product details for version 2");} else {return ResponseEntity.badRequest().body("Unsupported version");}}
}

完备的接口测试

  • 考虑使用 Mockito JUnit 等工具对每个接口进行测试,保证接口的准确性和稳健性。

本文小结

上面虽然列举好几种编写接口的规范和建议,但这些不是一成不变的,在具体的项目,还需要根据业务和项目需求做出一些让步和改动,灵活运用这些建议,你的接口也可以很优雅。代码就是一行行蓝色的诗,而不是冰冷乏味的英文串

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

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

相关文章

关于discuz论坛网址优化的一些记录(网站地图sitemap提交)

最近网站刚上线&#xff0c;针对SEO做了些操作&#xff0c;为了方便网站网页百度被收录&#xff0c;特此记录下 discuz有免费的sitemap插件可以用&#xff0c;打开后台管理&#xff0c;找到插件栏&#xff0c;然后找到更多插件&#xff0c;进入插件市场。 选择这个免费的sitem…

【数据分析面试】34.填充NaN值 (Python:groupby/sort_value/ffill)

题目&#xff1a;填充NaN值 &#xff08;Python) 给定一个包含三列的DataFrame&#xff1a;client_id、ranking、value 编写一个函数&#xff0c;将value列中的NaN值用相同client_id的前一个非NaN值填充&#xff0c;按升序排列。 如果不存在前一个client_id&#xff0c;则返…

Linux详解:进程等待

文章目录 进程等待等待的必要性进程等待的方法waitwaitpid获取子进程status阻塞等待 与 非阻塞等待 进程等待 等待的必要性 子进程退出&#xff0c;父进程不进行回收的话&#xff0c;就可能造成僵尸进程&#xff0c;进而造成内存泄露 如果进程进入了僵尸状态&#xff0c;kill…

Tcp自连接

Tcp自连接 如果客户端和服务端都在同一个环境&#xff0c;并且客户端先于服务端启动&#xff0c;那么很有可能产生自连接的现象。 所谓自连接&#xff0c;就是tcp两端使用了同一个端口进行连接&#xff0c;即localhost:port->localhost:port。 实现自连接 下面提供一个例…

GITEE 基于OAuth2的API V5版本

为了构建更好的码云生态环境&#xff0c;我们推出了基于OAuth2的API V5版本。 API V5接口使用方式以及Url都参照GitHub&#xff0c;为了各位开发者更好的兼容已经存在的第三方应用。 API 使用条款 OSCHINA 用户是资源的拥有者&#xff0c;需尊重和保护用户的权益。不能在应用…

4.29 IO多路复用

管道&#xff0c;就是用于进程之间的通信文件&#xff0c;根本不会用到磁盘内容&#xff0c;只是用来标记一块缓冲区&#xff0c;所以无论任何时候大小都是0。 管道必须要同时打开&#xff0c;只开一端是不行的&#xff0c;这样的话不能进行后续的操作&#xff0c;会卡在那里&…

基于SpringBoot+Vue高校竞赛管理系统的设计与实现

项目介绍&#xff1a; 高校竞赛管理系统管理系统按照操作主体分为管理员和用户。管理员的功能包括字典管理、论坛管理、竞赛公告管理、获奖管理、老师管理、评审管理、评审分配管理、评审打分管理、赛事管理、赛事提交管理、赛事报名管理、用户管理、专家管理、管理员管理。用…

如何安装最新版Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 Compose&#xff0c;您可以使用 YAML 文件来配置应用服务&#xff0c;然后只需一个简单的命令便能创建和启动所有服务。在本篇博客中&#xff0c;我们将详细介绍如何在 Linux 系统上安装 Docker Compos…

修改ETCD返回数据限额

问题 通过 get_prefix, get_range 等ETCD 接口查询大量数据时&#xff0c;报数据大小超过限额。 grpc_message:“Received message larger than max (5834875 vs. 4194304)” 原因 ETCD默认设置了4MB数据限额&#xff0c;如果返回的数据超过限额则会报错。 解决方法 解决方…

可以向同事炫耀的10个Python技巧

Python 是一种用途极为广泛的编程语言&#xff0c;有大量的库和框架为其提供支持。然而&#xff0c;在庞大的 Python 生态系统中&#xff0c;还存在一些鲜为人知的编码技巧和库&#xff0c;它们可以显著增强您的开发体验并优化您的代码。我们将探讨一些鲜为人知的 Python 技巧&…

0071__waitwaitpid函数详解

&#xff08;4&#xff09;wait&&waitpid函数详解_c语言 waitpid-CSDN博客

W801学习笔记十六:掌机系统——启动第一个应用

在开始游戏应用开发之前&#xff0c;我们先搞一个简单的应用&#xff0c;目的是把菜单操作与应用启动之间打磨平顺。 这里&#xff0c;我们做一个关于About页面即可。 1、菜单项JSON的定义&#xff1a; [{"t": "关于","i": "menu/test16…

与Apollo共创生态:七周年大会深有体会!

前言 百度从2013年开始涉足自动驾驶领域。2017年3月1日&#xff0c;百度通过内部邮件宣布&#xff0c;将现有业务和资源整合&#xff0c;成立智能驾驶事业群组&#xff08;简称IDG&#xff09;。同年&#xff0c;在上海车展上&#xff0c;百度发布了“Apollo计划”&#xff0c…

Git:克隆代码,提交流程,分支提交流程

1.克隆代码 git clone http://…(代码地址&#xff09; 克隆代码到本地 2.提交流程&#xff08;不牵涉分支&#xff09; 1&#xff09;git add . 将本地修改的文件暂存到缓存区 2&#xff09;git commit -m "当次提交解释说明备注" 在日志中显示 3&#xff09;git…

0426GoodsBiddingAJAX项目

0426GoodsBiddingAJAX项目包-CSDN博客 数据库字段 ​ 管理员的登录界面 ​ 登录成功跳转在线拍卖界面&#xff0c;使用监听器拦截请求&#xff0c;只能登录管理员后访问该界面 ​ 商品竞拍列表 ​ 商品竞拍列表的竞拍操作&#xff1a; ​ 1 用户未登录跳转用户登录界面&#x…

面向对象编程三大特征:封装、继承、多态

封装、继承、多态 1. 封装 1.1 介绍 封装(encapsulation)就是把抽象出的数据 [属性] 和对数据的操作 [方法] 封装在一起,数据被保护在内部,程序的其它部分只有通过被授权的操作 [方法] ,才能对数据进行操作。 1.2 封装的理解和好处 1) 隐藏实现细节:方法(连接数据库)<…

STM32CubeMX+MDK通过I2S接口进行音频输入输出(全双工读写一个DMA回调)续-音质问题解决总结

一、前言 之前进行了STM32CubeMXMDK通过I2S接口进行音频输入输出&#xff08;全双工读写一个DMA回调&#xff09;的研究总结&#xff1a; https://juejin.cn/post/7339016190612881408#heading-34 后续音质问题解决了&#xff0c;目前测试下来48khz的双声道使用效果很好&…

JSON.toJSONString() 输出 “$ref“:“$[0]“问题解决及原因分析

一、背景 在构建一个公共的批处理方法类的时候&#xff0c;在测试输出的时候&#xff0c;打印了" r e f " : " ref":" ref":"[0][0]"的内容&#xff0c;这让我比较疑惑。不由得继续了下去… 二、问题分析 首先&#xff0c;我们需要…

安卓开发Webview RTC 适配

一、场景 在混合开发方式中&#xff0c;项目前端使用了tracking.js 开发了一个人脸识别功能&#xff0c;但是在安卓端无法成功调用摄像头进行视频捕获&#xff0c;在浏览器中可以正常使用该功能。 二、问题分析 之前的音视频文件适配提供给前端的方式&#xff0c;都是通过inp…

@Injectable()

当你在 Nest.js 中使用 Injectable() 装饰器标记一个类时&#xff0c;它告诉 Nest.js 这个类是一个可以被注入到其他地方使用的服务。这意味着你可以在你的应用中的不同地方重复使用这个服务&#xff0c;而不必每次都手动创建它的实例。 比如说&#xff0c;假设你有一个服务叫…