RESTful API错误处理
springBoot中默认的错误处理机制
- 浏览器发出的请求,若发生错误,则重定向为/error,进入BasicErrorController的errorHtml方法处理
@Controller @RequestMapping("${server.error.path:${error.path:/error}}") public class BasicErrorController extends AbstractErrorController { @RequestMapping(produces = "text/html")//产生html类型的数据;浏览器发送的请求来到这个方法处理 public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) { HttpStatus status = getStatus(request); Map<String, Object> model = Collections.unmodifiableMap(getErrorAttributes( request, isIncludeStackTrace(request, MediaType.TEXT_HTML))); response.setStatus(status.value()); //去哪个页面作为错误页面;包含页面地址和页面内容 ModelAndView modelAndView = resolveErrorView(request, response, status, model); return (modelAndView == null ? new ModelAndView("error", model) : modelAndView); }
- 非浏览器发出的请求,若发生错误,进入BasicErrorController的error方法处理
@RequestMapping @ResponseBody //产生json数据,其他客户端来到这个方法处理; public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) { Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL)); HttpStatus status = getStatus(request); return new ResponseEntity<Map<String, Object>>(body, status); }
自定义异常处理
如何定制浏览器请求发生错误时页面
有模板引擎的情况下:error/状态码;
【将错误页面命名为 错误状态码.html 放在模板引擎文件夹里面的error文件夹下】,发生此状态码的错误就会来到对应的页面;我们可以使用4xx和5xx作为错误页面的文件名来匹配这种类型的所有错误,精确优先(优先寻找精确的状态码.html);页面能获取的信息:
- timestamp:时间戳
- status:状态码
- error:错误提示
- exception:异常对象
- message:异常消息
- errors:JSR303数据校验的错误都在这里
没有模板引擎(模板引擎找不到这个错误页面),静态资源文件夹下找;
以上都没有错误页面,就是默认来到SpringBoot默认的错误提示页面;
如何定制请求错误时的json数据
自定义异常处理&返回定制json数据;
@ControllerAdvice public class MyExceptionHandler { @ExceptionHandler(UserNotExistException.class) @ResponseBody @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) public Map<String,Object> UserNotExistExceptionHandler(UserNotExistException ex){ HashMap<String, Object> result = new HashMap<>(); result.put("id", ex.getId()); result.put("message", ex.getMessage()); return result; } } //没有自适应效果...
转发到/error进行自适应响应效果处理
@ExceptionHandler(UserNotExistException.class) public String UserNotExistExceptionHandler(UserNotExistException ex, HttpServletRequest request) { HashMap<String, Object> result = new HashMap<>(); result.put("id", ex.getId()); result.put("message", ex.getMessage()); //传入我们自己的错误状态码 4xx 5xx,否则就不会进入定制错误页面的解析流程 request.setAttribute("javax.servlet.error.status_code",500); return "forward:/error"; }
- 响应数据中添加定制属性
页面上能用的数据,或者是json返回能用的数据都是通过errorAttributes.getErrorAttributes得到 自定义ErrorAttributes:
//给容器中加入我们自己定义的ErrorAttributes @Component public class MyErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(RequestAttributes requestAttributes, boolean includeStackTrace) { Map<String, Object> map = super.getErrorAttributes(requestAttributes, includeStackTrace); map.put("company","dzg"); return map; } }
@GetMapping("/{id}") public void download(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) { try (InputStream ips = new FileInputStream(new File(folder, id + ".txt")); OutputStream ops = response.getOutputStream();) { response.setContentType("application/x-download"); response.setHeader("Content-Disposition", "attachment;filename=test.txt"); IOUtils.copy(ips, ops); ops.flush(); }catch (IOException e){ e.printStackTrace(); } }