全栈项目-乐优商场-通用工具服务-通用异常处理
全栈项目-乐优商场-通用工具服务-通用异常处理
目录
文章目录
内容
项目中出现异常在所难免,那么出现异常后怎么处理呢?
1、 场景预设
1.1、场景
假如我们做新增商品,需要接收下面的参数:
price: 价格
name: 名称
对数据做简单校验:
价格不能为空
新增时,自动形成ID,然后随商品对象一起返回
1.2、代码
-
实体类:在’ly-item-interface’模块中下java/com/leyou/item/pojo包下新建Item类
package com.leyou.item.pojo; import lombok.Data; @Data public class Item { private Integer id; private String name; private Integer price; }
-
service层:’ly-item-service’模块,java/com/leyou/item/service/ItemService
package com.leyou.item.service; import com.leyou.item.pojo.Item; import org.springframework.stereotype.Service; import java.util.Random; @Service public class ItemService { public Item saveItem(Item item) { int id = new Random().nextInt(100); item.setId(id); return item; }
-
web层: ’ly-item-service’模块,java/com/leyou/item/web/ItemController
package com.leyou.item.web; import com.leyou.item.pojo.Item; import com.leyou.item.service.ItemService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("item") public class ItemController { @Autowired private ItemService itemService; @PostMapping public ResponseEntity<Item> saveItem(Item item) { // 校验价格 if (item.getPrice() == null) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null); } Item item1 = itemService.saveItem(item); return ResponseEntity.status(HttpStatus.CREATED).body(item1); } }
1.3、启动测试‘ly-item-service’模块
使用前后端交互测试工具,insomnia或者postman。这里我们用postman,发送正常测试数据,返回结果,如图:
发送错误测试数据,结果:
有逻辑错误,但是没有错误提示,显然很不友好,下面我们开始做改进
2、错误处理改进
2.1、发生错误,我们直接返回异常
其他不变,修改ItemController类saveItem方法如下:
public ResponseEntity<Item> saveItem(Item item) {
// 校验价格
if (item.getPrice() == null) {
throw new RuntimeException("价格不能为空");
}
Item item1 = itemService.saveItem(item);
return ResponseEntity.status(HttpStatus.CREATED).body(item1);
}
在此发送错误数据,postman返回数据:
{
"timestamp": "2020-08-04T08:22:43.966+00:00",
"status": 500,
"error": "Internal Server Error",
"message": "",
"path": "/item"
}
显示服务器内部错误,这显然有误导,只是参数传递错误。
2.2、@ControllerAdvice改进
- @ControllerAdvice注解会拦截所有带@Controller的返回
- @ExecptionHandler 会拦截异常
- @ExceptionHandler(异常类字节码)拦截指定类型的异常
在’ly-common’模块 java/com/leyou/common/advice 新建CommonExceptionHandler类,用来拦截处理异常,代码如下:
package com.leyou.common.advice;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleException(RuntimeException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(e.getMessage());
}
}
‘ly-item-service’ pom.xml 添加ly-common依赖,如下:
<dependency>
<groupId>com.leyou.common</groupId>
<artifactId>ly-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
重新加载工程,重启服务,重新发送错误测试,返回结果:
价格不能为空
这样的话,提示过于简单,继续改进
2.3、自定义异常类
一下类都在’ly-common’模块下 java/com/leyou/common包下创建
-
LyException.java ,自定义异常类 exception包下,代码如下:
package com.leyou.common.exception; import com.leyou.common.enums.ExceptionEnum; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @NoArgsConstructor @AllArgsConstructor @Getter public class LyException extends RuntimeException { private ExceptionEnum exceptionEnum; }
-
ExceptionEnum,异常枚举 enums包下,代码如下:
package com.leyou.common.enums; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @NoArgsConstructor @AllArgsConstructor @Getter public enum ExceptionEnum { PRICE_NOTNULL(400, "价格不能为空!") ; private int code; private String msg; }
-
ExceptionResult,异常结果类,封装异常结果,vo包下,代码如下:
package com.leyou.common.vo; import com.leyou.common.enums.ExceptionEnum; import lombok.Data; @Data public class ExceptionResult { private int status; private String message; private long timestamp; public ExceptionResult(ExceptionEnum e) { this.status = e.getCode(); this.message = e.getMsg(); this.timestamp = System.currentTimeMillis(); } }
整体包结构如图:
重新reiport工程,重新运行’ly-item-service’模块,如果报错就重新install下’leyou‘一级工程,重新发送错误数据,返回结果图示:
到此通用异常处理结束,如果有新的逻辑异常,比如注册用户名不能重复,只需在ExceptionEnum内添加,然后使用即可。
后记 :
本项目为参考某马视频开发,相关视频及配套资料可自行度娘或者联系本人。上面为自己编写的开发文档,持续更新。欢迎交流,本人QQ:806797785
前端项目源代码地址:https://gitee.com/gaogzhen/ly-bms // 前端后台管理系统
后端JAVA源代码地址:https://gitee.com/gaogzhen/ly-backend // 后端项目