SpringBoot的@RestControllerAdvice作用詳解
一、@RestControllerAdvice是什么?
@RestContrllerAdvice是一種組合注解,由@ControllerAdvice,@ResponseBody組成
@ControllerAdvice繼承了@Component,反過來,可以理解為@RestContrllerAdvice本質(zhì)上就是@Component
1.1 @Component是什么?
本質(zhì)上是一個類,泛指各種組件,就是說當我們的類不屬于各種歸類的時候(不屬于@Controller,@Service等的時候),我們就可以使用@Component
作用就是實現(xiàn)bean注入,利用這個注解可以取代spring的xml配置文件
1.2 @Component案例
1.2.1 準備的jar
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.75</version> </dependency>
1.2.2 controller
@RestController public class TestController { @Autowired private TestService testService; @GetMapping("/test3") public String test3() { return testService.test(); } }
1.2.3 接口
public interface TestService { String test(); }
1.2.4組件
@Component public class TestServiceImpl implements TestService { @Autowired private ObjectMapper objectMapper; @Override public String test() { String b = null; try { b = objectMapper.writeValueAsString("a"); System.out.println(b); } catch (Exception e) { } return b; } }
二、@RestControllerAdvice有什么作用?
- 自定義客戶端返回格式
- 捕獲客戶端返回異常
三、@RestControllerAdvice案例和使用場景
捕獲客戶端返回異常案例(自定義返回異常)
3.1 未自定義捕獲異常之前
3.2 自定義捕獲異常以后
3.3代碼實現(xiàn)自定義捕獲異常
3.3.1 自定義異常枚舉
public interface BaseCodeMsg { String getCode(); String getMsg(); }
public enum PlatformExceptionMsgEnum implements BaseCodeMsg { /** * base平臺返回的異常信息 */ SELECT_NULL("000000001", "查詢數(shù)據(jù)為空"), INVOKE_IS_REJECT("00000002", "請求被拒絕"), ILLEGAL_ARGUMENT_FORMAT("000000003", "非法參數(shù)格式"), ILLEGAL_ARGUMENT("000000004","數(shù)據(jù)非法"), SYSTEM_EXCEPTION("000000005", "系統(tǒng)異常"); /** * 錯誤碼 */ private final String code; /** * 錯誤信息 */ private final String msg; PlatformExceptionMsgEnum(String code, String msg) { this.code = code; this.msg = msg; } @Override public String getCode() { return code; } @Override public String getMsg() { return msg; } }
3.3.2 自定義平臺異常
public abstract class AbstractApiException extends RuntimeException{ public AbstractApiException() { } public abstract String getCode(); public abstract String getMsg(); }
public class PlatformException extends AbstractApiException { private String code; private String msg; public PlatformException(BaseCodeMsg baseCodeMsg) { code = baseCodeMsg.getCode(); msg = baseCodeMsg.getMsg(); } public static void throwException(BaseCodeMsg baseCodeMsg) { throw new PlatformException(baseCodeMsg.getCode(), baseCodeMsg.getMsg()); } public static void throwException(BaseCodeMsg baseCodeMsg, String msg) { throw new PlatformException(baseCodeMsg.getCode(), StringUtils.isEmpty(baseCodeMsg.getMsg()) ? msg : baseCodeMsg.getMsg()); } public static void throwException(String code, String msg) { throw new PlatformException(code, msg); } public static void throwException(String msg) { throw new PlatformException(PlatformExceptionMsgEnum.SYSTEM_EXCEPTION.getCode(), msg); } public PlatformException(String code, String msg) { this.code = code; this.msg = msg; } @Override public String getCode() { return code; } @Override public String getMsg() { return msg; } }
3.3.3 自定義返回類
@Data public class BaseResult<T> implements Serializable { private static final long serialVersionUID = 1L; private String code; private String msg; private String traceId; private T data; public boolean isSuccess() { return PlatformExceptionMsgEnum.SUCCESS.getCode().equals(this.code); } public static BaseResult ok() { return restBaseResult((Object)null, PlatformExceptionMsgEnum.SUCCESS); } public static <T> BaseResult<T> ok(T data) { return restBaseResult(data, PlatformExceptionMsgEnum.SUCCESS); } public static BaseResult fail() { return restBaseResult((Object)null, PlatformExceptionMsgEnum.SYSTEM_ERROR); } public static BaseResult fail(BaseCodeMsg baseCodeMsg) { return restBaseResult((Object)null, baseCodeMsg); } public static BaseResult fail(String code, String msg) { return restBaseResult((Object)null, code, msg); } private static <T> BaseResult<T> restBaseResult(T data, BaseCodeMsg baseCodeMsg) { return restBaseResult(data, baseCodeMsg.getCode(), baseCodeMsg.getMsg()); } private static <T> BaseResult<T> restBaseResult(T data, String code, String msg) { BaseResult<T> apiBaseResult = new BaseResult(); apiBaseResult.setCode(code); apiBaseResult.setData(data); apiBaseResult.setMsg(msg); apiBaseResult.setTraceId(MDC.get("traceId")); return apiBaseResult; } public BaseResult() { } }
3.3.4 controller層
@RestController public class TestController { @GetMapping("/test") public void test() { PlatformException.throwException(PlatformExceptionMsgEnum.SYSTEM_EXCEPTION); } }
3.3.5 @RestControllerAdvice
@RestControllerAdvice @Configuration public class GlobalExceptionHandler { private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class); private MessageSource messageSource; /** * 捕獲全局異常類 * * @param e * @return */ @ExceptionHandler({MethodArgumentNotValidException.class}) public BaseResult handle(MethodArgumentNotValidException e) { if (e.getBindingResult().hasErrors()) { String msg = ((ObjectError) e.getBindingResult().getAllErrors().get(0)).getDefaultMessage(); return BaseResult.fail(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT.getCode(), this.getI18nMsg(msg)); } else { log.info(e.getMessage(), e); return BaseResult.fail(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT.getCode(), this.getI18nMsg(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT.getMsg())); } } /** * 捕獲API調(diào)用接口的異常類 * * @param e * @return */ @ExceptionHandler(AbstractApiException.class) public BaseResult abstractApiException(AbstractApiException e) { return BaseResult.fail(e.getCode(), e.getMsg()); } /** * 前端傳入的參數(shù)和后端傳入的參數(shù)接收不匹配 * * @param e * @return */ @ExceptionHandler({HttpMessageNotReadableException.class}) public BaseResult handle(HttpMessageNotReadableException e) { log.warn(e.getMessage(), e); return BaseResult.fail(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT_FORMAT.getCode(), this.getI18nMsg(PlatformExceptionMsgEnum.ILLEGAL_ARGUMENT_FORMAT.getMsg())); } /** * 子類異常(相當于子類不能拋出比父類更廣泛異常) * * @param e * @return */ @ExceptionHandler({UndeclaredThrowableException.class}) public BaseResult handle(UndeclaredThrowableException e) { log.warn(e.getMessage(), e); return BaseResult.fail(PlatformExceptionMsgEnum.INVOKE_IS_REJECT.getCode(), this.getI18nMsg(PlatformExceptionMsgEnum.INVOKE_IS_REJECT.getMsg())); } /** * 異常捕獲 * * @param e 捕獲的異常,封裝返回的對象 * @return */ @ExceptionHandler(Exception.class) public BaseResult handleException(Exception e) { log.warn(e.getMessage(), e); StringJoiner joiner = new StringJoiner(":"); joiner.add(this.getI18nMsg(PlatformExceptionMsgEnum.INVOKE_IS_REJECT.getMsg())).add(e.getMessage()); return BaseResult.fail(PlatformExceptionMsgEnum.SYSTEM_EXCEPTION.getCode(), joiner.toString()); } private String getI18nMsg(String msg) { try { return this.messageSource.getMessage(msg, (Object[]) null, LocaleContextHolder.getLocale()); } catch (NoSuchMessageException var3) { return msg; } } public GlobalExceptionHandler(MessageSource messageSource) { this.messageSource = messageSource; } }
3.4 代碼實現(xiàn)自定義返回結(jié)果
沒有自定義返回結(jié)果之前
自定義返回結(jié)果以后
3.4.1 controller
@RestController public class TestController { @GetMapping("/test2") public String test2() { return "test2"; } }
3.4.2 返回結(jié)果來
BaseResult返回結(jié)果類在上面,對應需要導入json的jar也在上面
3.4.3 @RestControllerAdvice
@RestControllerAdvice( annotations = {RestController.class} ) @Configuration public class BaseResultResponseAdvice implements ResponseBodyAdvice<Object> { @Autowired private ObjectMapper objectMapper; /** * @param methodParameter 利用這個參數(shù)判斷注解信息 * @param aClass * @return */ @Override public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) { return true; } /** * @param body 原controller需要返回的內(nèi)容 * @param methodParameter 利用這個參數(shù)判斷注解信息 * @param mediaType * @param aClass * @param serverHttpRequest * @param serverHttpResponse * @return */ @Override public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) { try { if (methodParameter.getParameterType() == ResponseEntity.class) { return body; } else if (methodParameter.getParameterType() == BaseResult.class) { return body; } else if (methodParameter.getParameterType() == String.class) { serverHttpResponse.getHeaders().setContentType(MediaType.APPLICATION_JSON); return this.objectMapper.writeValueAsString(BaseResult.ok(body)); } else { return BaseResult.ok(body); } } catch (Throwable t) { return BaseResult.fail(); } } }
四、拓展
@RestControllerAdvice的使用還可以指定對應的注解、包,類。比如你需要返回自定義結(jié)果格式,可以指定@RestController層使用,如果你要指定類和包也可以
4.1 指定注解
@RestControllerAdvice( annotations = {RestController.class} )
4.2 指定類
@RestControllerAdvice( basePackageClasses = TestController.class )
4.3 指定包
@RestControllerAdvice( basePackages = "com.common.base.controller" )
到此這篇關(guān)于SpringBoot的@RestControllerAdvice作用詳解的文章就介紹到這了,更多相關(guān)@RestControllerAdvice作用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA下lombok安裝及找不到get,set的問題的解決方法
這篇文章主要介紹了IDEA下lombok安裝及找不到get,set的問題的解決方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題
這篇文章主要介紹了Mybatis如何解決sql中l(wèi)ike通配符模糊匹配問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-01-01java+mysql模擬實現(xiàn)銀行系統(tǒng)
這篇文章主要為大家詳細介紹了java+mysql模擬實現(xiàn)銀行系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-05-05spring+srpingmvc+hibernate實現(xiàn)動態(tài)ztree生成樹狀圖效果
這篇文章主要介紹了spring+srpingmvc+hibernate動態(tài)ztree生成樹狀圖效果,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-11-11