美文网首页springboot安全收集
Springboot全局异常与全局响应

Springboot全局异常与全局响应

作者: jackcooper | 来源:发表于2019-11-08 16:30 被阅读0次

    1.全局异常

    将返回值统一封装时我们没有考虑当接口抛出异常的情况。当接口抛出异常时让用户直接看到服务端的异常肯定是不够友好的,而我们也不可能每一个接口都去try/catch进行处理,此时只需要使用@ExceptionHandler注解即可无感知的全局统一处理异常。

    
    import com.chehejia.framework.beans.exception.BizException;
    import com.chehejia.framework.beans.model.Response;
    import com.saos.wo.consts.StatusCode;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang.exception.ExceptionUtils;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @author jack-cooper
     * @version 1.0.0
     * @ClassName GlobalExceptionHandler.java
     * @Description 全局异常处理器
     * @createTime 2019年11月01日 09:08:00
     */
    @Slf4j
    @RestController
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(value = Exception.class)
    @ResponseBody
        public Response defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
            log.error("---BaseException Handler---Host {} invokes url {} ERROR: ",req.getRemoteHost(),req.getRequestURL(),e);
            return Response.fail(StatusCode.SYS_SERVICE_ERROR.getCode(), ExceptionUtils.getFullStackTrace(e));
        }
    
        @ExceptionHandler(value = BizException.class)
    @ResponseBody
        public Response jsonErrorHandle(HttpServletRequest req, BizException e) {
            log.warn("---BaseException Handler---Host {} invokes url {}  ",req.getRemoteHost(),req.getRequestURL());
            return Response.fail(e.getCode(),e.getMessage());
        }
    
    }
    

    2.全局响应

    在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。下面通过实现SpringBoot中为我们提供好的解决方法,只需要在项目中加上一下代码,即可实现相关功能。主要是实现接口ResponseBodyAdvice

    
    import com.chehejia.framework.beans.model.Response;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.MethodParameter;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.http.server.ServerHttpRequest;
    import org.springframework.http.server.ServerHttpResponse;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
    
    
    /**
     * @author jack-cooper
     * @version 1.0.0
     * @ClassName GlobalReturnConfig.java
     * @Description 全局返回统一封装
     * @createTime 2019年11月08日 15:51:00
     */
    @EnableWebMvc
    @Configuration
    @RestControllerAdvice
    public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
    
        @Override
        public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
            return true;
        }
    
        @Override
        public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
            if (body instanceof Response) {
                return body;
            } else {
                return Response.success(body);
            }
        }
    }
    

    3.统一返回对象

    
    import com.chehejia.framework.beans.exception.BizException;
    import com.chehejia.framework.beans.exception.BizRuntimeException;
    import io.swagger.annotations.ApiModel;
    import io.swagger.annotations.ApiModelProperty;
    import lombok.*;
    
    import java.io.Serializable;
    import java.util.Optional;
    import java.util.function.Supplier;
    
    
    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    @Builder
    @ApiModel("统一返回")
    public class Response<T> implements Serializable {
    
        private static final long serialVersionUID = -6724401478874316373L;
    
        public static <T> Response<T> success() {
            return Response.success(RestfulCode.SUCCESS, null, null);
        }
    
        public static <T> Response<T> success(T data) {
            return Response.success(RestfulCode.SUCCESS, null, data);
        }
    
        public static <T> Response<T> success(RestfulCode rc, T data) {
            return Response.success(rc, null, data);
        }
    
        public static <T> Response<T> success(RestfulCode rc, String msg, T data) {
            return Response.<T>builder()
                    .code(rc.getCode())
                    .msg(Optional.ofNullable(msg).orElse(rc.getMessage()))
                    .data(data)
                    .build();
        }
    
        public static <T> Response<T> fail(BizException e) {
            return Response.<T>builder()
                    .code(e.getCode())
                    .msg(e.getMessage())
                    .build();
        }
    
        public static <T> Response<T> fail(BizRuntimeException e) {
            return Response.<T>builder()
                    .code(e.getCode())
                    .msg(e.getMessage())
                    .build();
        }
    
        public static <T> Response<T> fail(Integer code, String msg) {
            return Response.<T>builder()
                    .code(code)
                    .msg(msg)
                    .build();
        }
    
        public static <T> Response<T> fail(RestfulCode rs) {
            return Response.<T>builder()
                    .code(rs.getCode())
                    .msg(rs.getMessage())
                    .build();
        }
    
        public static <T> Response<T> fail(Integer code, String msg, T data) {
            return Response.<T>builder()
                    .code(code)
                    .msg(msg)
                    .data(data)
                    .build();
        }
    
        public static <T> Response<T> fail(RestfulCode rs, T data) {
            return Response.<T>builder()
                    .code(rs.getCode())
                    .msg(rs.getMessage())
                    .data(data)
                    .build();
        }
    
        public static <T> Response<T> fail(Response source) {
            return Response.<T>builder()
                    .code(source.getCode())
                    .msg(source.getMsg())
                    .build();
        }
    
        /**
         * 判断返回码是否相同,与是否成功无关
         *
         * @param restfulCode
         *
         * @return
         */
        public boolean codeEquals(RestfulCode restfulCode) {
            if (this.getCode() == null || restfulCode == null) {
                return false;
            }
            return this.getCode().equals(restfulCode.getCode());
        }
    
        /**
         * 如果成功则返回data,失败则抛出异常
         * @return data
         * @throws BizRuntimeException 失败抛出
         */
        public T orFailThrow() throws BizRuntimeException {
            if (isSuccess()) {
                return getData();
            } else {
                throw new BizRuntimeException(getCode(), getMsg());
            }
        }
    
        public <X extends Throwable> T orFailThrow(Supplier<? extends X> supplier) throws X {
            if (isSuccess()) {
                return getData();
            } else {
                throw supplier.get();
            }
        }
    
        /**
         * 期望有data
         * @return data
         * @throws BizRuntimeException 失败或data为null 抛出异常
         */
        public T forceData(RestfulCode error) throws BizRuntimeException {
            return Optional.ofNullable(orFailThrow()).orElseThrow(() -> new BizRuntimeException(error));
        }
    
        public boolean isSuccess() {
            return RestfulCode.SUCCESS.isEquals(getCode());
        }
    
        /**
         * 状态码
         */
        @ApiModelProperty("状态码")
        private Integer code = RestfulCode.SUCCESS.getCode();
    
        /**
         * 描述信息
         */
        @ApiModelProperty("描述信息")
        private String msg = RestfulCode.SUCCESS.getMessage();
    
        /**
         * 返回数据
         */
        @ApiModelProperty("返回数据")
        private T data;
    }
    
    

    相关文章

      网友评论

        本文标题:Springboot全局异常与全局响应

        本文链接:https://www.haomeiwen.com/subject/pxkwbctx.html