详解java封装返回结果与RestControllerAdvice注解

 更新时间:2022年09月15日 14:49:15   作者:bluesky  
这篇文章主要为大家介绍了java封装返回结果与RestControllerAdvice注解实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1.为什么要把结果封装成统一格式?

异常和正常情况无法区分:异常情况返回数据为null,正常情况下查询结果也为null,返回给前端无法区分

显示抛出异常信息:前端需要显示抛出的异常信息

@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.统一异常接收

为什么要用统一异常接收?

通常在service层抛异常,涉及到事务时不会进行try-catch,需要在controller里处理异常。即使能够进行try-catch的地方也需要统一返回格式,造成重复代码很多,可读性比较差。

如何实现统一的异常接收?

@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());
    }
}

抛出异常后,会进入到@RestControllerAdvice注解的方法,过滤出和抛出异常相同的class的方法,执行相应的方法。

protected ModelAndView doResolveHandlerMethodException(HttpServletRequest request, HttpServletResponse response, @Nullable HandlerMethod handlerMethod, Exception exception) {
    //根据异常类型过滤方法
    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;
            //执行方法
            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());
        }
    }
    //初始化的时候已经将beanType作为key,标注@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();
            //根据class进行筛选
            Method method = resolver.resolveMethod(exception);
            if (method != null) {
                return new ServletInvocableHandlerMethod(advice.resolveBean(), method, this.applicationContext);
            }
        }
    }
    return null;
}

直接在service层抛出异常,controller中返回正常的结果,由标注了@RestControllerAdvice的类对异常进行处理

@RestController
@RequestMapping("/user")
public class UserController {
    @GetMapping("/test")
    public Result<Boolean> testGlobalException() {
        globalException.throwException();
        return Result.success(Boolean.TRUE);
    }
}

以上就是详解java封装返回结果与RestControllerAdvice注解的详细内容,更多关于java RestControllerAdvice 封装返回的资料请关注脚本之家其它相关文章!

相关文章

  • 关于Prometheus + Spring Boot 应用监控的问题

    关于Prometheus + Spring Boot 应用监控的问题

    这篇文章主要介绍了关于Prometheus + Spring Boot 应用监控的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-03-03
  • Java中的Native关键字讲解

    Java中的Native关键字讲解

    本文介绍了Java中的Native关键字,native关键字是架起本机语言和JAVA之间鸿沟的桥梁。如果我们的软件与硬件的交互在使用预先存在的代码时更有效,那么这可以作为一个关键环节。与从头开始设计新的应用程序代码相比,只要可以避免,它就可以使实现工作更少,下面来了解集体内容
    2021-12-12
  • SpringBoot配置多数据源的四种方式分享

    SpringBoot配置多数据源的四种方式分享

    在日常开发中我们都是以单个数据库进行开发,在小型项目中是完全能够满足需求的,但是,当我们牵扯到大型项目的时候,单个数据库就难以承受用户的CRUD操作,那么此时,我们就需要使用多个数据源进行读写分离的操作,本文就给大家介绍SpringBoot配置多数据源的方式
    2023-07-07
  • Java利用跳跃表解决双重队列问题详解

    Java利用跳跃表解决双重队列问题详解

    这篇文章主要为大家详细介绍了Java如何利用跳跃表来解决双重队列的问题。本文通过一个简单的例题进行了讲解,感兴趣的小伙伴可以了解一下
    2022-12-12
  • Mybatis参数(Parameters)传递方式

    Mybatis参数(Parameters)传递方式

    这篇文章主要介绍了Mybatis参数(Parameters)传递方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-12-12
  • 解决springboot配置logback-spring.xml不起作用问题

    解决springboot配置logback-spring.xml不起作用问题

    这篇文章主要介绍了解决springboot配置logback-spring.xml不起作用问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • Spring中RedisTemplate的基本使用浅析

    Spring中RedisTemplate的基本使用浅析

    Spring Boot Data(数据) Redis中提供了RedisTemplate和StringRedisTemplate,其中StringRedisTemplate是RedisTemplate的子类,两个方法基本一致。本文介绍了Spring操作Redis的方法,需要的可以参考一下
    2023-02-02
  • 浅谈线程通信wait,notify作用

    浅谈线程通信wait,notify作用

    这篇文章主要介绍了浅谈线程通信wait,notify作用,具有一定借鉴价值,需要的朋友可以参考下
    2017-12-12
  • 深入浅析Java 抽象类和接口

    深入浅析Java 抽象类和接口

    这篇文章主要介绍了Java 抽象类和接口的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • 什么是Spring Boot

    什么是Spring Boot

    Spring是一个非常受欢迎的Java框架,它用于构建web和企业应用。本文介绍将各种Spring的配置方式,帮助您了解配置Spring应用的复杂性
    2017-08-08

最新评论