自定義 ZuulFilter丟擲異常
阿新 • • 發佈:2018-11-10
前提:
專案中統一使用 HttpResponseCode 來作為服務正常的返回, body 中放具體返回的內容.
如果丟擲異常的情況下,期望 code 是4XX,body 中存放錯誤資訊給使用者友好提示
但是,在SpringCloud 中預設的異常丟擲是一個包含五個欄位的物件.如下:
{
"timestamp": 1513303905953,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException" ,
"message": "Required Integer parameter 'userId' is not present",
"path": "/info"
}
我們需要的是這樣一種情況的:
接下來我們來實現這種情況.
首先,第一個想到的是使用 @ControllerAdvice 來做全域性的異常攔截,對異常進行處理但是,重啟過後並沒有什麼作用,忽然想到@ControllerAdvice 應該是隻處理到達 Controller 中的請求才能被攔截到,而 filter 在 controller 之前,所以攔截不到.那麼就要找其他方法來處理.
ZuulFilter 中的 FilterType 中有一個 Error 的處理器.查詢這方面資料StackOverflow,別人也遇到過這種情況需要同樣的處理.
解決方案如下:
- error 型別的 zuulFilter
- 執行順序在預設的 SendErrorFilter (index=0)之前,因此,我們設定為-1
- should 方法中檢查有沒有丟擲異常
- run 方法中對異常進行處理
程式碼如下:
@Component
public class ErrorFilter extends ZuulFilter {
private final Logger log = LoggerFactory.getLogger(Http401UnauthorizedEntryPoint.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
//需要在預設的 SendErrorFilter 之前
return -1; // Needs to run before SendErrorFilter which has filterOrder == 0
}
@Override
public boolean shouldFilter() {
// only forward to errorPath if it hasn't been forwarded to already
return RequestContext.getCurrentContext().containsKey("throwable");
}
@Override
public Object run() {
try {
RequestContext ctx = RequestContext.getCurrentContext();
Object e = ctx.get("throwable");
if (e != null && e instanceof ZuulException) {
ZuulException zuulException = (ZuulException) e;
// Remove error code to prevent further error handling in follow up filters
// 刪除該異常資訊,不然在下一個過濾器中還會被執行處理
ctx.remove("throwable");
// 根據具體的業務邏輯來處理
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
} catch (Exception ex) {
log.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}
作者:羅曼蒂克
連結:https://www.jianshu.com/p/2de6290d7bf1
著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。