SpringMVC 三种异常处理方式
springmvc 三种异常处理方式
在 springmvc, springboot 处理 web 请求时, 若遇到错误或者异常,返回给用户一个良好的错误信息比 whitelabel error page 好的多。 springmvc 提供了三种异常处理方式, 良好的运用它们可以给用户提供可读的错误信息。
1. 实现 handlerexceptionresolver
public class apphandlerexceptionresolver implements handlerexceptionresolver { @override public modelandview resolveexception(httpservletrequest request, httpservletresponse response, object handler, exception ex) { modelandview mav = new modelandview(); mav.addobject("message", ex.getmessage()); // 可以设置视图名导向错误页面 mav.setviewname("/error"); // 直接返回视图 // 如果返回 null,则会调用下一个 handlerexceptionresolver return mav; } }
然后配置一个 handlerexceptionresolver
@bean public apphandlerexceptionresolver apphandlerexceptionresolver() { return new apphandlerexceptionresolver(); }
handlerexceptionresolver 的实现类会 catch 到 @controller 方法执行时发生的异常,处理后返回 modelandview 作为结果视图,因此可以通过它来定制异常视图。
handlerexceptionresolver 只能捕获 @controller 层发生的异常(包括 @controller 调用 @service 发生的异常),其他地方的异常,比如访问了一个不存在的路径,不会被 handlerexceptionresolver 捕获,此时会跳到 errorcontroller 处理, 下面会说到。
2. 通过 @controlleradvice 和 @exceptionhandler 注解
// 可以配置拦截指定的类或者包等 // @restcontrolleradvice 使 @exceptionhandler 注解的方法默认具有 @responsebody 注解 @restcontrolleradvice(basepackageclasses = helloworldcontroller.class) public class appexceptionhandleradvice { // 配置拦截的错误类型 // 这里也可以返回 modelandview 导向错误视图 @exceptionhandler(exception.class) public responseentity<object> responseentity(exception e) { httpheaders headers = new httpheaders(); headers.setcontenttype(mediatype.application_json_utf8); map<string, object> map = new hashmap<>(); map.put("status", 400); map.put("message", e.getmessage()); // 直接返回结果 return new responseentity<>(map, headers, httpstatus.bad_request); } }
这种方式配置的异常处理由 handlerexceptionresolver 的默认实现类 handlerexceptionresolvercomposite 处理,因此也只能捕获 @controller 层的异常。
@exceptionhandler 可以返回 modelandview 定制异常视图。
@controlleradvice 可以拦截特定的类,@exceptionhandler 可以拦截特定的异常,因此可以更精确的配置异常处理逻辑。
@exceptionhandler 可以在 @controller 类中声明,此时只能处理同一个类的异常
3. 自定义 errorcontroller bean
@restcontroller @requestmapping("/error") public class apperrorcontroller extends abstracterrorcontroller { public apperrorcontroller(errorattributes errorattributes) { super(errorattributes); } @requestmapping public responseentity<map<string, object>> error(httpservletrequest request) { map<string, object> body = geterrorattributes(request, false); httpstatus status = getstatus(request); // 返回响应体 return new responseentity<>(body, status); } @override public string geterrorpath() { return "/error"; } }
如果没有配置 errorcontroller, springboot 会通过 errormvcautoconfiguration 自动配置一个,默认的实现类为 basicerrorcontroller。
errorcontroller 可以处理非 @controller 层抛出的异常,例如常见的访问了一个不存在的路径。
errorcontroller 可以进行统一的错误处理,即让 handlerexceptionresolver 返回的 modelandview 导向错误页面。