前提:
項(xiàng)目中統(tǒng)一使用 HttpResponseCode 來(lái)作為服務(wù)正常的返回, body 中放具體返回的內(nèi)容.
如果拋出異常的情況下,期望 code 是4XX,body 中存放錯(cuò)誤信息給用戶友好提示
但是,在SpringCloud 中默認(rèn)的異常拋出是一個(gè)包含五個(gè)字段的對(duì)象.如下:
{
"timestamp": 1513303905953,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MissingServletRequestParameterException",
"message": "Required Integer parameter 'userId' is not present",
"path": "/info"
}
我們需要的是這樣一種情況的:

Screen Shot 2017-12-15 at 2.23.05 PM.png
接下來(lái)我們來(lái)實(shí)現(xiàn)這種情況.

Screen Shot 2017-12-15 at 2.45.26 PM.png
但是,重啟過(guò)后并沒(méi)有什么作用,忽然想到@ControllerAdvice 應(yīng)該是只處理到達(dá) Controller 中的請(qǐng)求才能被攔截到,而 filter 在 controller 之前,所以攔截不到.那么就要找其他方法來(lái)處理.
ZuulFilter 中的 FilterType 中有一個(gè) Error 的處理器.查找這方面資料StackOverflow,別人也遇到過(guò)這種情況需要同樣的處理.
解決方案如下:
- error 類型的 zuulFilter
- 執(zhí)行順序在默認(rèn)的 SendErrorFilter (index=0)之前,因此,我們?cè)O(shè)置為-1
- should 方法中檢查有沒(méi)有拋出異常
- run 方法中對(duì)異常進(jìn)行處理
代碼如下:
@Component
public class ErrorFilter extends ZuulFilter {
private final Logger log = LoggerFactory.getLogger(Http401UnauthorizedEntryPoint.class);
@Override
public String filterType() {
return "error";
}
@Override
public int filterOrder() {
//需要在默認(rèn)的 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
// 刪除該異常信息,不然在下一個(gè)過(guò)濾器中還會(huì)被執(zhí)行處理
ctx.remove("throwable");
// 根據(jù)具體的業(yè)務(wù)邏輯來(lái)處理
ctx.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());
}
} catch (Exception ex) {
log.error("Exception filtering in custom error filter", ex);
ReflectionUtils.rethrowRuntimeException(ex);
}
return null;
}
}
注意:可能是因?yàn)榘姹静煌? 上文鏈接解決方案中shoutFilter 中異常信息不一致,導(dǎo)致不能進(jìn)入處理