如前面的文章所述,controller中拋出的異常我們使用ControllerAdvice來處理:
@RestControllerAdvice @Slf4j public class GlobalExceptionHandler { @ExceptionHandler(value = Exception.class) public AjaxResponse handler(Exception e){ AjaxResponse r = new AjaxResponse(); if (e instanceof RuntimeException){ RuntimeException selectNoFindException = (RuntimeException) e; r.setStatus(-1); r.setMsg(selectNoFindException.getMessage()); } else { r.setStatus(-1); r.setMsg("系統錯誤"); } log.error(e.getMessage()); return r; } /** * 捕獲自定義異常 * @param e * @return */ @ExceptionHandler(value = FriendlyException.class) public Map<String,Object> errorHandle(FriendlyException e){ Map<String,Object> map = new HashMap<String,Object>(); map.put("code",e.getCode()); map.put("msg",e.getMsg()); return map; } }
但是filter中拋出的異常上面的方法就為無能為力了,如登錄的認證,和權限的判斷,我們可以使用如下的處理方法:
定義一個controller 繼承BasicErrorController,並重寫error方法。
@RestController @Api(value = "handle filter throws exception", description = "處理filter拋出的異常") public class ErrorController extends BasicErrorController { public ErrorController() { super(new DefaultErrorAttributes(), new ErrorProperties()); } @Override @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE}) public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); Map<String,Object> map = new HashMap<String,Object>(); map.put("code",body.get("status")); map.put("msg",body.get("message")); return new ResponseEntity<Map<String, Object>>(map, status); } }
看下request中的信息:
看一下body中的信息:
接下來就可以filter中拋出異常,errorcontroller就可以捕獲了:
以下是shiro中認證失敗時方法onAccessDenied:
protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { HttpServletResponse httpResponse = WebUtils.toHttp(servletResponse); httpResponse.setCharacterEncoding("UTF-8"); httpResponse.setContentType("application/json;charset=UTF-8"); httpResponse.setStatus(HttpStatus.SC_NON_AUTHORITATIVE_INFORMATION); fillCorsHeader(WebUtils.toHttp(servletRequest), httpResponse); throw new AuthenticationException("token認證失敗"); //return false; }
以下是權限判斷時,權限不足時拋出的異常在isAccessAllowed方法中。
protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object mappedValue) throws Exception { Subject subject = getSubject(servletRequest, servletResponse); String[] rolesArray = (String[]) mappedValue; //沒有角色限制,有權限訪問 if (rolesArray == null || rolesArray.length == 0) { return true; } for (String role : rolesArray) { //若當前用戶是rolesArray中的任何一個,則有權限訪問 if (subject.hasRole(role)) { return true; } } throw new AuthorizationException("沒有權限訪問此資源"); }
這里isAccessAllowed和onAccessDenied應該在哪個方法拋出異常呢,我沒有考慮太多,都試了一下,有機會時再研究一下