詳解java封裝返回結(jié)果與RestControllerAdvice注解
1.為什么要把結(jié)果封裝成統(tǒng)一格式?
異常和正常情況無法區(qū)分:異常情況返回?cái)?shù)據(jù)為null,正常情況下查詢結(jié)果也為null,返回給前端無法區(qū)分
顯示拋出異常信息:前端需要顯示拋出的異常信息
@AllArgsConstructor
public enum ResultCode {
CODE_200(200, "success"),
CODE_1000(1000, "fail");
@Getter
private Integer code;
@Getter
private String msg;
}
@Data
public class Result<T> {
private String msg;
private Integer code;
private T data;
private Result(String msg, Integer code) {
this.msg = msg;
this.code = code;
}
private Result(ResultCode resultCode, String msg) {
this(msg, resultCode.getCode());
}
private Result(ResultCode resultCode) {
this(resultCode.getMsg(), resultCode.getCode());
}
public static <T>Result<T> result(ResultCode resultCode,T data) {
Result result = new Result(resultCode);
result.setData(data);
return result;
}
public static <T>Result<T> fail(ResultCode resultCode,String message) {
Result result = new Result(resultCode, message);
result.setData(null);
return result;
}
public static <T>Result<T> fail(T data) {
Result result = new Result(ResultCode.CODE_1000);
result.setData(data);
return result;
}
public static <T>Result<T> success(T data) {
Result result = new Result(ResultCode.CODE_200);
result.setData(data);
return result;
}
}
不封裝:

封裝:

2.統(tǒng)一異常接收
為什么要用統(tǒng)一異常接收?
通常在service層拋異常,涉及到事務(wù)時(shí)不會(huì)進(jìn)行try-catch,需要在controller里處理異常。即使能夠進(jìn)行try-catch的地方也需要統(tǒng)一返回格式,造成重復(fù)代碼很多,可讀性比較差。
如何實(shí)現(xiàn)統(tǒng)一的異常接收?
@Slf4j
@RestControllerAdvice
public class GlobalException {
@ExceptionHandler(Exception.class)
public Result<?> handlerException(Exception exception) {
log.info("Exception異常信息:" + exception.getMessage());
return Result.fail(ResultCode.CODE_1000, exception.getMessage());
}
@ExceptionHandler(value = {MyException.class})
public Result<?> handlerMyException(Exception exception) {
log.info("MyException異常信息:" + exception.getMessage());
return Result.fail(ResultCode.CODE_1000, exception.getMessage());
}
}
拋出異常后,會(huì)進(jìn)入到@RestControllerAdvice注解的方法,過濾出和拋出異常相同的class的方法,執(zhí)行相應(yīng)的方法。
protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) {
//根據(jù)異常類型過濾方法
ServletInvocableHandlerMethod exceptionHandlerMethod = this.getExceptionHandlerMethod(handlerMethod, exception);
if (exceptionHandlerMethod == null) {
return null;
} else {
if (this.argumentResolvers != null) {
exceptionHandlerMethod.setHandlerMethodArgumentResolvers(this.argumentResolvers);
}
if (this.returnValueHandlers != null) {
exceptionHandlerMethod.setHandlerMethodReturnValueHandlers(this.returnValueHandlers);
}
ServletWebRequest webRequest = new ServletWebRequest(request, response);
ModelAndViewContainer mavContainer = new ModelAndViewContainer();
ArrayList<Throwable> exceptions = new ArrayList();
try {
if (this.logger.isDebugEnabled()) {
this.logger.debug("Using @ExceptionHandler " + exceptionHandlerMethod);
}
Throwable cause;
for(Throwable exToExpose = exception; exToExpose != null; exToExpose = cause != exToExpose ? cause : null) {
exceptions.add(exToExpose);
cause = ((Throwable)exToExpose).getCause();
}
Object[] arguments = new Object[exceptions.size() + 1];
exceptions.toArray(arguments);
arguments[arguments.length - 1] = handlerMethod;
//執(zhí)行方法
exceptionHandlerMethod.invokeAndHandle(webRequest, mavContainer, arguments);
} catch (Throwable var13) {
if (!exceptions.contains(var13) && this.logger.isWarnEnabled()) {
this.logger.warn("Failure in @ExceptionHandler " + exceptionHandlerMethod, var13);
}
return null;
}
if (mavContainer.isRequestHandled()) {
return new ModelAndView();
} else {
ModelMap model = mavContainer.getModel();
HttpStatus status = mavContainer.getStatus();
ModelAndView mav = new ModelAndView(mavContainer.getViewName(), model, status);
mav.setViewName(mavContainer.getViewName());
if (!mavContainer.isViewReference()) {
mav.setView((View)mavContainer.getView());
}
if (model instanceof RedirectAttributes) {
Map<String, ?> flashAttributes = ((RedirectAttributes)model).getFlashAttributes();
RequestContextUtils.getOutputFlashMap(request).putAll(flashAttributes);
}
return mav;
}
}
}
protected ServletInvocableHandlerMethod getExceptionHandlerMethod(@Nullable HandlerMethod handlerMethod, Exception exception) {
Class<?> handlerType = null;
if (handlerMethod != null) {
handlerType = handlerMethod.getBeanType();
ExceptionHandlerMethodResolver resolver = (ExceptionHandlerMethodResolver)this.exceptionHandlerCache.get(handlerType);
if (resolver == null) {
resolver = new ExceptionHandlerMethodResolver(handlerType);
this.exceptionHandlerCache.put(handlerType, resolver);
}
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(handlerMethod.getBean(), method, this.applicationContext);
}
if (Proxy.isProxyClass(handlerType)) {
handlerType = AopUtils.getTargetClass(handlerMethod.getBean());
}
}
//初始化的時(shí)候已經(jīng)將beanType作為key,標(biāo)注@ExceptionHandler的方法包裝成resolve作為value放到exceptionHandlerAdviceCache中
Iterator var9 = this.exceptionHandlerAdviceCache.entrySet().iterator();
while(var9.hasNext()) {
Map.Entry<ControllerAdviceBean, ExceptionHandlerMethodResolver> entry = (Map.Entry)var9.next();
ControllerAdviceBean advice = (ControllerAdviceBean)entry.getKey();
if (advice.isApplicableToBeanType(handlerType)) {
ExceptionHandlerMethodResolver resolver = (ExceptionHandlerMethodResolver)entry.getValue();
//根據(jù)class進(jìn)行篩選
Method method = resolver.resolveMethod(exception);
if (method != null) {
return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext);
}
}
}
return null;
}
直接在service層拋出異常,controller中返回正常的結(jié)果,由標(biāo)注了@RestControllerAdvice的類對(duì)異常進(jìn)行處理
@RestController
@RequestMapping("/user")
public class UserController {
@GetMapping("/test")
public Result<Boolean> testGlobalException() {
globalException.throwException();
return Result.success(Boolean.TRUE);
}
}以上就是詳解java封裝返回結(jié)果與RestControllerAdvice注解的詳細(xì)內(nèi)容,更多關(guān)于java RestControllerAdvice 封裝返回的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
restTemplate發(fā)送get與post請(qǐng)求并且?guī)?shù)問題
這篇文章主要介紹了restTemplate發(fā)送get與post請(qǐng)求并且?guī)?shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Springboot中如何使用過濾器校驗(yàn)PSOT類型請(qǐng)求參數(shù)內(nèi)容
在Springboot中創(chuàng)建過濾器,用來過濾所有POST類型請(qǐng)求并獲取body中的參數(shù)進(jìn)行校驗(yàn)內(nèi)容是否合法,該方法僅適用于POST類型請(qǐng)求,本文給大家介紹Springboot中如何使用過濾器校驗(yàn)PSOT類型請(qǐng)求參數(shù)內(nèi)容,感興趣的朋友一起看看吧2023-08-08
Java8 Stream Collectors收集器使用方法解析
這篇文章主要介紹了Java8 Stream Collectors收集器使用方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
基于kafka實(shí)現(xiàn)Spring Cloud Bus消息總線
消息總線是一種通信工具,可以在機(jī)器之間互相傳輸消息、文件等,這篇文章主要介紹了如何利用kafka實(shí)現(xiàn)SpringCloud Bus消息總線,感興趣的可以學(xué)習(xí)一下2022-04-04
Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(12)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07
Java實(shí)現(xiàn)獲取指定個(gè)數(shù)的不同隨機(jī)數(shù)
今天小編就為大家分享一篇關(guān)于Java實(shí)現(xiàn)獲取指定個(gè)數(shù)的不同隨機(jī)數(shù),小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧2019-01-01
詳解Java對(duì)象轉(zhuǎn)換神器MapStruct庫的使用
在我們?nèi)粘i_發(fā)的程序中,為了各層之間解耦,一般會(huì)定義不同的對(duì)象用來在不同層之間傳遞數(shù)據(jù)。當(dāng)在不同層之間傳輸數(shù)據(jù)時(shí),不可避免地經(jīng)常需要將這些對(duì)象進(jìn)行相互轉(zhuǎn)換。今天給大家介紹一個(gè)對(duì)象轉(zhuǎn)換工具M(jìn)apStruct,代碼簡潔安全、性能高,強(qiáng)烈推薦2022-09-09
詳解使用Mybatis-plus + velocity模板生成自定義的代碼
這篇文章主要介紹了詳解使用Mybatis-plus + velocity模板生成自定義的代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03

