spring 统一异常处理有 3 种方式,分别为:
使用@ exceptionhandler注解、实现handlerexceptionresolver接口、使用 @controlleradvice 注解
使用 @ exceptionhandler 注解
使用该注解有一个不好的地方就是:进行异常处理的方法必须与出错的方法在同一个controller里面。使用如下:
@controller public class globalcontroller {/** * 用于处理异常的 * @return */ @exceptionhandler({myexception.class})public string exception(myexception e) {system.out.println(e.getmessage());e.printstacktrace();return "exception";}@requestmapping("test")public void test() {throw new myexception("出错了!");}}
可以看到,这种方式最大的缺陷就是不能全局控制异常。每个类都要写一遍。
实现 handlerexceptionresolver 接口
这种方式可以进行全局的异常控制。例如:
@component public class exceptiontest implements handlerexceptionresolver{/** * todo 简单描述该方法的实现功能(可选). * @see org.springframework.web.servlet.handlerexceptionresolver#resolveexception(javax.servlet.http.httpservletrequest, javax.servlet.http.httpservletresponse, java.lang.object, java.lang.exception) */ public modelandview resolveexception(httpservletrequest request, httpservletresponse response, object handler, exception ex) {system.out.println("this is exception handler method!");return null;}}
使用 @controlleradvice+ @ exceptionhandler 注解
上文说到 @ exceptionhandler 需要进行异常处理的方法必须与出错的方法在同一个controller里面。那么当代码加入了 @controlleradvice,则不需要必须在同一个 controller 中了。这也是 spring 3.2 带来的新特性。从名字上可以看出大体意思是控制器增强。 也就是说,@controlleradvice + @ exceptionhandler 也可以实现全局的异常捕捉。
请确保此webexceptionhandle 类能被扫描到并装载进 spring 容器中。
@controlleradvice@responsebodypublic class webexceptionhandle {private static logger logger = loggerfactory.getlogger(webexceptionhandle.class);/** * 400 - bad request */@responsestatus(httpstatus.bad_request)@exceptionhandler(httpmessagenotreadableexception.class)public serviceresponse handlehttpmessagenotreadableexception(httpmessagenotreadableexception e) {logger.error("参数解析失败", e);return serviceresponsehandle.failed("could_not_read_json");}/** * 405 - method not allowed */@responsestatus(httpstatus.method_not_allowed)@exceptionhandler(httprequestmethodnotsupportedexception.class)public serviceresponse handlehttprequestmethodnotsupportedexception(httprequestmethodnotsupportedexception e) {logger.error("不支持当前请求方法", e);return serviceresponsehandle.failed("request_method_not_supported");}/** * 415 - unsupported media type */@responsestatus(httpstatus.unsupported_media_type)@exceptionhandler(httpmediatypenotsupportedexception.class)public serviceresponse handlehttpmediatypenotsupportedexception(exception e) {logger.error("不支持当前媒体类型", e);return serviceresponsehandle.failed("content_type_not_supported");}/** * 500 - internal server error */@responsestatus(httpstatus.internal_server_error)@exceptionhandler(exception.class)public serviceresponse handleexception(exception e) {if (e instanceof businessexception){return serviceresponsehandle.failed("business_error", e.getmessage());}logger.error("服务运行异常", e);e.printstacktrace();return serviceresponsehandle.failed("server_error");}}
如果 @exceptionhandler 注解中未声明要处理的异常类型,则默认为参数列表中的异常类型。所以还可以写成这样:
@controlleradvicepublic class globalexceptionhandler {@exceptionhandler()@responsebodystring handleexception(exception e){return "exception deal! " + e.getmessage();}}
参数对象就是 controller 层抛出的异常对象!
继承 responseentityexceptionhandler 类来实现针对 rest 接口 的全局异常捕获,并且可以返回自定义格式:
@slf4j@controlleradvicepublic class exceptionhandlerbean extends responseentityexceptionhandler {/** * 数据找不到异常 * @param ex * @param request * @return * @throws ioexception */@exceptionhandler({datanotfoundexception.class})public responseentity<object> handledatanotfoundexception(runtimeexception ex, webrequest request) throws ioexception {return getresponseentity(ex,request,returnstatuscode.datanotfoundexception);}/** * 根据各种异常构建 responseentity 实体. 服务于以上各种异常 * @param ex * @param request * @param specificexception * @return */private responseentity<object> getresponseentity(runtimeexception ex, webrequest request, returnstatuscode specificexception) {returntemplate returntemplate = new returntemplate();returntemplate.setstatuscode(specificexception);returntemplate.seterrormsg(ex.getmessage());return handleexceptioninternal(ex, returntemplate,new httpheaders(), httpstatus.ok, request);}}
以上就是spring mvc异常统一处理的三种方式的详细内容。