29.Spring Boot中異常處理與REST格式處理

我在項目中是想作純粹的先後端分離的,全部數據都經過接口來返回,那麼在這個過程勢必須要解決兩個問題,一是對異常的處理還有一個就是當出現404這樣的錯誤的時候我也須要把這個異常封裝成json的格式給到前端,我在網上找的一個博客見連接在項目中使用SpringMVC全局異常處理,這篇文章其實已經能很好的處理一些自定義的異常與系統出現的一些404等異常,可是仍是有點不大夠的,主要是在返回的json格式上,當出現404的時候其實這個時候咱們也仍是想有一個data這樣的字段在其中,只不過是在返回的字段中succes是false或者是爲1這樣的一個字段,也就是以下所示 異常數據的格式 前端

異常404的格式
正常數據的格式
返回正常數據的格式
那麼在前一篇文章中那樣我感受仍是不大夠的須要進行補充一下

1.修改ErrorDTO

把原博客中的ErrorDTO修改爲JsonDTO須要作的就是在JsonDTO中增長一個success跟data屬性,那麼在每一個接口中我返回數據的時候我就返回這個JsonDTO回去java

package com.gz.whblog.utils;

public class JsonDTO {
    
    private boolean success;
    private int msgcode;
    private String msg;
    private Object data;

    public boolean isSuccess() {
        return success;
    }

    public void setSuccess(boolean success) {
        this.success = success;
    }

    public int getMsgcode() {
        return msgcode;
    }

    public void setMsgcode(int msgcode) {
        this.msgcode = msgcode;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public JsonDTO(){

    }

    public JsonDTO(boolean success,int msgcode,String msg,Object data){
        super();
        this.success = success;
        this.msgcode = msgcode;
        this.msg = msg;
        this.data = data;
    }

}
複製代碼

請注意這裏的data是使用object來修飾的,我無論你增刪改查返回的數據是ArrayList仍是字典仍是什麼東西我都能給你存git

2.CustomRestExceptionHandler的改寫

package com.gz.whblog.utils;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import java.util.ArrayList;

/**
* @description: 用來監聽處理全局異常
*
* @return: 
**/

@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {

//    處理自定義異常
    @ExceptionHandler(CustomException.class)
    public ResponseEntity<Object> handleCustomerException(CustomException ex){
        final JsonDTO customeJsonDTD = new JsonDTO(false,ex.getMsgCode(),ex.getLocalizedMessage(),new ArrayList<>());
        return new ResponseEntity<Object>(customeJsonDTD,new HttpHeaders(),ex.getHttpStatus());
    }

//    處理通用異常,這裏舉例說明如何覆蓋處理 請求方法不支持的異類
    @Override
    protected  ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        final JsonDTO customeJsonDTD = new JsonDTO(false,status.value(),"httpRequestMethodNotSupported",new ArrayList<>());
        System.out.println("我是全局處理請求方法不支持方法");
        return new ResponseEntity<Object>(customeJsonDTD,new HttpHeaders(),status);
    }

//    重寫系統的404方法
    @Override
    protected ResponseEntity<Object> handleNoHandlerFoundException(NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        final JsonDTO customeJsonDTD = new JsonDTO(false,status.value(),"NoHandlerFoundException",new ArrayList<>());
        System.out.println("我是全局處理404異常方法");
        return new ResponseEntity<Object>(customeJsonDTD,new HttpHeaders(),status);
    }
}
複製代碼

在自定義異常的方法中,若是遇到異常在data部分返回data部分就是一個空的list,固然這裏返回的data也能夠你去寫null,可是我認爲在這個地方寫一個返回的空數組更好github

  • 1.是你在調用自定義異常的時候也能夠不要去管這個data部分的值了;
  • 2.是前端拿到這個data值不要去處理爲null的一些異常問題 另外在這個地方,須要注意的是這裏對系統出現的異常代碼像,我才重寫了404跟405兩個問題,若是你要處理500的問題,那你是須要再次重寫的,你可能會說這我怎麼知道要重寫多少方法?不要緊這是很容易找到的 點擊ResponseEntityExceptionHandler進去查看源碼
    這裏就是一些異常類
    如下就是能夠重寫的一些方法
protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
			HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		pageNotFoundLogger.warn(ex.getMessage());

		Set<HttpMethod> supportedMethods = ex.getSupportedHttpMethods();
		if (!CollectionUtils.isEmpty(supportedMethods)) {
			headers.setAllow(supportedMethods);
		}
		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(
			HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		List<MediaType> mediaTypes = ex.getSupportedMediaTypes();
		if (!CollectionUtils.isEmpty(mediaTypes)) {
			headers.setAccept(mediaTypes);
		}

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleHttpMediaTypeNotAcceptable(
			HttpMediaTypeNotAcceptableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}

	protected ResponseEntity<Object> handleMissingPathVariable(
			MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleMissingServletRequestParameter(
			MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleServletRequestBindingException(
			ServletRequestBindingException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleConversionNotSupported(
			ConversionNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleTypeMismatch(
			TypeMismatchException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleHttpMessageNotReadable(
			HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleHttpMessageNotWritable(
			HttpMessageNotWritableException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleMethodArgumentNotValid(
			MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleMissingServletRequestPart(
			MissingServletRequestPartException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleBindException(
			BindException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
protected ResponseEntity<Object> handleNoHandlerFoundException(
			NoHandlerFoundException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {

		return handleExceptionInternal(ex, null, headers, status, request);
	}
複製代碼
@Nullable
	protected ResponseEntity<Object> handleAsyncRequestTimeoutException(
			AsyncRequestTimeoutException ex, HttpHeaders headers, HttpStatus status, WebRequest webRequest) {

		if (webRequest instanceof ServletWebRequest) {
			ServletWebRequest servletWebRequest = (ServletWebRequest) webRequest;
			HttpServletResponse response = servletWebRequest.getResponse();
			if (response != null && response.isCommitted()) {
				if (logger.isWarnEnabled()) {
					logger.warn("Async request timed out");
				}
				return null;
			}
		}

		return handleExceptionInternal(ex, null, headers, status, webRequest);
	}
複製代碼
protected ResponseEntity<Object> handleExceptionInternal(
			Exception ex, @Nullable Object body, HttpHeaders headers, HttpStatus status, WebRequest request) {

		if (HttpStatus.INTERNAL_SERVER_ERROR.equals(status)) {
			request.setAttribute(WebUtils.ERROR_EXCEPTION_ATTRIBUTE, ex, WebRequest.SCOPE_REQUEST);
		}
		return new ResponseEntity<>(body, headers, status);
	}
複製代碼

至於以爲過多嫌麻煩的話,我也不知作別人高手是怎麼處理的,我目前的一些方法就是挨個這樣重寫了web

3.自定義異常CustomException

package com.gz.whblog.utils;

import org.springframework.http.HttpStatus;

/**
* @description: 自定義異常類
*
* @return: 
**/
public class CustomException extends RuntimeException {

    private HttpStatus httpStatus;

    private int msgCode;
    public CustomException(HttpStatus httpStatus,int msgCode,String message){
        super(message);
        this.httpStatus = httpStatus;
        this.msgCode = msgCode;
    }

    public CustomException(String message,int errorCode,Exception e){
        super(message,e.getCause());
    }

    public HttpStatus getHttpStatus() {
        return httpStatus;
    }

    public void setHttpStatus(HttpStatus httpStatus) {
        this.httpStatus = httpStatus;
    }

    public int getMsgCode() {
        return msgCode;
    }

    public void setMsgCode(int msgCode) {
        this.msgCode = msgCode;
    }
    
}
複製代碼

4.異常狀態碼枚舉類ExceptionEnum

package com.gz.whblog.utils;

import org.springframework.http.HttpStatus;

/**
* @description: 異常枚舉類
*
* @return: 
**/
public enum  ExceptionEnum {

//    跟數據庫CRUD有關的一些自定義代碼
    ADD_DATA_SUCCESS(20000,"操做成功",HttpStatus.OK),
    QUERARY_DATA_SUCCESS(20001,"查詢成功",HttpStatus.OK),
    INSERT_DATA_SUCCESS(20002,"插入成功",HttpStatus.OK),
    UPDATE_DATA_SUCCESS(20003,"更新數據成功",HttpStatus.OK),
    DELETE_DATA_SUCCESS(20004,"刪除數據成功",HttpStatus.OK),

//    用戶登陸有關的一些自定義代碼
    LOGIN_USER_SUCCESS(10000,"登陸成功",HttpStatus.OK),
    LOGIN_USERNAME_ERROR(10001,"用戶名錯誤",HttpStatus.BAD_REQUEST),
    LOGIN_PASSWORD_ERROR(10002,"登陸密碼錯誤",HttpStatus.BAD_REQUEST),
    LOGIN_VERIFICODE_ERROR(10003,"驗證碼錯誤",HttpStatus.BAD_REQUEST),
    LOGIN_TELEPHONE_ERROR(10004,"手機號錯誤",HttpStatus.BAD_REQUEST),

    ;

    private int msgcode;
    private String msgdesc;
    private HttpStatus httpStatus;


    ExceptionEnum(int msgcode, String msgdesc, HttpStatus status) {
        this.msgcode = msgcode;
        this.msgdesc = msgdesc;
        this.httpStatus = status;
    }

    public int getMsgcode() {
        return msgcode;
    }

    public void setMsgcode(int msgcode) {
        this.msgcode = msgcode;
    }

    public String getMsgdesc() {
        return msgdesc;
    }

    public void setMsgdesc(String msgdesc) {
        this.msgdesc = msgdesc;
    }

    public HttpStatus getHttpStatus() {
        return httpStatus;
    }

    public void setHttpStatus(HttpStatus httpStatus) {
        this.httpStatus = httpStatus;
    }
}
複製代碼

若是有其餘的一些操做還能夠繼續添加一些狀態碼的 Github同步更新我的學習筆記,若是這篇文章對你有好處點個星星你不虧 WiHongNoteBookspring

相關文章
相關標籤/搜索