java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > @RestControllerAdvice作用

SpringBoot的@RestControllerAdvice作用详解

作者:java-zh

这篇文章主要介绍了SpringBoot的@RestControllerAdvice作用详解,@RestContrllerAdvice是一种组合注解,由@ControllerAdvice,@ResponseBody组成,本质上就是@Component,需要的朋友可以参考下

一、@RestControllerAdvice是什么?

@RestContrllerAdvice是一种组合注解,由@ControllerAdvice,@ResponseBody组成

@ControllerAdvice继承了@Component,反过来,可以理解为@RestContrllerAdvice本质上就是@Component

1.1 @Component是什么?

本质上是一个类,泛指各种组件,就是说当我们的类不属于各种归类的时候(不属于@Controller,@Service等的时候),我们就可以使用@Component

作用就是实现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代码实现自定义捕获异常

3.3.1 自定义异常枚举

public interface BaseCodeMsg {
    String getCode();
    String getMsg();
}
public enum PlatformExceptionMsgEnum implements BaseCodeMsg {
    /**
     * base平台返回的异常信息
     */
    SELECT_NULL("000000001", "查询数据为空"),
    INVOKE_IS_REJECT("00000002", "请求被拒绝"),
    ILLEGAL_ARGUMENT_FORMAT("000000003", "非法参数格式"),
    ILLEGAL_ARGUMENT("000000004","数据非法"),
    SYSTEM_EXCEPTION("000000005", "系统异常");
    /**
     * 错误码
     */
    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调用接口的异常类
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AbstractApiException.class)
    public BaseResult abstractApiException(AbstractApiException e) {
        return BaseResult.fail(e.getCode(), e.getMsg());
    }
    /**
     * 前端传入的参数和后端传入的参数接收不匹配
     *
     * @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 代码实现自定义返回结果

没有自定义返回结果之前

自定义返回结果以后

3.4.1 controller

@RestController
public class TestController {
    @GetMapping("/test2")
    public String test2() {
        return "test2";
    }
}

3.4.2 返回结果来

BaseResult返回结果类在上面,对应需要导入json的jar也在上面

3.4.3 @RestControllerAdvice

@RestControllerAdvice(
        annotations = {RestController.class}
)
@Configuration
public class BaseResultResponseAdvice implements ResponseBodyAdvice<Object> {
    @Autowired
    private ObjectMapper objectMapper;
    /**
     * @param methodParameter 利用这个参数判断注解信息
     * @param aClass
     * @return
     */
    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }
    /**
     * @param body               原controller需要返回的内容
     * @param methodParameter    利用这个参数判断注解信息
     * @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的使用还可以指定对应的注解、包,类。比如你需要返回自定义结果格式,可以指定@RestController层使用,如果你要指定类和包也可以

4.1 指定注解

@RestControllerAdvice(
        annotations = {RestController.class}
)

4.2 指定类

@RestControllerAdvice(
        basePackageClasses = TestController.class
)

4.3 指定包

@RestControllerAdvice(
        basePackages = "com.common.base.controller"
)

到此这篇关于SpringBoot的@RestControllerAdvice作用详解的文章就介绍到这了,更多相关@RestControllerAdvice作用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文