如前面的文章所述,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应该在哪个方法抛出异常呢,我没有考虑太多,都试了一下,有机会时再研究一下