詳解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-07Springboot中如何使用過濾器校驗(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-08Java8 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-04Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(12)
下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧,希望可以幫到你2021-07-07Java實(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,代碼簡(jiǎn)潔安全、性能高,強(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