應用軟件在實際開發和運行過程當中,總有這樣那樣的錯誤,若是每個接口的錯誤邏輯都讓本身處理,這樣顯然是很麻煩的,並且說不定還有漏捕獲的錯誤,這樣的接口顯然是不友好的,爲了讓接口只專一於處理業務的自己,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