Spring Boot统一异常处理方案示例
一、异常处理的原则
1、调用方法的时候返回布尔值来代替返回null,这样可以 NullPointerException。由于空指针是java异常里最恶心的异常。
2、 catch块里别不写代码。空catch块是异常处理里的错误事件,因为它只是捕获了异常,却没有任何处理或者提示。通常你起码要打印出异常信息,当然你最好根据需求对异常信息进行处理。
3、能抛受控异常(checked Exception)就尽量不抛受非控异常(unchecked Exception[Error或者RuntimeException的异常])。通过去掉重复的异常处理代码,可以提高代码的可读性。
4、 绝对不要让你的数据库相关异常显示到客户端。由于绝大多数数据库和SQLException异常都是受控异常,在Java中,你应该在DAO层把异常信息处理,然后返回处理过的能让用户看懂并根据异常提示信息改正操作的异常信息。
5、 在Java中,一定要在数据库连接,数据库查询,流处理后,在finally块中调用close()方法。
二、示例说明
本示例以“前后端分离模式”进行演示,调试用的异常信息通过日志的形式打印出来,代码并不完整,仅从异常处理进行部分代码示例。
1、创建异常类
@Getter //通过lombok插件实现省写setter或者getter方法
public class SellException extends RuntimeException { private Integer code;
private String message; public SellException(ResultEnum resultEnum) {
super(resultEnum.getMessage());
this.code = resultEnum.getCode();
} public SellException(Integer code,String message) {
this.code = code;
this.message = message;
}
}
2、使用Handler类捕获异常,统一格式返回给前端
@ControllerAdvice
public class SellExceptionHandler { @ExceptionHandler(value = SellException.class)
@ResponseBody
public ResultVO handlerSellerException(SellException e){
return ResultVOUtil.error(e.getCode(),e.getMessage());
} }
统一格式类:
public class ResultVOUtil { public static ResultVO success(Object object) {
ResultVO resultVO = new ResultVO();
resultVO.setData(object);
resultVO.setCode(0);
resultVO.setMsg("成功");
return resultVO;
} public static ResultVO success() {
return success(null);
} public static ResultVO error(Integer code,String msg) {
ResultVO resultVO = new ResultVO();
resultVO.setCode(code);
resultVO.setMsg(msg);
return resultVO;
} }
@Data
public class ResultVO<T> implements Serializable{ private static final long serialVersionUID = 8960474786737581150L; /**
* 错误码
*/
private Integer code;
/**
*提示信息
*/
private String msg;
/**
* 具体内容
*/
private T data; }
3、异常的信息通过枚举统一定义,方便定义管理
@Getter
public enum ResultEnum { SUCCESS(0,"成功"), PARAM_ERROR(1,"参数不正确"), PRODUCT_NOT_EXIST(10,"商品不存在"), PRODUCT_STOCK_ERROR(11,"商品库存不正确"), ORDER_NOT_EXIST(12,"订单不存在"), ORDERDETAIL_NOT_EXIST(13,"订单详情不存在"), ORDER_STATUS_ERROR(14,"订单状态不正确"), ORDER_UPDATE_FAIL(15,"订单更新失败"), ORDER_DETAIL_EMPTY(16,"订单详情为空"), CART_EMPTY(18,"购物车为空"), ORDER_OWNER_ERROR(19,"该订单不属于当前用户"),
; private Integer code;
private String message; ResultEnum(Integer code, String message) {
this.code = code;
this.message = message;
} }
4、使用异常类
① controller层处理页面传来参数的校验,如参数不正确,抛出自定义异常,由handler捕获返回给页面。
@RestController
@RequestMapping("/buyer/order")
@Slf4j
public class BuyerOrderController { @Autowired
private OrderService orderService; @Autowired
private BuyerService buyerService; //创建订单
@PostMapping("/create")
public ResultVO<Map<String,String>> create(@Valid OrderForm orderForm,
BindingResult bindingResult){
if (bindingResult.hasErrors()){
log.error("[创建订单] 参数不正确,orderForm={}",orderForm);
throw new SellException(ResultEnum.PARAM_ERROR.getCode(),
bindingResult.getFieldError().getDefaultMessage());
}
OrderDTO orderDTO = OrderForm2OrderDTOConverter.convert(orderForm);
if (CollectionUtils.isEmpty(orderDTO.getOrderDetailList())){
log.error("[创建订单] 购物不能为空");
throw new SellException(ResultEnum.CART_EMPTY);
} OrderDTO createResult = orderService.create(orderDTO);
Map<String,String> map = new HashMap<>();
map.put("orderId",createResult.getOrderId()); return ResultVOUtil.success(map); }
//订单列表
@GetMapping("/list")
public ResultVO<List<OrderDTO>> list(@RequestParam("openid") String openid,
@RequestParam(value = "page",defaultValue = "0") Integer page,
@RequestParam(value = "size",defaultValue = "10") Integer size){
if (StringUtils.isEmpty(openid)){
log.error("[查询订单列表] openid为空");
throw new SellException(ResultEnum.PARAM_ERROR);
}
PageRequest request = new PageRequest(page, size);
Page<OrderDTO> orderDTOPage = orderService.findList(openid, request); return ResultVOUtil.success(orderDTOPage.getContent());
} //订单详情
@GetMapping("/detail")
public ResultVO<OrderDTO> detail(@RequestParam("openid") String openid,
@RequestParam("orderId") String orderId){ OrderDTO orderDTO = buyerService.findOrderOne(openid, orderId);
return ResultVOUtil.success(orderDTO);
} //取消订单
@PostMapping("/cancel")
public ResultVO<OrderDTO> cancel(@RequestParam("openid") String openid,
@RequestParam("orderId") String orderId) { buyerService.cancelOrderOne(openid, orderId);
return ResultVOUtil.success();
}
}
② service处理返回的结果的异常,抛出自定义异常,由handler捕获返回给页面。
@Service
@Slf4j
public class BuyerServiceImpl implements BuyerService { @Autowired
private OrderService orderService; @Override
public OrderDTO findOrderOne(String openid, String orderId) {
return checkOrderOwner(openid, orderId);
} @Override
public OrderDTO cancelOrderOne(String openid, String orderId) {
OrderDTO orderDTO = checkOrderOwner(openid, orderId);
if (orderDTO == null){
log.error("[取消订单] 查不到该订单,orderDTO={}",orderId);
throw new SellException(ResultEnum.ORDER_NOT_EXIST);
}
return orderService.cancel(orderDTO);
} private OrderDTO checkOrderOwner(String openid, String orderId) {
OrderDTO orderDTO = orderService.findOne(orderId);
if (orderDTO == null){
return null;
}
if (!orderDTO.getBuyerOpenid().equalsIgnoreCase(openid)){
log.error("[查询订单] 订单的openid不一致,openid={},orderDTO={}",openid,orderDTO);
throw new SellException(ResultEnum.ORDER_OWNER_ERROR);
}
return orderDTO;
} }
Spring Boot统一异常处理方案示例的更多相关文章
- Spring Boot统一异常处理实践
摘要: SpringBoot异常处理. 原文:Spring MVC/Boot 统一异常处理最佳实践 作者:赵俊 前言 在 Web 开发中, 我们经常会需要处理各种异常, 这是一件棘手的事情, 对于很多 ...
- spring boot 统一异常处理
需求源自于任何一个业务的编写总会有各种各样的条件判断,需要时时手动抛出异常,又希望让接口返回友好的错误信息. spring boot提供的帮助是自动将异常重定向到路由为/error的控制器 但是我们又 ...
- Spring Boot☞ 统一异常处理
效果区: 代码区: package com.wls.integrateplugs.exception.dto; public class ErrorInfo<T> { public st ...
- js构建ui的统一异常处理方案(四)
上一篇我们介绍了统一异常处理方案的设计方案,这一篇我们将直接做一个小例子,验证我们的设计方案. 例子是一个todo的列表界面(页面代码参考于https://github.com/zongxiao/Dj ...
- js构建ui的统一异常处理方案(三)
笔者之前分析了如何实现js的责任链异常处理的方法,通过promise这个异步模型,我们能够对同步方法和异步方法的两种情况,均可以实现责任链模式.有了这些武器,我们就可以开始设计ui的统一异常处理方案了 ...
- Spring MVC 统一异常处理
Spring MVC 统一异常处理 看到 Exception 这个单词都心慌 如果有一天你发现好久没有看到Exception这个单词了,那你会不会想念她?我是不会的.她如女孩一样的令人心动又心慌,又或 ...
- 编程小白入门分享三:Spring AOP统一异常处理
Spring AOP统一异常处理 简介 在Controller层,Service层,可能会有很多的try catch代码块.这将会严重影响代码的可读性."美观性".怎样才可以把更多 ...
- Spring Boot全局异常处理
本文为大家分享了Spring Boot全局异常处理,供大家参考,具体内容如下 1.后台处理异常 a.引入thymeleaf依赖 <!-- thymeleaf模板插件 --> <dep ...
- Spring Boot Ftp Client 客户端示例支持断点续传
本章介绍 Spring Boot 整合 Ftpclient 的示例,支持断点续传 本项目源码下载 1 新建 Spring Boot Maven 示例工程项目 注意:是用来 IDEA 开发工具 File ...
随机推荐
- 813. Largest Sum of Averages
We partition a row of numbers A into at most K adjacent (non-empty) groups, then our score is the su ...
- [bug]小程序弹出层滚动穿透问题修复
如题,解决方案有两种: 1.如果弹出层没有滚动事件,就直接在蒙板和弹出层上加 catchtouchmove;(方便快捷) <template name="popup-modal&quo ...
- 组件基础—Vue学习笔记
ammm学习Vue有好几天了,今天遇到难点所以打算写一点随笔加深印象. 一.首先最简单的创建组件 1全局组件 Vue.component() Vue.component('hello',{ tem ...
- SnapKit 类图
 如图上图所示,居于中心的是ConstraintDescription,它用来生成Constraint,最后再转换成系统的NSLayoutConstraint. ConstraintDescript ...
- Rsync备份服务
一.Rsync 原理图 二.Rsync 原理描述 2.1:什么是Rsync Rsync是备份的一款软件,它可以实现全量备份.增量备份,也可以在不改变内容.属性的情况下进行同步备份,端口默认是873 2 ...
- POJ 2248
#include <iostream> #define MAXN 100 #define min __min using namespace std; int tem[MAXN]; int ...
- RabbitMQ初学之二:直接发送消息到队列
一. 背景 总前提:队列无论是在生产者声明还是在消费者声明,只有声明了,才能在RabbitMQ的管理界面看到该队列 生产者直接发送消息到队列,消费者直接消费队列中的消息,而不用指定exchange并绑 ...
- 关于符号Symbol第二篇
来看一下继承自Symbol的具体实现类. 1.TypeSymbol /** A class for type symbols. * Type variables are represented by ...
- jQuery操纵cookie(原生javascript处理cookie)
jQuery也是可以操作cookie的 1.首先下载jQuery.js 以及 jquery.cookie.js 这两个文件 2.安装(其实就是引用) <html> <he ...
- SharePoint 2013 EventHanlder工具
之前在07的时候使用SharePoint Event Receiver Manager (2007 & 2010)来管理SharePoint的Event Handler,但是2013后作者没有 ...