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 ...
随机推荐
- Asp.Net Core 使用 Sqlite 数据库
在Asp.Net Core 使用 Sqlite 数据库 在Asp.Net Core(5.0)项目中使用Sqlite数据库的设置, 1,创建新web项目 2,安装下面的依赖包 Install-Packa ...
- 一个tomcat配置多个不同端口的项目
1.将要同时启动的项目放入不同的webapps文件夹中 2.修改tomcat安装目录下的conf-->setting.xml文件 <?xml version="1.0" ...
- S3C2440—7.存储控制器访问外设
文章目录 一.内存接口的概念 二.存储控制器(内存控制器) 2.1 什么是存储控制器? 2.2 S3C2440存储控制器介绍 2.3 存储控制器如何处理不同位宽的外设 2.4 怎么确定芯片的访问地址? ...
- 解决uni-file-picker组件在ios点击失效的问题
从组件源码里找到choose-and-upload-file.js文件,查找chooseAndUploadFile方法,在方法里添加下面代码,保存即可解决. opts.sourceType = ['a ...
- 题解 matrix
传送门 无比毒瘤的dp题,而且伪装地好像很可做的样子 考场上我给它氪了差不多一个小时最后还是只能扔了个20pts状压走人 以下思路基本均来源于题解: 对于此题,题面中三个限制条件: (1)第 i 行第 ...
- 一 · 路由事件的三种方式/策略(冒泡 直接 隧道)
WPF中的路由事件是沿着VisualTree传递的,作用是用来调用应用程序的元素树上的各种监听器上的处理程序. (1)冒泡,这种事件处理方式是从源元素向上级流过去,直到到达根节点即顶层节点,一般为最外 ...
- FLV简介
FLV (Flash Video) 是由 Adobe 公司推出的一种封装格式,主要用于流媒体系统. FLV 封装的媒体文件具有体积轻巧.封装播放简单等特点,很适合网络应用. 目前各浏览器普遍使用 Fl ...
- spring整合LOG4J2日志
POM文件 <!-- Log Begin --> <slf4j.version>1.7.24</slf4j.version> <log4j2.version& ...
- ORB_SLAM2 Ubuntu16.04编译错误
Ubuntu14.04一切正常,迁移到Ubuntu16.04后编译报错,提示: /usr/include/eigen3/Eigen/src/Core/AssignEvaluator.h:745:3: ...
- Photoshop 各混合模式 RGB 是如何计算的
原文链接:https://www.jb51.net/photoshop/249182.html 1.正常模式(Normal) 默认模式,显示混合色图层的像素,没有进行任何的图层混合.这意味着基色图层( ...