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 ...
随机推荐
- 003 PCI Express体系结构(三)
一.PCI总线的存储器读写总线事务 总线的基本任务是实现数据传送,将一组数据从一个设备传送到另一个设备,当然总线也可以将一个设备的数据广播到多个设备.在处理器系统中,这些数据传送都要依赖一定的规则,P ...
- 【mysql】用户和权限管理
1.用户管理 相关命令如下 命令 描述 备注 create user zhang3 identified by '123123'; 创建名称为zhang3 的用户,密码设为123123: sele ...
- JDBC中级篇(MYSQL)——模拟从数据库中上传下载附件
注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package b_blob_clob; import java.io.BufferedOutputStream; import j ...
- 如何从 vue-element-admin 迁移到 Fantastic-admin
// FIXME 链接更新 如果你还不知道 Fantastic-admin 是什么,那么我先用几张预览图给大家了解一番. 看来预览图,如果你感兴趣,可以点这里来详细了解并试用,这是一款完成度极高,开箱 ...
- MySQL-存储引擎-1
一.MySQL存储引擎 mysql> create table country( -> country_id smallint unsigned not null auto_increme ...
- React事件处理、收集表单数据、高阶函数
3.React事件处理.收集表单数据.高阶函数 3.1事件处理 class Demo extends React.Component { /* 1. 通过onXxx属性指定事件处理函数(注意大小写) ...
- JavaWeb使用Filter进行字符编码过滤 预防web服务中文乱码
JavaWeb使用Filter进行字符编码过滤 预防web服务中文乱码 准备条件:一个创建好的 JavaWeb 项目 步骤: 1.创建一个类并实现 Filter 接口 import javax.ser ...
- 通俗易懂讲解Word2vec的本质
本文首发于微信公众号「对白的算法屋」,来一起学AI叭 一.Word2vec CBOW(Continuous Bag-of-Words):每个词的含义都由相邻词决定. Skip-gram:依据分布的相似 ...
- Spring(二)——IOC
一.入门 1.案例 1 public class Student { 2 3 private String name; 4 5 public Student() { 6 System.out.prin ...
- Java的参数传递是值传递还是引用传递?
一.前言 首先先说结论,Java中方法参数传递方式是按值传递.如果参数是基本类型,传递的是基本类型的字面量值的拷贝.如果参数是引用类型,传递的是该参量所引用的对象在堆中地址值的拷贝. 接下来深入了解一 ...