溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Spring?Boot統(tǒng)一接口返回及全局異常處理的方法

發(fā)布時(shí)間:2022-04-21 10:19:47 來源:億速云 閱讀:220 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要講解了“Spring Boot統(tǒng)一接口返回及全局異常處理的方法”,文中的講解內(nèi)容簡單清晰,易于學(xué)習(xí)與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學(xué)習(xí)“Spring Boot統(tǒng)一接口返回及全局異常處理的方法”吧!

    1、解決方案

    Spring?Boot統(tǒng)一接口返回及全局異常處理的方法

    定義公共模塊,實(shí)現(xiàn)統(tǒng)一接口定義規(guī)范和異常處理,其他的系統(tǒng)進(jìn)行依賴和擴(kuò)展即可。

    2、具體實(shí)現(xiàn)

    2.1 定義狀態(tài)碼統(tǒng)一接口

    public interface BaseResultCode
    {
        /**
         * 狀態(tài)碼
         * @return
         */
        int getCode();
        /**
         * 提示信息
         * @return
         */
        String getMsg();
    }

    2.2 公共模塊狀態(tài)碼枚舉類

    public enum ResultCode implements BaseResultCode
    {
        OK(200, "成功"),
        ERROR(300,"系統(tǒng)異常"), 
        NEED_AUTH(301, "非法請求,請重新登錄"), 
        PARAMTER_ERROR(302, "參數(shù)錯(cuò)誤");
        //省略其他定義錯(cuò)誤碼
        private int code;
        private String msg;
        private ResultCode(int code, String msg)
        {
            this.code = code;
            this.msg = msg;
        }
        public static ResultCode getValue(int code)
        {
            for (ResultCode errorCode : values())
            {
                if (errorCode.getCode() == code)
                {
                    return errorCode;
                }
            }
            return null;
        }
       //省略Get、Set方法
     }

    2.3 定義全局自定義異常

    public class SysException extends RuntimeException
    {
        private static final long serialVersionUID = 5225171867523879342L;
        private int code;
        private String msg;
        private Object[] params;
        private BaseResultCode errorCode;
        public SysException()
        {
            super();
        }
        public SysException(String message)
        {
            super(message);
        }
        public SysException(Throwable cause)
        {
            super(cause);
        }
        public SysException(int code ,String message)
        {
            this.code = code;
            this.msg = message;
        }
        public SysException(int code ,String message,  Object[] params)
        {
            this(code, message);
            this.params= params;
        }
        public SysException(String message, Throwable cause)
        {
            super(message, cause);
        }
        public SysException(BaseResultCode errorCode)
        {
            this.errorCode = errorCode;
        }
        public SysException(String message, Object[] params)
        {
            super(message);
            this.params = params;
        }
        public SysException(BaseResultCode errorCode, String message, Object[] params)
        {
            this(message, params);
            this.errorCode = errorCode;
        }
        
        /**
         * Construct by default
         * 
         * @param message
         *            message
         * @param parameters
         *            parameters
         * @param cause
         *            cause
         */
        public SysException(String message, Object[] params, Throwable cause)
        {
            super(message, cause);
            this.params = params;
        }
    
        public int getCode()
        {
            return code;
        }
        public void setCode(int code)
        {
            this.code = code;
        }
        public String getMsg()
        {
            return msg;
        }
        public void setMsg(String msg)
        {
            this.msg = msg;
        }
        /**
         * @return the params
         */
        public Object[] getParams()
        {
            return params;
        }
        /**
         * @param params
         *            the params to set
         */
        public void setParams(Object[] params)
        {
            this.params = params;
        }
        public BaseResultCode getErrorCode()
        {
            return errorCode;
        }
        public void setErrorCode(BaseResultCode errorCode)
        {
            this.errorCode = errorCode;
        }
        
    }

    2.4 定義統(tǒng)一接口格式輸出類

    public class Result implements Serializable
    {
        private static final long serialVersionUID = -1773941471021475043L;
        private Object data;
        private int code;
        private String msg;
        public Result()
        {
        }
        public Result(int code, Object data, String msg)
        {
            this.code = code;
            this.data = data;
            this.msg = msg;
        }
        public Result(int code, String desc)
        {
            this(code, null, desc);
        }
        public Result(BaseResultCode errorCode)
        {
            this(errorCode.getCode(), null, errorCode.getMsg());
        }
        public static Result success()
        {
            return success(null);
        }
        public static Result success(Object data)
        {
            Result result = new Result();
            result.setData(data);
            result.setCode(ResultCode.OK.getCode());
            return result;
        }
        public static Result error(String msg)
        {
            Result result = new Result();
            result.setCode(ResultCode.ERROR.getCode());
            result.setMsg(msg);
            return result;
        }
        public static Result error(BaseResultCode baseCode)
        {
            Result result = new Result();
            result.setCode(baseCode.getCode());
            result.setMsg(baseCode.getMsg());
            return result;
        }
    }

    個(gè)人建議:統(tǒng)一接口輸出類不要定義為泛型類型

    2.5 定義統(tǒng)一接口格式輸出類

    @RestControllerAdvice
    public class SysExceptionHandler
    {
        public static Log logger = LogManager.getLogger(SysExceptionHandler.class);
        @ExceptionHandler(Exception.class)
        public Result handleException(HttpServletRequest request,
                Exception ex)
        {
            logger.error("Handle Exception Request Url:{},Exception:{}",request.getRequestURL(),ex);
            Result result = new Result();
            //系統(tǒng)異常
            if (ex instanceof SysException)
            {
                SysException se = (SysException) ex;
                BaseResultCode resultCode =se.getErrorCode();
                if(resultCode==null)
                {
                    result = Result.error(se.getMessage());
                }
                else
                {
                   result = new Result(resultCode.getCode(),
                                           StringUtil.isNotEmpty(se.getMessage())?se.getMessage():resultCode.getMsg());
                }
            }
            //參數(shù)錯(cuò)誤
            else if (ex instanceof ConstraintViolationException)
            {
                ConstraintViolationException v = (ConstraintViolationException) ex;
                String message = v.getConstraintViolations().iterator().next()
                        .getMessage();
                result.setCode(ResultCode.PARAMTER_ERROR.getCode());
                result.setMsg(ResultCode.PARAMTER_ERROR.getMsg() + ":" + message);
            }
            //參數(shù)錯(cuò)誤
            else if (ex instanceof BindException)
            {
                BindException v = (BindException) ex;
                String message = v.getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));
                result.setCode(ResultCode.PARAMTER_ERROR.getCode());
                result.setMsg(ResultCode.PARAMTER_ERROR.getMsg() + ":" + message);
            }
            //參數(shù)錯(cuò)誤
            else if (ex instanceof MethodArgumentNotValidException)
            {
                MethodArgumentNotValidException v = (MethodArgumentNotValidException) ex;
                String message = v.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.joining(","));
                result.setCode(ResultCode.PARAMTER_ERROR.getCode());
                result.setMsg(ResultCode.PARAMTER_ERROR.getMsg() + ":" + message);
            }
            else
            {
               result = new Result(ResultCode.ERROR.getCode(),ExceptionUtil.getErrorMsg(ex));
            }
            logger.info("exception handle reuslt:" + result);
            return result;
        }
    }

    上述定義已經(jīng)可以實(shí)現(xiàn)全局接口和異常的統(tǒng)一處理,但是存在的如下問題

    每個(gè)controller都需要返回Reesult類型,且每個(gè)方法都需要返回Result.success()或者Result.success(data)的結(jié)果,有點(diǎn)重復(fù),需要進(jìn)行優(yōu)化。

        @GetMapping("addUser")
        public Result add()
        {
           for(int i=0;i<10;i++)
           {
               TUser user = new TUser();
               //user.setOid(IdWorker.getId());
               user.setName("shareing_"+i);
               user.setAge(i);
               userService.addUser(user);
           }
           return Result.success();
        }

    2.6 接口統(tǒng)一輸出優(yōu)化

    實(shí)現(xiàn)方式只需要實(shí)現(xiàn)ResponseBodyAdvice接口,重寫beforeBodyWrite方法接口。

    @RestControllerAdvice
    public class ResponseAdvice implements ResponseBodyAdvice<Object>
    {
        private Logger logger = LoggerFactory.getLogger(ResponseAdvice.class);
        @Override
        public boolean supports(MethodParameter returnType,
                Class<? extends HttpMessageConverter<?>> converterType)
        {
            return true;
        }
        @Override
        public Object beforeBodyWrite(Object o, MethodParameter returnType,
                MediaType selectedContentType,
                Class<? extends HttpMessageConverter<?>> selectedConverterType,
                ServerHttpRequest request, ServerHttpResponse response)
        {
            logger.info("before body write param:{}",o);
            if(o instanceof String)
            {
               //序列化結(jié)果輸出
               return FastJsonUtil.toJSONString(Result.success(o));
            }
            else if (o instanceof Result)
            {
                 return o;
            }
            return Result.success(o);
        }
    }

    經(jīng)過優(yōu)化后,controller輸出可以根據(jù)業(yè)務(wù)的需求定義輸出對象。

     @GetMapping("getUserByName")
        public TUser getUserByName1(@RequestParam String name)
        {
           logger.info("getUserByName paramter name:"+name);
           return userService.getUserByName(name); 
        }

    2.7 子系統(tǒng)如何實(shí)現(xiàn)

    子系統(tǒng)引入common的jar包,

      <dependency>
    	    <groupId>com.xx</groupId>
    	    <artifactId>xx-common</artifactId>
    	    <version>2.0</version>
    	</dependency>

    3、子系統(tǒng)定義狀態(tài)碼,實(shí)現(xiàn)BaseResultCode接口

     public enum OrderModelErrorCode implements BaseResultCode
    {
        ORDER_STATUS_ERROR(1000, "訂單狀態(tài)不正確");
        private int code;
        private String msg;
        private UserModelErrorCode(int code, String msg)
        {
            this.code = code;
            this.msg = msg;
        }
        @Override
        public int getCode()
        {
            return code;
        }
        @Override
        public String getMsg()
        {
            return msg;
        }
    }

    定義異常處理類,繼承公共異常處理類SysExceptionHandler

    @RestControllerAdvice
    public class OrderModalExceptionHandle extends SysExceptionHandler
    {
         @Override
        public Result handleException(HttpServletRequest request, Exception ex)
        {
            return super.handleException(request, ex);
            //子系統(tǒng)可以擴(kuò)展異常處理
        }
    }

    子系統(tǒng)使用示例:

    @Override
    public Order getOrder(String orderId)
    {
    	Order order =getOrder(orderId);
            //相關(guān)偽代碼
    	if(order.getStatus()>120)
    	{
    	   throw new SysException(OrderModelErrorCode.ORDER_STATUS_ERROR);    
    	}
    	return order;
    }

    感謝各位的閱讀,以上就是“Spring Boot統(tǒng)一接口返回及全局異常處理的方法”的內(nèi)容了,經(jīng)過本文的學(xué)習(xí)后,相信大家對Spring Boot統(tǒng)一接口返回及全局異常處理的方法這一問題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識點(diǎn)的文章,歡迎關(guān)注!

    向AI問一下細(xì)節(jié)

    免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

    AI