完整代碼地址在結(jié)尾!!
第一步,創(chuàng)建一個(gè)SpringBoot項(xiàng)目,此處不贅述
第二步,編寫(xiě)application.yml配置文件,如下
server:
port: 8085
spring:
application:
name: exception-demo-server
第三步,創(chuàng)建響應(yīng)碼枚舉ResponseEnums,統(tǒng)一響應(yīng)類(lèi)Response,如下
ResponseEnums
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @version 1.0
* @author jinhaoxun
* @date 2018-05-09
* @description 響應(yīng)碼枚舉
*/
@Getter
@AllArgsConstructor
public enum ResponseEnums {
/**
* 請(qǐng)求成功
*/
SUCCESS(200,"請(qǐng)求成功"),
/**
* 系統(tǒng)異常,請(qǐng)稍后重試
*/
EXCEPTION(10000,"系統(tǒng)異常,請(qǐng)稍后重試"),
/**
* 請(qǐng)求的資源(網(wǎng)頁(yè)等)不存在
*/
NOT_FOUND(404,"請(qǐng)求的資源(網(wǎng)頁(yè)等)不存在"),
/**
* 共6位,1:系統(tǒng)異常碼和值定義在該類(lèi)中,大家公用
* 前2位表示大板塊(10:系統(tǒng),11:管理后臺(tái)模塊,12:文章模塊,13:公共模塊,14:上傳下載文件模塊)
* 第3,4位表示項(xiàng)目的小模塊,5,6位代表具體錯(cuò)誤
*/
/************************** 系統(tǒng)模塊 *******************************/
/**
* 登陸超時(shí)
*/
LOGIN_TIMEOUT(100001 ,"登陸超時(shí)"),
/**
* 參數(shù)有誤
*/
WRONG_PARAM(100002 ,"參數(shù)有誤"),
/**
* 缺少必要的參數(shù)
*/
MISS_PARAM(100003 ,"缺少必要的參數(shù)"),
/**
* Hystrix 降級(jí)開(kāi)啟拋出異常
*/
HYSTRIX_THROW_EXCEPTION(100004 ,"請(qǐng)求超時(shí),請(qǐng)稍后重試"),
/************************** 賬號(hào)模塊 *******************************/
/**
* 您沒(méi)有該權(quán)限
*/
MNG_PERMISSION_DENY(110101,"您沒(méi)有該權(quán)限"),
/**
* 密碼錯(cuò)誤
*/
PASSWORD_WRONG(110102,"密碼錯(cuò)誤"),
/**
* 用戶(hù)不存在
*/
USER_NOT_EXIST(110103,"用戶(hù)不存在"),
/**
* 賬號(hào)被封禁
*/
ACCOUNT_IS_BLOCKED(110104,"賬號(hào)被封禁"),
/**
* 賬號(hào)已注銷(xiāo)
*/
ACCOUNT_IS_CANCELLED(110105,"賬號(hào)已注銷(xiāo)"),
/**
* 驗(yàn)證碼已過(guò)期
*/
VERIFICATION_CODE_EXPIRED(110106,"驗(yàn)證碼已過(guò)期"),
/**
* 從Redis中獲取驗(yàn)證碼錯(cuò)誤
*/
GET_CODE_WRONG_FROM_REDIS(110107,"從Redis中獲取驗(yàn)證碼錯(cuò)誤"),
/**
* 身份信息已過(guò)期
*/
IDENTITY_INFORMATION_IS_EXPIRED(110108,"身份信息已過(guò)期"),
/**
* 用戶(hù)未登錄
*/
USER_NOT_LOG_IN(110109,"用戶(hù)未登錄"),
/**
* 用戶(hù)退出登錄失敗
*/
USER_LOG_OUT_FAIL(110110,"用戶(hù)退出登錄失敗"),
/**
* 密碼修改失敗
*/
PASSWORD_CHANGE_FAIL(110112,"密碼修改失敗"),
/**
* 賬號(hào)封禁失敗
*/
ACCOUNT_BLOCK_FAIL(110113,"賬號(hào)封禁失敗"),
/**
* 賬號(hào)解封失敗
*/
ACCOUNT_UNSEALING_FAIL(110114,"賬號(hào)解封失敗"),
/**
* 賬號(hào)注冊(cè)失敗
*/
ACCOUNT_REGISTRATION_FAIL(110115,"賬號(hào)注冊(cè)失敗"),
/**
* 獲取手機(jī)驗(yàn)證碼失敗
*/
GET_PHONE_CODE_FAIL(110116,"獲取手機(jī)驗(yàn)證碼失敗"),
/**
* 獲取郵箱驗(yàn)證碼失敗
*/
GET_EMAIL_CODE_FAIL(110117,"獲取郵箱驗(yàn)證碼失敗"),
/**
* 獲取用戶(hù)信息失敗
*/
GET_USERINFO_FAIL(110118,"獲取用戶(hù)信息失敗"),
/**
* 更新用戶(hù)信息失敗
*/
UPDATE_USERINFO_FAIL(110119,"更新用戶(hù)信息失敗"),
/**
* 賬號(hào)注銷(xiāo)失敗
*/
ACCOUNT_CANAEL_FAIL(110120,"賬號(hào)注銷(xiāo)失敗"),
/**
* 重復(fù)獲取驗(yàn)證碼
*/
REPEAT_GET_USER_LOG_IN_CODE(110121,"重復(fù)獲取驗(yàn)證碼"),
/**
* 驗(yàn)證碼已過(guò)期
*/
USER_LOG_IN_CODE_EXPIRATIONED(110122,"驗(yàn)證碼已過(guò)期"),
/**
* 驗(yàn)證碼錯(cuò)誤
*/
USER_LOG_IN_CODE_WRONG(110123,"驗(yàn)證碼錯(cuò)誤"),
;
public Integer code;
public String msg;
}
Response
import com.luoyu.exception.constant.ResponseEnums;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* Response
*
* @author luoyu
* @date 2018/10/07 13:28
* @description 通用返回類(lèi)
*/
@Data
public class Response implements Serializable {
private String msg;
private int code;
private Object data;
private String time;
private Response() {
}
private Response(int code, String msg) {
this.code = code;
this.msg = msg;
this.time = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
}
private Response(int code, String msg, Object data) {
this.code = code;
this.msg = msg;
this.data = data;
this.time = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
}
public static Response success() {
return new Response(ResponseEnums.SUCCESS.getCode(), ResponseEnums.SUCCESS.getMsg());
}
public static Response success(Object data) {
return new Response(ResponseEnums.SUCCESS.getCode(), ResponseEnums.SUCCESS.getMsg(), data);
}
public static Response success(Object data, String msg) {
return new Response(ResponseEnums.SUCCESS.getCode(), msg, data);
}
public static Response fail() {
return new Response(ResponseEnums.EXCEPTION.getCode(), ResponseEnums.EXCEPTION.getMsg());
}
public static Response fail(ResponseEnums responseEnums) {
return new Response(responseEnums.getCode(), responseEnums.getMsg());
}
public static Response fail(ResponseEnums responseEnums, Object data) {
return new Response(responseEnums.getCode(), responseEnums.getMsg(), data);
}
public static Response fail(int code, String msg) {
return new Response(code, msg);
}
public static Response fail(int code, String msg, Object data) {
return new Response(code, msg, data);
}
}
第四步,創(chuàng)建自定義異常類(lèi)CustomException,如下
import lombok.Data;
import java.io.Serializable;
/**
* @version 1.0
* @author jinhaoxun
* @date 2018-05-09
* @description 自定義統(tǒng)一異常(相當(dāng)于業(yè)務(wù)異常)
*/
@Data
public class CustomException extends Exception implements Serializable {
private static final long serialVersionUID = 1L;
private Integer code;
private String log;
/**
* @author jinhaoxun
* @description 構(gòu)造器
* @param code 異常狀態(tài)碼
* @param log 異常打印日志
* @param msg 異常返回信息
*/
public CustomException(Integer code, String log, String msg) {
super(msg);
this.code = code;
this.log = log;
}
}
第五步,創(chuàng)建全局異常統(tǒng)一處理類(lèi)ExceptionHandle,如下
import com.luoyu.exception.constant.ResponseEnums;
import com.luoyu.exception.entity.vo.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @version 1.0
* @author jinhaoxun
* @date 2018-05-09
* @description 統(tǒng)一的異常處理
*/
@Slf4j
@RestControllerAdvice
public class ExceptionHandle {
/**
* @author jinhaoxun
* @description 統(tǒng)一的異常處理方法
* @param e 拋出的異常
* @return 返回給前端的錯(cuò)誤信息提示
*/
@ExceptionHandler(value = Exception.class)
public Response handleException(Exception e){
if(e instanceof CustomException) {
CustomException ex = (CustomException)e;
log.info("自定義業(yè)務(wù)異常:msg:" + ex.getMessage() + ",log:" + ex.getLog(), e);
return Response.fail(ex.getCode(), ex.getMessage(),null);
}else if(e instanceof MethodArgumentNotValidException) {
MethodArgumentNotValidException ex = (MethodArgumentNotValidException)e;
log.error("參數(shù)校驗(yàn)異常:msg:" + ex.getBindingResult().getFieldError().getDefaultMessage());
return Response.fail(ResponseEnums.WRONG_PARAM.getCode(),
ResponseEnums.WRONG_PARAM.getMsg() + ":"
+ ex.getBindingResult().getFieldError().getDefaultMessage(), null);
}else{
log.error("統(tǒng)一系統(tǒng)異常:msg:" + e.getMessage(), e);
return Response.fail(ResponseEnums.EXCEPTION.getCode(), ResponseEnums.EXCEPTION.getMsg(), null);
}
}
}
說(shuō)明
- @ExceptionHandler用于統(tǒng)一處理某一類(lèi)異常,從而能夠減少代碼重復(fù)率和復(fù)雜度,所有拋出來(lái)的異常都會(huì)在這里被捕獲
第六步,創(chuàng)建TestService,TestServiceImpl,TestController,如下
TestService
/**
* @Description:
* @Author: jinhaoxun
* @Date: 2020/7/10 10:31 上午
* @Version: 1.0.0
*/
public interface TestService {
void get1() throws Exception;
void get2() throws Exception;
}
TestServiceImpl
import com.luoyu.exception.exception.CustomException;
import com.luoyu.exception.service.TestService;
import org.springframework.stereotype.Service;
/**
* @Description:
* @Author: jinhaoxun
* @Date: 2020/7/10 10:32 上午
* @Version: 1.0.0
*/
@Service
public class TestServiceImpl implements TestService {
@Override
public void get1() throws Exception {
int i = 1/0;
}
@Override
public void get2() throws Exception {
try {
int i = 1/0;
}catch (Exception e){
throw new CustomException(10086, "自定義打印異常", "自定義返回異常");
}
}
}
TestController
import com.luoyu.exception.entity.vo.Response;
import com.luoyu.exception.service.TestService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @Description:
* @Author: jinhaoxun
* @Date: 2020/7/10 10:31 上午
* @Version: 1.0.0
*/
@RestController
@RequestMapping("/test")
public class TestController {
@Resource
private TestService testService;
/**
* @author jinhaoxun
* @description 測(cè)試接口1
*/
@GetMapping("/get1")
public Response get1() throws Exception {
testService.get1();
return Response.success();
}
/**
* @author jinhaoxun
* @description 測(cè)試接口2
*/
@GetMapping("/get2")
public Response get2() throws Exception {
testService.get2();
return Response.success();
}
}
解釋
- 從可能出現(xiàn)異常的地方往外面拋異常,本文是從service開(kāi)始,直到controller往外面拋出異常后,會(huì)被ExceptionHandle捕獲,然后自行進(jìn)行處理,打印日志,統(tǒng)一狀態(tài)碼,錯(cuò)誤信息返回給前端。
第七步,啟動(dòng)項(xiàng)目,使用postman調(diào)接口,如下圖
測(cè)試1,使用GET請(qǐng)求http://localhost:8085/test/get1

image.png

image.png
測(cè)試2,使用GET請(qǐng)求http://localhost:8085/test/get2

image.png

image.png