在Spring Boot项目中使用统一返回结果

news/2024/4/25 0:02:40/文章来源:https://blog.csdn.net/pikcacho_pkq/article/details/127354734

在一个完整的项目中,如果每一个控制器的方法都返回不同的结果,那么对项目的维护和扩展都会很麻烦;并且现在主流的开发模式时前后端分离的模式,如果后端返回各式各样的结果,那么在前后端联调时会非常的麻烦,还会增加前后端的格外任务。
所以,在一个项目中统一返回结果就是一个十分必要和友好的做法。接下来就用一个简单的demo来看看统一返回结果的效果。

1.创建Spring Boot项目

这里比较简单,就不详细介绍了;将多余的文件删除,保持项目的整洁;引入必要的依赖。
demo的项目结构
在这里插入图片描述

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency>

2.返回结果的封装

在common包下创建Result结果类,将需要返回的必要数据封装在Result结果类中;这里封装三个属性,第一个是返回的状态码,第二个是返回的描述信息,第三个是返回的数据,此数据是前端需要接收展示的数据。

Result.java

@Setter
@Getter
@ToString
public class Result<T> implements Serializable {private static final long serialVersionUID = 1L;private int resultCode;private String message;private T data;public Result(){}public Result(int resultCode, String message){this.resultCode = resultCode;this.message = message;}// 服务器处理失败public Result failure(){return new Result(Constants.RESULT_CODE_SERVER_ERROR, "服务器错误");}}

创建Constants类,规定基本的状态码所代表的含义;这些状态码的基本规定需要符合常见的状态码含义,并且在一个项目能够保证统一即可。
Constants.java

public class Constants {public static final int RESULT_CODE_SUCCESS = 200;  // 成功处理请求public static final int RESULT_CODE_BAD_REQUEST = 412;  // 请求错误public static final int RESULT_CODE_NOT_LOGIN = 402;  // 未登录public static final int RESULT_CODE_PARAM_ERROR = 406;  // 传参错误public static final int RESULT_CODE_SERVER_ERROR= 500;  // 服务器错误// 等等,可以根据场景继续添加
}

最后创建结果类生成器ResultGenerator类,用于生成结果类。
ResultGenerator.java

public class ResultGenerator {private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";private static final String DEFAULT_FAIL_MESSAGE = "FAIL";public static Result genSuccessResult(){Result result = new Result();result.setResultCode(Constants.RESULT_CODE_SUCCESS);result.setMessage(DEFAULT_FAIL_MESSAGE);return result;}public static Result genSuccessResult(String message){Result result = new Result();result.setResultCode(Constants.RESULT_CODE_SUCCESS);result.setMessage(message);return result;}public static Result genSuccessResult(Object data){Result result = new Result();result.setResultCode(Constants.RESULT_CODE_SUCCESS);result.setMessage(DEFAULT_SUCCESS_MESSAGE);result.setData(data);return result;}public static Result genFailResult(String message){Result result = new Result();result.setResultCode(Constants.RESULT_CODE_SERVER_ERROR);if(StringUtils.isEmpty(message)){result.setMessage(DEFAULT_FAIL_MESSAGE);}else{result.setMessage(message);}return result;}public static Result genNullResult(String message){Result result = new Result();result.setResultCode(Constants.RESULT_CODE_BAD_REQUEST);result.setMessage(message);return result;}public static Result genErrorResult(int code, String message){Result result = new Result();result.setResultCode(code);result.setMessage(message);return result;}
}

3.后端接口实现

这里实现简单的增删改查,并且应用统一返回结果。

3.1 创建实体类

User.java

@Setter
@Getter
@Generated
@ToString
public class User {private Integer id;private String name;private String password;
}

3.2 创建dao层

UserDao.java

public interface UserDao {/*** 查询所有的用户* @return*/public List<User> findAllUsers();/*** 根据主键查询用户* @param id* @return*/public User getUserById(Integer id);/*** 添加一个用户* @param user* @return*/public int insertUser(User user);/*** 修改一个用户信息* @param user* @return*/public int updateUser(User user);/*** 删除一个用户* @param id* @return*/public int deleteUser(Integer id);}

userDao.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.picacho.dao.UserDao"><resultMap type="com.picacho.entity.User" id="UserResult"><result property="id" column="id"/><result property="name" column="name"/><result property="password" column="password"/></resultMap><select id="findAllUsers" resultMap="UserResult">select id,name,password from tb_userorder by id desc</select><select id="getUserById" resultMap="UserResult">select id,name,password from tb_userwhere id = #{id}</select><insert id="insertUser" parameterType="com.picacho.entity.User">insert into tb_user(name,password)values(#{name},#{password})</insert><update id="updateUser" parameterType="com.picacho.entity.User">update tb_usersetname=#{name},password=#{password}where id=#{id}</update><delete id="deleteUser" parameterType="int">delete from tb_user where id=#{id}</delete></mapper>

3.3 创建Controller层

这里基本没有任何业务逻辑可言,只是单纯的增删改查,所以也就不太需要业务层了。
UserController.java

@Controller
public class UserController {@AutowiredUserDao userDao;/*** 查询所有用户* @return*/@RequestMapping(value = "/users", method = RequestMethod.GET)@ResponseBodypublic Result<List<User>> queryAll(){List<User> users = userDao.findAllUsers();return ResultGenerator.genSuccessResult(users);}/*** 查询一个用户* @param id* @return*/@RequestMapping(value = "/users/{id}", method = RequestMethod.GET)@ResponseBodypublic Result<User> queryOne(@PathVariable("id") Integer id){if(id == null || id < 1){return ResultGenerator.genFailResult("缺少参数");}User user = userDao.getUserById(id);if(user == null){return ResultGenerator.genFailResult("无此数据");}return  ResultGenerator.genSuccessResult(user);}/*** 添加一个用户* @param user* @return*/@RequestMapping(value = "/users", method = RequestMethod.POST)@ResponseBodypublic Result<Boolean> insert(@RequestBody User user){if(StringUtils.isEmpty(user.getName()) || StringUtils.isEmpty(user.getPassword())){return ResultGenerator.genFailResult("缺少参数");}return ResultGenerator.genSuccessResult(userDao.insertUser(user) > 0);}/*** 修改用户信息* @param user* @return*/@RequestMapping(value = "/users", method = RequestMethod.PUT)@ResponseBodypublic Result<Boolean> update(@RequestBody User user){if(user.getId() == null || user.getId() < 1 || StringUtils.isEmpty(user.getName()) || StringUtils.isEmpty(user.getPassword())){return ResultGenerator.genFailResult("缺少参数");}User tempUser = userDao.getUserById(user.getId());if(tempUser == null){return ResultGenerator.genFailResult("参数异常");}tempUser.setName(user.getName());tempUser.setPassword(user.getPassword());return ResultGenerator.genSuccessResult(userDao.updateUser(tempUser) > 0);}/*** 删除一个用户* @param id* @return*/@RequestMapping(value = "/users/{id}", method = RequestMethod.DELETE)@ResponseBodypublic Result<Boolean> delete(@PathVariable("id") Integer id){if(id == null || id < 1){return ResultGenerator.genFailResult("缺少参数");}return ResultGenerator.genSuccessResult(userDao.deleteUser(id) > 0);}}

4.前端部分

这里前端使用ajax来与后端进行交互,所以前端资源只需要引入jquery即可。

<script src="https://cdn.staticfile.org/jquery/1.12.0/jquery.min.js"></script>

user-test.html

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><title>统一返回结果 | 请求测试</title>
</head>
<body class="hold-transition login-page">
<div style="width:720px;margin:7% auto"><div class="content"><div class="container-fluid"><div class="row"><div class="col-lg-6"><hr><div class="card"><div class="card-header"><h5 class="m-0">详情查询接口测试</h5></div><div class="card-body"><input id="queryId" type="number" placeholder="请输入id字段"><h6 class="card-title">查询接口返回数据如下:</h6><p class="card-text" id="result0"></p><a href="#" class="btn btn-primary" onclick="requestQuery()">发送详情查询请求</a></div></div><br><hr><div class="card"><div class="card-header"><h5 class="m-0">列表查询接口测试</h5></div><div class="card-body"><h6 class="card-title">查询接口返回数据如下:</h6><p class="card-text" id="result1"></p><a href="#" class="btn btn-primary" onclick="requestQueryList()">发送列表查询请求</a></div></div><br><hr><div class="card"><div class="card-header"><h5 class="m-0">添加接口测试</h5></div><div class="card-body"><input id="addName" type="text" placeholder="请输入name字段"><input id="addPassword" type="text" placeholder="请输入password字段"><h6 class="card-title">添加接口返回数据如下:</h6><p class="card-text" id="result2"></p><a href="#" class="btn btn-primary" onclick="requestAdd()">发送添加请求</a></div></div><br><hr><div class="card"><div class="card-header"><h5 class="m-0">修改接口测试</h5></div><div class="card-body"><input id="updateId" type="number" placeholder="请输入id字段"><input id="updateName" type="text" placeholder="请输入name字段"><input id="updatePassword" type="text" placeholder="请输入password字段"><h6 class="card-title">修改接口返回数据如下:</h6><p class="card-text" id="result3"></p><a href="#" class="btn btn-primary" onclick="requestUpdate()">发送修改请求</a></div></div><br><hr><div class="card"><div class="card-header"><h5 class="m-0">删除接口测试</h5></div><div class="card-body"><input id="deleteId" type="number" placeholder="请输入id字段"><h6 class="card-title">删除接口返回数据如下:</h6><p class="card-text" id="result4"></p><a href="#" class="btn btn-primary" onclick="requestDelete()">发送删除请求</a></div></div><hr></div></div></div></div>
</div><!-- jQuery -->
<script src="https://cdn.staticfile.org/jquery/1.12.0/jquery.min.js"></script>
<script type="text/javascript">function requestQuery() {var id = $("#queryId").val();if (typeof id == "undefined" || id == null || id == "" || id < 0) {return false;}$.ajax({type: "GET",//方法类型dataType: "json",//预期服务器返回的数据类型url: "/users/" + id,contentType: "application/json; charset=utf-8",success: function (result) {$("#result0").html(JSON.stringify(result));},error: function () {$("#result0").html("接口异常,请联系管理员!");}});}function requestQueryList() {$.ajax({type: "GET",//方法类型dataType: "json",//预期服务器返回的数据类型url: "/users",contentType: "application/json; charset=utf-8",success: function (result) {$("#result1").html(JSON.stringify(result));},error: function () {$("#result1").html("接口异常,请联系管理员!");}});}function requestAdd() {var name = $("#addName").val();var password = $("#addPassword").val();var data = {"name": name, "password": password}$.ajax({type: "POST",//方法类型dataType: "json",//预期服务器返回的数据类型url: "/users",contentType: "application/json; charset=utf-8",data: JSON.stringify(data),success: function (result) {$("#result2").html(JSON.stringify(result));},error: function () {$("#result2").html("接口异常,请联系管理员!");}});}function requestUpdate() {var id = $("#updateId").val();var name = $("#updateName").val();var password = $("#updatePassword").val();var data = {"id": id, "name": name, "password": password}$.ajax({type: "PUT",//方法类型dataType: "json",//预期服务器返回的数据类型url: "/users",contentType: "application/json; charset=utf-8",data: JSON.stringify(data),success: function (result) {$("#result3").html(JSON.stringify(result));},error: function () {$("#result3").html("接口异常,请联系管理员!");}});}function requestDelete() {var id = $("#deleteId").val();if (typeof id == "undefined" || id == null || id == "" || id < 0) {return false;}$.ajax({type: "DELETE",//方法类型dataType: "json",//预期服务器返回的数据类型url: "/users/" + id,contentType: "application/json; charset=utf-8",success: function (result) {$("#result4").html(JSON.stringify(result));},error: function () {$("#result4").html("接口异常,请联系管理员!");}});}
</script>
</body>
</html>

5.验证

验证添加效果
在这里插入图片描述
验证查询

在这里插入图片描述
验证查询多个用户
在这里插入图片描述
修改用户
在这里插入图片描述
删除用户
在这里插入图片描述
测试也基本成功了,这样统一的返回结果在前端接收处理数据时,会十分具有优势,所以在完整的项目中也都是采用这种方案,到这里这个demo也就基本结束了。

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

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

相关文章

多线程-线程安全前篇

线程安全如果有多个线程在同时运行 而这些线程可能会同时运行这段代码 程序每次运行结果和单线程运行的结果是一样的 而且其他的变量的值也和预期的是一样的 就像线程安全的 演示线程的安全问题: 电影院要买票 我们模拟电影院的卖票过程 本次电影的座位共100个(背场电影只能卖…

Clickhouse 基础架构

ClickHouse 基础架构 我们从两块来看ClickHouse的基础架构 ClickHouse集群结构ClickHouse 内部结构1. ClickHouse集群结构 ClickHouse 采用了 Multi Master 多主架构,集群中的每个节点角色对等,客户端访问任意一个节点都能得到相同的效果。 多主架构中每个节点对等的角色使…

CSS学习笔记:背景图片样式

CSS 背景属性用于定义HTML元素的背景。 CSS 属性定义背景效果: 关于背景图片&#xff0c;块元素和行内元素都可以设置背景图片。 但是块元素有宽度和高度&#xff0c;设置之后&#xff0c;图片图片默认往宽和高方向上平铺&#xff0c;对于行内元素&#xff0c;它没有宽度和高…

零售信贷产品的8大业务流程

简单来说&#xff0c;零售信贷业务流程是指做事的方法和步骤&#xff0c;是一个降低成本、规避风险、获取效益&#xff0c;以确保信贷资金的安全性、流动性、盈利性的过程。关注“金科应用研院”&#xff0c;回复“CSDN”领取风控资料合集 通过既定的操作程序&#xff0c;每个…

【第一弹】Python题库刷题---完事开头难,从基础题开始

您好&#xff0c;我是码农飞哥&#xff08;wei158556&#xff09;&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f4aa;&#x1f3fb; 1. Python基础专栏&#xff0c;基础知识一网打尽&#xff0c;9.9元买不了吃亏&#xff0c;买不了上当。 Python从入门到精…

做Web自动化前,你必须掌握的几个技能

每天进步一点点,关注我们哦,每天分享测试技术文章 本文章出自【码同学软件测试】 码同学公众号:自动化软件测试,领取资料可加:magetest 码同学抖音号:小码哥聊软件测试 学习web自动化的前提条件:手工测试(了解各种测试的知识)、学习编程语言、学习Web基础、学习自动化…

sklearn里的逻辑回归,随机森林及SVM应用于指数方向”预测“

原创文章第76篇&#xff0c;专注“个人成长与财富自由、世界运作的逻辑&#xff0c; AI量化投资”。 backtrader代表传统量化&#xff0c;而qlib代表AI量化&#xff0c;二者的范式不同。 backtrader擅长规则驱动&#xff0c;更像是传统技术分析的“自动化”版本&#xff0c;当…

【附源码】计算机毕业设计SSM民宿网站管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

docsify search插件对多个md文件建索引查找

docsify search插件对多个md文件建索引查找 如果配置了不管用,那应该是浏览器缓存的问题,换个浏览器访问试试看 index.html中配置paths 对应路径即可 官网示例如下图: 附上完整index.html配置 <!DOCTYPE html> <html lang"en"> <head><m…

MySQL—表的增删改查

MySQL—表的增删改查一、Create1.1、单行数据 全列插入1.2、多行数据 指定列插入1.3、插入否则更新1.4 替换二、Retrieve2.1、全列查询2.2、指定列查询2.3、查询字段为表达式2.4、为查询结果指定别名2.5 结果去重2.6 WHERE 条件>, >, <, <,2.7、结果排序2.8、筛选…

分布式锁(Distributed Lock)理论介绍

在多线程环境中&#xff0c;线程之间通常使用互斥锁实现共享资源的独占访问。在多进程环境&#xff0c;特别是分布式环境&#xff0c;常使用分布式锁来实现共享资源的独占访问。简单来说&#xff0c;分布式锁就是指在分布式环境下&#xff0c;通过加解锁实现多节点对共享资源的…

Day2: 正原电子 imx交叉编译环境搭建

imx交叉编译环境搭建 资源下载 https://atk-imx6ull.coding.net/public/imx6ull/05_Tools/git/files/master/01%E3%80%81%E4%BA%A4%E5%8F%89%E7%BC%96%E8%AF%91%E5%99%A8 正点原子提供两种交叉编译工具链。这两种交叉编译工具链解释如下图。 第一种 Poky 编译器是Yocto 项…

Entity Framework教程-Entity Framework-模型关系(Model Relationships)

更新记录 转载请注明出处: 2022年10月17日 发布。 2022年10月10日 从笔记迁移到博客。配置实体关系的方式 使用数据特性 使用FluentAPI关系配置 使用关系属性 导航属性(navigation property) 导航属性说明 一个类型为主体实体或从属实体的属性 无论它是指它的父实体还是持有…

Spring源码分析(八)依赖注入源码解析1:autowire自动注入 和 @Autowired注入

Spring中到底有几种依赖注入的方式&#xff1f; 首先分两种&#xff1a; 手动注入自动注入 手动注入 在XML中定义Bean时&#xff0c;就是手动注入&#xff0c;因为是程序员手动给某个属性指定了值。 <bean name"userService" class"com.luban.service.U…

谷粒商城项目学-分布式基础

项目框架图 分布式基础概念 • 微服务、注册中心、配置中心、远程调用、Feign、网关 • 2、基础开发 • SpringBoot2.0、SpringCloud、Mybatis-Plus、Vue组件化、阿里云对象存储 • 3、环境 • Vagrant、Linux、Docker、MySQL、Redis、逆向工程&人人开源 • 4、开发规范 •…

【LeetCode48:旋转图像(附Java代码)】

旋转图像一、题目描述1.题目内容2.样例二、解决方案1.算法流程1&#xff09;分析2&#xff09;算法流程2.Java代码1&#xff09;核心代码2&#xff09;完整测试代码一、题目描述 1.题目内容 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必…

metamask api 请求 一般操作

参考文档&#xff1a;https://docs.metamask.io/guide/ 注意 metamask 必须是运行在站点之下的 web 页进行操作。 一、检查 metamask 是否安装 metamask 提供了 window.ethereum 供开发者对 metamask&#xff08;以太坊网络&#xff09; 进行交互&#xff0c;当然是需要你已…

DO、VO、BO、DTO、POJO

DO:Domain Object 即数据库表字段 在Java中一一对应关系(有人称它实体类) BO:Business Object 即业务对象,Service层向上传传输的对象。是多个DO的组合形式 VO:view oject 展示层对象,通过接口向前端输出展示的对象 DTO:Date Transfer Object 数据传输对象,controll…

《Linux下软件的管理》

【一】Linux软件包yum 什么是软件包&#xff1f; 在Linux下安装软件&#xff0c;一个通常的办法就是下载程序的源代码&#xff0c;并经行编译&#xff0c;既可得到可执行程序&#xff0c;但是这种办法属实是太麻烦了&#xff0c;因为下载要时间&#xff0c;编译要时间&#x…

根文件系统简介

根文件系统 根文件系统一般也叫做rootfs&#xff0c;那么什么叫根文件系统&#xff1f;看到“文件系统”这四个字&#xff0c;很多人&#xff0c;第一反应就是FATFS、FAT、EXT4、YAFFS和NTFS等这样的文件系统。在这里&#xff0c;根文件系统并不是FATFS这样的文件系统代码&…