# springboot_exception_handle_data **Repository Path**: CYSpringBoot/springboot_exception_handle_data ## Basic Information - **Project Name**: springboot_exception_handle_data - **Description**: 使用异常处理服务器返回数据 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2019-07-02 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # springboot_exception_handle_data ### 介绍 > 使用统一异常,处理服务器返回给客户端数据 ### 服务器数据格式 > 通过 [springboot_jpa](https://gitee.com/CYSpringBoot/springboot_jpa.git) 提供的接口数据可以看出,返回数据格式不统一,这样客户端处理起来会比较麻烦。 > 通常服务器会制定统数据格式返回到客户端 ```json { // 状态码 "code": 0, // 状态信息 "msg": "成功", // 返回数据 "data": null } ``` ### 创建响应数据格式 ```java package com.lcy.exceptionhandledata.Exception; // 使用泛型T,因为每个接口但会的data可能不同 public class ResultData { // 状态码 private Integer code; // 状态码对应的状态信息 private String msg; // 数据 private T data; public Integer getCode() { return code; } public void setCode(Integer code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public T getData() { return data; } public void setData(T data) { this.data = data; } } ``` ### 创建状态码和状态信息关联的枚举 > 使用枚举,可以更好体现状态码和状态信息对应关系 ```java package com.lcy.exceptionhandledata.Enum; public enum ResultEnum { SUCCESS(0,"操作成功"), FAILURE(10000,"操作失败"), INSERT_USERINFO_FAILURE(10001,"插入用户信息失败"), UPDATE_USERINFO_FAILURE(10002, "更新用户信息失败"), USER_NOT_EXISTS(10003, "用户不存在"), ; // 状态码 private Integer code; // 状态码对应的状态信息 private String msg; ResultEnum(Integer code, String msg) { this.code = code; this.msg = msg; } public Integer getCode() { return code; } public String getMsg() { return msg; } } ``` ### 创建异常处理类 ```java package com.lcy.exceptionhandledata.Exception; import com.lcy.exceptionhandledata.Enum.ResultEnum; public class DataException extends RuntimeException { // 状态码 private Integer code; public DataException(ResultEnum resultEnum) { // 把状态信息传递给父类RuntimeException处理 super(resultEnum.getMsg()); // 保存状态码 this.code = resultEnum.getCode(); } public Integer getCode() { return code; } } ``` ### 使用@ControllerAdvice统一处理异常 ```java package com.lcy.exceptionhandledata.Exception; import com.lcy.exceptionhandledata.Utils.ResultUtils; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; // 配置统一异常处理,之所有的Controller跑出的异常都会通过DataExceptionHandle处理,也可以制定Controller @ControllerAdvice public class DataExceptionHandle { // 处理接收异常类 @ExceptionHandler(value = Exception.class) // 返回数据为JSON, 如果做Web前端展示,可以不加@ResponseBody @ResponseBody private ResultData handleDataException(Exception e) { ResultData resultData = new ResultData(); if (e instanceof DataException) { DataException dataException = (DataException) e; resultData.setCode(code); resultData.setMsg(message); } else { resultData.setCode(-1); resultData.setMsg("未知错误"); } return resultData; } } 注意: 可以看出,我们在使用ResultData时, 每次都要创建对象,不方便使用 ``` ### 封装ResultData工具类 ```java package com.lcy.exceptionhandledata.Utils; import com.lcy.exceptionhandledata.Enum.ResultEnum; import com.lcy.exceptionhandledata.Exception.ResultData; // 工具类, 更方便得到ResultData对象 public class ResultUtils { // 操作成功数据处理 public static ResultData success(Object object) { ResultData resultData = new ResultData(); resultData.setCode(ResultEnum.SUCCESS.getCode()); resultData.setMsg(ResultEnum.SUCCESS.getMsg()); resultData.setData(object); return resultData; } // 处理操作成功但是数据为null public static ResultData success() { return success(null); } // 处理错误信息 public static ResultData error(Integer code, String message) { ResultData resultData = new ResultData(); resultData.setCode(code); resultData.setMsg(message); return resultData; } } 这样统一异常中的代码可以修改为如下: // 配置统一异常处理 @ControllerAdvice public class DataExceptionHandle { // 处理接收异常类 @ExceptionHandler(value = Exception.class) @ResponseBody private ResultData handleDataException(Exception e) { if (e instanceof DataException) { DataException dataException = (DataException) e; return ResultUtils.error(dataException.getCode(), dataException.getMessage()); } else { // 处理其他异常 return ResultUtils.error(-1,"未知错误"); } } } ``` ### 优化UserController中的代码 ```java package com.lcy.exceptionhandledata.Controller; import com.lcy.exceptionhandledata.Dao.UserDao; import com.lcy.exceptionhandledata.Entity.User; import com.lcy.exceptionhandledata.Enum.ResultEnum; import com.lcy.exceptionhandledata.Exception.DataException; import com.lcy.exceptionhandledata.Exception.ResultData; import com.lcy.exceptionhandledata.Utils.ResultUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; import java.util.Optional; @RestController public class UserController { @Autowired private UserDao userDao; // 添加用户信息 // @PostMapping POST请求 // @RequestBody 说明参数是JSON数据 @PostMapping(value = "/addUser") public ResultData addUser(@RequestBody User user){ User insertUser = userDao.save(user); if (insertUser != null) { return ResultUtils.success(); } throw new DataException(ResultEnum.INSERT_USERINFO_FAILURE); } // 根据用户ID设置用户数据 @PostMapping(value = "/updateUser") public ResultData updateUser(Integer userId, @RequestBody User user){ // 通过jpa提供的接口方法,获取用户信息 Optional userOptional = userDao.findById(userId); if (userOptional.isPresent()) { // 获取用户信息 User findUser = userOptional.get(); // 获取用户信息成功, 更新用户数据 findUser.setUserName(user.getUserName()); findUser.setUserAge(user.getUserAge()); findUser.setUserPassword(user.getUserPassword()); User updateUser = userDao.save(findUser); if(updateUser != null) { return ResultUtils.success(); } throw new DataException(ResultEnum.UPDATE_USERINFO_FAILURE); } throw new DataException(ResultEnum.USER_NOT_EXISTS); } // 获取所有用户信息 @RequestMapping(value = "/getAllUsers") public ResultData getAllUsers() { // 通过jpa提供的接口方法,获取所有用户信息 List userList = userDao.findAll(); return ResultUtils.success(userList); } // 根据ID获取用户信息 @RequestMapping(value = "/getUserInfoByID") public ResultData getUserInfoByID(Integer userId) { // 通过jpa提供的接口方法,获取用户信息 Optional userOptional = userDao.findById(userId); if (userOptional.isPresent()) { // 获取用户信息 User user = userOptional.get(); return ResultUtils.success(user); } throw new DataException(ResultEnum.USER_NOT_EXISTS); } // 根据userName获取用户信息 @RequestMapping(value = "/getUserInfoByName") public ResultData getUserInfoByName(String userName) { // 通过jpa提供的接口方法,获取用户信息 List userList = userDao.findUserByName(userName); return ResultUtils.success(userList); } // 根据ID删除用户信息 @RequestMapping(value = "/deleteUserByID") public ResultData deleteUserByID(Integer userId) { // 通过jpa提供的接口方法,获取用户信息 userDao.deleteById(userId); return ResultUtils.success(); } } ``` - 这样就可以看到我们所有的接口都统一返回ResultData类型。
> PostMan访问接口 http://localhost:8888/getAllUsers ```json { "code": 0, "msg": "操作成功", "data": [ { "userId": 6, "userName": "lcy", "userPassword": "123456", "userAge": "20" }, { "userId": 7, "userName": "lc4y", "userPassword": "123456", "userAge": "20" }, { "userId": 8, "userName": "lc4y111", "userPassword": "123456", "userAge": "20" }, { "userId": 9, "userName": "lc4y123456", "userPassword": "123456", "userAge": "25" }, { "userId": 10, "userName": "lc4y", "userPassword": "abcdefg", "userAge": "50" } ] } ``` > PostMan访问接口 http://localhost:8888/updateUser?userId=11, userId不存在的 ```json { "code": 10003, "msg": "用户不存在", "data": null } ``` ### 完成 > 待续...