生产级别的通用异常处理
所有的异常都抛出,统一在表现层处理,其余直接抛出就好。

spring定义的错误响应方式如图所示。
使用Java提供的异常类抛出的时候只可以传递string,所以需要自定义一个异常类,继承RuntimeException,抛出的时候同时包含信息和状态码

新建通用异常处理类
相当于aop里面的通知,起到拦截的作用,要做到通用,状态码不可以写死,这里的设计不对,后面会改进
src/main/java/com/deltaqin/common/advice/CommonExceptionHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.deltaqin.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());
} }
|
common模块引入springMVC的依赖
需要controller注解
不需要启动器,只需要spring-webmvc里面的MVC
1 2 3 4
| <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> </dependency>
|
自定义异常类
抛出的时候只抛出自定义的异常
src/main/java/com/deltaqin/common/exception/mallException.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| package com.deltaqin.common.exception;
import com.deltaqin.common.enums.ExceptionEnums; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor;
@AllArgsConstructor @NoArgsConstructor @Getter public class mallException extends RuntimeException {
private ExceptionEnums exceptionEnums; }
|
异常枚举类
具有固定实例个数的类,不像正常类无限制,类的对象是提前创建好的
src/main/java/com/deltaqin/common/enums/ExceptionEnums.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.deltaqin.common.enums;
import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor;
@Getter @NoArgsConstructor @AllArgsConstructor public enum ExceptionEnums {
PRICE_CANNOT_BE_NALL(400, "价格不能为空"), PRICE_CANNOT_BE(400, "价格不能为空") ; private int code; private String msg; }
|
item-service模块引入自定义通用异常的依赖
1 2 3 4 5
| <dependency> <groupId>com.deltaqin.common</groupId> <artifactId>common</artifactId> <version>1.0.0-SNAPSHOT</version> </dependency>
|
修改item-service抛出的异常
抛出异常的时候,不仅仅是传递信息还要传递状态码
src/main/java/com/deltaqin/item/web/ItemController.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| package com.deltaqin.item.web;
import com.deltaqin.common.enums.ExceptionEnums; import com.deltaqin.common.exception.mallException; import com.deltaqin.item.service.ItemService; import com.deltaqin.item.pojo.Item; 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) {
throw new mallException(ExceptionEnums.PRICE_CANNOT_BE_NALL); } item = itemService.saveItem(item); return ResponseEntity.status(HttpStatus.CREATED).body(item); } }
|
修改通用异常处理类
src/main/java/com/deltaqin/common/advice/CommonExceptionHandler.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| package com.deltaqin.common.advice;
import com.deltaqin.common.exception.mallException; import com.deltaqin.common.vo.ExceptionResult;
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class CommonExceptionHandler {
@ExceptionHandler(mallException.class) public ResponseEntity<ExceptionResult> handleException(mallException e){ return ResponseEntity.status(e.getExceptionEnums().getCode()) .body(new ExceptionResult(e.getExceptionEnums()));
} }
|
自定义异常结果集
src/main/java/com/deltaqin/common/vo/ExceptionResult.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.deltaqin.common.vo;
import com.deltaqin.common.enums.ExceptionEnums; import lombok.Data;
@Data public class ExceptionResult { private int status; private String message; private Long timestamp;
public ExceptionResult(ExceptionEnums em){ this.status = em.getCode(); this.message = em.getMsg(); this.timestamp = System.currentTimeMillis(); } }
|

注意
- 写代码报了一个小时错吗,老是让我定义一个service,我都懵逼了。。。居然是启动类的类名和service的类名一样了
- 注意启动类的位置决定了可以扫描的包的位置。要放在com.deltaqin里面,不要再往里面放,不然导入common的时候扫不到com.deltaqin.common里面的内容