Java项目常用的统一返回跟统一异常处理
先创建一个crud的项目。
controller调用service调用mapper
以下以简单代码代替
- controller
@GetMapping("/getUserById")
public String getUserById(String id){
String userById = userService.getUserById(id);
return userById;
}
- service
@Override
public String getUserById(String id) {
// 模拟业务
User user = userMapper.selectById(id);
return user.toString();
}
上面代码虽然是把数据返回给前台了,但是没有处理异常以及没有一个明确的标识告诉前端我是成功还是失败了,此时我们需要封装一下统一的成功失败标志来告诉前台如何处理返回数据。
使用Lombok 简单封装了一个CommonResponse类(lombok的使用需要考虑项目是否真正适合lombok,不要因为方便引入导致后期版本或者一些其他的隐藏坑。)
@Data
public class CommonResponse {
/**
* 返回业务码用来判断成功失败
* 200 成功
* 500 失败
*/
private String code;
/** 描述 */
private String massage;
/** 描述 */
private Object date;
public CommonResponse(String code, String massage, Object date) {
this.code = code;
this.massage = massage;
this.date = date;
}
public static CommonResponse succeed(){
return getCommonResponse(CodeEnum.SUCCESS.getCode(), CodeEnum.SUCCESS.getMassage(), null);
}
public static CommonResponse succeed(Object date){
return getCommonResponse(CodeEnum.SUCCESS.getCode(), CodeEnum.SUCCESS.getMassage(), date);
}
public static CommonResponse succeed(String massage,Object date){
return getCommonResponse(CodeEnum.SUCCESS.getCode(), massage, date);
}
public static CommonResponse error(String massage){
return getCommonResponse(CodeEnum.ERROR.getCode(), massage, null);
}
public static CommonResponse error(String code,String massage){
return getCommonResponse(code, massage, null);
}
public static CommonResponse error(){
return getCommonResponse(CodeEnum.ERROR.getCode(), CodeEnum.ERROR.getMassage(), null);
}
public static CommonResponse getCommonResponse(String code, String massage, Object date){
return new CommonResponse(code,massage,date);
}
}
返回的controller使用统一的CommonResponse
@GetMapping("/getUserById")
public CommonResponse getUserById(String id){
String userById = userService.getUserById(id);
return CommonResponse.succeed(userById);
}
返回
{
"code": "200",
"massage": "成功",
"date": "User(id=1, username=嘉文00, password=1000000, age=5555)"
}
上述返回基本符合预期,但是当程序出现未知异常怎么办了。
对service改造下
@Override
public String getUserByIdException(String id) {
User user = userMapper.selectById(id);
// 模拟业务异常
int i=5/0;
return user.toString();
}
controller 改造
@GetMapping("/getUserById")
public CommonResponse getUserById(String id){
try{
String userById = userService.getUserById(id);
return CommonResponse.succeed(userById);
}catch(Exception e){
e.printStackTrace();
log.error(e.getMessage());
return CommonResponse.error(e.getMessage());
}
}
上面是不是也可以,通过trycatch来判断如何返回。但是这样代码中就会出现大量的try catch,是不是很不好看,我们能不能添加一个统一的try呢,答案是可以的。
使用spring提供的统一的异常处理
spring 提供了三种异常捕获方式,个人比较推荐这一种
@Slf4j
@ControllerAdvice
public class ExceptionHandle {
/**
* 处理未知异常
* @param e
* @return
*/
@ExceptionHandler(Exception.class)
@ResponseBody
public CommonResponse handleException(Exception e){
log.error("系统异常:{}",e.getMessage());
return CommonResponse.error(e.getMessage());
}
/**
* 处理主动抛出的自定义异常
* @param e
* @return
*/
@ExceptionHandler(BusinessException.class)
@ResponseBody
public CommonResponse handleBusinessException(BusinessException e){
log.error("自定义异常:{}",e.getErrMassage());
return CommonResponse.error(e.getErrCode(),e.getErrMassage());
}
}
踩过的坑:
- 这个地方在写的时候遇到一个坑,因为捕获异常后的返回值是CommonResponse,所以要加上注解 @ResponseBody 便于 格式转换。
- 在配置@ExceptionHandler的时候不能配置两个相同的Exception。否则会不知道使用哪个而报错。
这时controller 已经很清晰了,如下:只用处理好业务调用,无需处理向上抛出的异常。
@GetMapping("/getUserByIdException")
public CommonResponse getUserByIdException(String id){
String userById = userService.getUserByIdException(id);
return CommonResponse.succeed(userById);
}
@GetMapping("/getUserByIdBusinessException")
public CommonResponse getUserByIdBusinessException(String id){
String userById = userService.getUserByIdBusinessException(id);
return CommonResponse.succeed(userById);
}
当然有时候我们会遇到自己的校验不通过来终止程序。我们可以throw 一个Exception 或者我们需要定制返回码,自定义一个异常类也行。如下简单示例,大家可以根据自己的业务需求去自定义。
- 自定义异常类BusinessException
@Data
public class BusinessException extends RuntimeException{
private static final long serialVersionUID = 918204099850898995L;
private String errCode;
private String errMassage;
public BusinessException(String errCode,String errMassage){
super(errMassage);
this.errCode = errCode;
this.errMassage = errMassage;
}
}
- service返回自定义异常
@Override
public String getUserByIdBusinessException(String id) {
User user = userMapper.selectById(id);
// 模拟业务异常
if("1".equals(id)){
throw new BusinessException("400","id为1的数据不支持查询。");
}
return user.toString();
}
此时我们前端得到的返回
## 请求
http://localhost:8088/getUserByIdBusinessException?id=1
## 返回
{
"code": "400",
"massage": "id为1的数据不支持查询。",
"date": null
}
以上就是统一异常捕获跟统一的返回。
另外我们实际项目为了使业务异常好看,统一,我们可以定义一个枚举来存放我们的业务异常信息。
- 定义一个枚举类
public enum ExceptionEnum {
BUSINESS_NOT_ONE("400","id为1的数据不支持查询"),
ERR_NOT_LOOK("401","长得太帅不让看")
// 往后面累加...
;
private String code;
private String desc;
ExceptionEnum(String code, String desc) {
this.code = code;
this.desc = desc;
}
public void ThrowException(){
ThrowException(code,desc);
}
public void ThrowException(String errMassage){
errMassage = desc +":"+errMassage;
ThrowException(code,errMassage);
}
private BusinessException ThrowException(String code,String desc){
throw new BusinessException(code,desc);
}
}
- 在service 中抛出枚举异常
@Override
public String getUserByIdBusinessExceptionByEnumOne(String id) {
User user = userMapper.selectById(id);
// 模拟业务异常
if("1".equals(id)){
ExceptionEnum.BUSINESS_NOT_ONE.ThrowException();
}
return user.toString();
}
@Override
public String getUserByIdBusinessExceptionByEnumTwo(String id) {
User user = userMapper.selectById(id);
// 模拟业务异常
if("look".equals(id)){
// 可以动态拼接异常信息
ExceptionEnum.ERR_NOT_LOOK.ThrowException("你说对吧"+id);
}
return user.toString();
}
- 前台返回
{
"code": "400",
"massage": "id为1的数据不支持查询",
"date": null
}
{
"code": "401",
"massage": "长得太帅不让看:你说对吧look",
"date": null
}
这种做法的好处就是方便管理,一眼就知道自己项目中有多少错误,多少异常。但是也会有同学觉得这样写好费劲,每次抛异常的时候还要先在枚举类中定义。所以这个做法是项目跟成员而定。
以上是本人拙见,若有不合适之处,欢迎留言指正。
从项目中来到项目中去
Java项目常用的统一返回跟统一异常处理的更多相关文章
- java项目常用 BaseDao BaseService
java项目常用 BaseDao BaseService IBaseDao 1 package com.glht.sim.dao; 2 3 import java.util.List; 4 5 6 ...
- Java基础学习总结(70)——开发Java项目常用的工具汇总
要想全面了解java开发工具,我们首先需要先了解一下java程序的开发过程,通过这个过程我们能够了解到java开发都需要用到那些工具. 首先我们先了解完整项目开发过程,如图所示: 从上图中我们能看到一 ...
- Spring Boot 统一返回结果及异常处理
在 Spring Boot 构建电商基础秒杀项目 (三) 通用的返回对象 & 异常处理 基础上优化.调整 一.通用类 1.1 通用的返回对象 public class CommonReturn ...
- java项目常用架构
三层架构 : 界面层/表现层 UI 业务逻辑层 BLL 针对具体的问题的操作,也可以理解成对数据层的操作,对数据业务逻辑处理. 数据访问层 DAL 访问数据库 mvc : 而 MVC 是在三层架构的基 ...
- JAVA项目常用异常处理情况
Java异常处理 网络整理 这里是异常的说明: 算术异常类:ArithmeticExecption 空指针异常类:NullPointerException 类型强制转换异常:ClassCastExce ...
- Java 项目创建 -- 统一结果处理、统一异常处理、统一日志处理
一.IDEA 插件使用 1.说明 此处使用 SpringBoot 2.2.6 .JDK 1.8 .mysql 8.0.18 作为演示. 使用 IDEA 作为开发工具. 2.IDEA 插件 -- Lom ...
- [原创]Java项目统一UTC时间方案
Java项目统一UTC时间方案 作者:Gods_巨蚁 引言 近期团队的个别项目在进行框架升级后,部分时间值存在8小时误差,原因是错误的将数据库中的时间数据理解成了UTC时间(旧版本认为是北京时间) 考 ...
- java统一返回标准类型
一.前言.背景 在如今前后端分离的时代,后端已经由传统的返回view视图转变为返回json数据,此json数据可能包括返回状态.数据.信息等......因为程序猿的习惯不同所以返回json数据的格式也 ...
- Java封装接口统一返回数据模板
现在大多数都使用前后端分离开发模式,前端通过Ajax请求访问后台服务器,后台返回JSON数据供前端操作,这里编写一个统一返回数据模板类,方便日后操作 public class R extends Ha ...
随机推荐
- Sqli-Labs less8-10
less-8 前置基础知识: 前几关我们用到了布尔盲注的办法,还有一种盲注就是时间盲注,不仅可以用于有回显的盲注,还能用于没有回显的盲注 函数:sleep(1):等待1秒之后再返回页面做出反应 IF( ...
- 公司新来了一个质量工程师,说团队要保证 0 error,0 warning
摘要:静态代码检查又称为静态程序分析,是指在不运行计算机程序的条件下,进行程序分析的方法. 本文分享自华为云社区<公司新来了一个质量工程师,说团队要保证 0 error,0 warning> ...
- 从350ms到80ms,揭秘阿里工程师 iOS 短视频优化方案
内容作为 App 产品新的促活点,受到了越来越多的重视与投入,短视频则是增加用户粘性.增加用户停留时长的一把利器.短视频的内容与体验直接关系到用户是否愿意长时停留,盒马也提出全链路内容视频化的规划,以 ...
- C# ThreadLocal源码追踪
ThreadLocal 字段成员: private Func<T>? _valueFactory; 一个获取默认值的委托 不同线程共享此成员. [ThreadStatic] private ...
- offsetof宏---个人笔记
标准库里面提供的offsetof(t,m)宏,用来计算两个变量在内存中的地址偏移量 #include <stdio.h>//原型: #define offsetof(TYPE, MEMBE ...
- 利用Python快速绘制海报级别地图
1 简介 基于Python中诸如matplotlib等功能丰富.自由度极高的绘图库,我们可以完成各种极富艺术感的可视化作品,关于这一点我在系列文章在模仿中精进数据可视化中已经带大家学习过很多案例了. ...
- 每天迁移MySQL历史数据到历史库Python脚本
#!/usr/bin/env python # coding:utf-8 #__author__ = 'Logan' import MySQLdb import sys import dat ...
- Mysql索引最佳实践笔记0524
#mysql5.7 innodb默认存储引擎 一.关于索引二.最佳实践三.避坑实践 一.关于索引 1.索引的作用 -提高查询效率 -数据分组.排序 -避免回表查询 -优化聚集查询 -用于多表join关 ...
- vue 引入 echarts 图表 并且展示柱状图
npm i echarts -S 下载 echarts 图表 mian.js 文件 引入图表并且全局挂载 //echarts 图表 import echarts from 'echarts' Vue. ...
- OpenCV 之 透视 n 点问题
透视 n 点问题,源自相机标定,是计算机视觉的经典问题,广泛应用在机器人定位.SLAM.AR/VR.摄影测量等领域 1 PnP 问题 1.1 定义 已知:相机的内参和畸变系数:世界坐标系中,n 个 ...