详解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 封装返回的资料请关注脚本之家其它相关文章!

相关文章

  • Java定时器Timer与TimerTask的使用详解

    Java定时器Timer与TimerTask的使用详解

    这篇文章主要介绍了Java定时器Timer与TimerTask的使用详解,在JDK类库中Timer主要负责计划任务的功能,也就是在指定时间执行某一任务,执行时候会在主线程之外起一个单独的线程执行指定的任务,该类主要是设置任务计划,但封装的类是TimerTask类,需要的朋友可以参考下
    2023-10-10
  • 23种设计模式(19)java责任链模式

    23种设计模式(19)java责任链模式

    这篇文章主要为大家详细介绍了23种设计模式之java责任链模式,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-01-01
  • 如何修改覆盖spring boot默认日志策略logback详解

    如何修改覆盖spring boot默认日志策略logback详解

    这篇文章主要给大家介绍了关于如何修改覆盖spring boot默认日志策略logback的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-10-10
  • Mybatis调用Oracle存储过程的方法图文详解

    Mybatis调用Oracle存储过程的方法图文详解

    这篇文章主要介绍了Mybatis调用Oracle存储过程的方法介绍,需要的朋友可以参考下
    2017-09-09
  • java多线程之定时器Timer的使用详解

    java多线程之定时器Timer的使用详解

    本篇文章主要介绍了java多线程之定时器Timer的使用详解,Time类主要负责完成定时计划任务的功能,有兴趣的可以了解一下。
    2017-04-04
  • java发起http请求调用post与get接口的方法实例

    java发起http请求调用post与get接口的方法实例

    在实际开发过程中,我们经常需要调用对方提供的接口或测试自己写的接口是否合适,下面这篇文章主要给大家介绍了关于java发起http请求调用post与get接口的相关资料,需要的朋友可以参考下
    2022-08-08
  • java.lang.OutOfMemoryError: Java heap space错误的问题解决

    java.lang.OutOfMemoryError: Java heap space错误

    本文主要介绍了java.lang.OutOfMemoryError: Java heap space错误的问题解决,包括内存泄漏、数据过大和JVM堆大小配置不足,提供了解决方法,具有一定的参考价值,感兴趣的可以了解一下
    2025-03-03
  • Java中如何获取文件的上级目录

    Java中如何获取文件的上级目录

    这篇文章主要介绍了Java中如何获取文件的上级目录问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-12-12
  • java启动命令中-D和--的区别解析

    java启动命令中-D和--的区别解析

    在 SpringBoot 项目中,启动时,通过 -D 或 -- 添加参数,都可以直接覆盖 yml 或 properties 配置文件中的同名配置,如果不存在则相当于添加了一个配置,这篇文章主要介绍了java启动命令中-D和--的区别,需要的朋友可以参考下
    2024-08-08
  • java数组、泛型、集合在多态中的使用及对比

    java数组、泛型、集合在多态中的使用及对比

    本文主要介绍了java数组、泛型、集合在多态中的使用及对比。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-03-03

最新评论