SpringBoot實戰:SpringBoot之全局錯誤處理

應用軟件在實際開發和運行過程當中,總有這樣那樣的錯誤,若是每個接口的錯誤邏輯都讓本身處理,這樣顯然是很麻煩的,並且說不定還有漏捕獲的錯誤,這樣的接口顯然是不友好的,爲了讓接口只專一於處理業務的自己,SpringBoot提供了@ExceptionHandler註解來全局錯誤攔截處理。java

import com.wusy.demo.exception.BusinessException;
import com.wusy.demo.model.ResultObjectModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpStatus;
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.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.NoHandlerFoundException;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.HttpServletRequest;

/**
 * @author wusy
 * Company: xxxxxx科技有限公司
 * Createtime : 2020/2/28 22:04
 * Description : rest full 全局統一返回封裝
 */
@RestControllerAdvice
public class GlobalControllerAdvice implements ResponseBodyAdvice<Object> {

    private Logger logger = LoggerFactory.getLogger(GlobalControllerAdvice.class);

    /**
     * 判斷哪些須要攔截
     * @param returnType
     * @param converterType
     * @return
     */
    @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) {
        //若是返回的數據是ResultObjectModel、Byte類型則不進行封裝
        if( body instanceof ResultObjectModel || body instanceof Byte || body instanceof String) {
            return body;
        }
        return this.getWrapperResponse(request , body);
    }
    /**
     * 默認異常處理,返回500錯誤
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResultObjectModel<String> defaultExceptionHandler(HttpServletRequest req, Exception e) {
        return getExpResponse(req, e);
    }

    /**
     * 沒法找到映射handler的異常處理,返回404錯誤
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(NoHandlerFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResultObjectModel<String> noHandlerFoundExceptionHandler(HttpServletRequest req, Exception e) {
        return getExpResponse(req, e);
    }

   
    /**
     * 異常信息返回
     * @param request
     * @param e
     * @return
     */
    private ResultObjectModel<String> getExpResponse(HttpServletRequest request, Exception e) {
        return new ResultObjectModel<>(false, e.getMessage() , null);
    }
    /**
     * 返回正常的信息
     * @param request
     * @param data
     * @return
     */
    private ResultObjectModel<Object> getWrapperResponse(ServerHttpRequest request, Object data) {
        return new ResultObjectModel<>(true, "請求成功" , data);
    }
}
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wusy
 * Company: xxxxxx科技有限公司
 * Createtime : 2020/2/24 21:54
 * Description :
 */
@RestController
@RequestMapping("/api/demo")
public class HelloWorldController {
    
    @RequestMapping(value = "/exception", method = RequestMethod.GET)
    public void exception() throws Exception  {
        throw new Exception("這是錯誤的接口");
    }

}

運行應用,打開瀏覽器,在地址欄輸入http://127.0.0.1:8787/api/demo/exception,觀察結果web

從結果看出,全局錯誤的配置起做用了。一般爲了寫業務方便會自定義一些錯誤類。spring

import lombok.Getter;
import lombok.Setter;

/**
 * @author wusy
 * Company: xxxxxx科技有限公司
 * Createtime : 2020/3/2 21:44
 * Description :
 */
@Getter
@Setter
public class BusinessException extends RuntimeException {

    private String message;

    private Object data;

    public BusinessException(String message) {
        super(message);
        this.message = message;
    }

    public BusinessException(String message ,Object data) {
        super(message);
        this.message = message;
        this.data = data;
    }

}

全局錯誤添加自定義錯誤處理api

/**
 * 業務層異常
 * @param request
 * @param e
 * @return
 */
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.OK)
public ResultObjectModel<Object> businessExceptionHandler(HttpServletRequest request, Exception e) {
    BusinessException ex = (BusinessException)e;
    // 記錄錯誤信息
    logger.info((request.getRequestURI().replaceAll("[\r\n]",""))+", message : ["+ e.getMessage().replaceAll("[\r\n]","")+"]");
    return new ResultObjectModel(true , ex.getMessage(),ex.getData());
}

修改rest full接口類瀏覽器

import com.wusy.demo.exception.BusinessException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author wusy
 * Company: xxxxxx科技有限公司
 * Createtime : 2020/2/24 21:54
 * Description :
 */
@RestController
@RequestMapping("/api/demo")
public class HelloWorldController {

    @RequestMapping(value = "/exception", method = RequestMethod.GET)
    public void exception() throws Exception  {
        throw new BusinessException("這是自定義錯誤的接口");
    }

}

運行應用,打開瀏覽器,在地址欄輸入http://127.0.0.1:8787/api/demo/exception,觀察結果mvc

觀察後臺日誌能夠看到app

至此全局錯誤攔截配置演示結束ide

相關文章
相關標籤/搜索