详解Springboot自定义异常处理
程序员文章站
2024-03-01 15:34:40
背景
springboot 默认把异常的处理集中到一个modelandview中了,但项目的实际过程中,这样做,并不能满足我们的要求。具体的自定义异常的处理,参看以下...
背景
springboot 默认把异常的处理集中到一个modelandview中了,但项目的实际过程中,这样做,并不能满足我们的要求。具体的自定义异常的处理,参看以下
具体实现
如果仔细看完spring boot的异常处理详解,并且研究过源码后,我觉得具体的实现可以不用看了。。。
重写定义错误页面的url,默认只有一个/error
@bean public embeddedservletcontainercustomizer containercustomizer(){ return new embeddedservletcontainercustomizer(){ @override public void customize(configurableembeddedservletcontainer container) { container.adderrorpages(new errorpage(httpstatus.not_found, "/error/404")); container.adderrorpages(new errorpage(httpstatus.internal_server_error, "/error/500")); container.adderrorpages(new errorpage(java.lang.throwable.class,"/error/500")); } }; }
重写通过实现errorcontroller,重写basicerrorcontroller的功能实现
/** * 重写basicerrorcontroller,主要负责系统的异常页面的处理以及错误信息的显示 * @see org.springframework.boot.autoconfigure.web.basicerrorcontroller * @see org.springframework.boot.autoconfigure.web.errormvcautoconfiguration * * @author jonathan * @version 2016/5/31 11:22 * @since jdk 7.0+ */ @controller @requestmapping(value = "error") @enableconfigurationproperties({serverproperties.class}) public class exceptioncontroller implements errorcontroller { private errorattributes errorattributes; @autowired private serverproperties serverproperties; /** * 初始化exceptioncontroller * @param errorattributes */ @autowired public exceptioncontroller(errorattributes errorattributes) { assert.notnull(errorattributes, "errorattributes must not be null"); this.errorattributes = errorattributes; } /** * 定义404的modelandview * @param request * @param response * @return */ @requestmapping(produces = "text/html",value = "404") public modelandview errorhtml404(httpservletrequest request, httpservletresponse response) { response.setstatus(getstatus(request).value()); map<string, object> model = geterrorattributes(request, isincludestacktrace(request, mediatype.text_html)); return new modelandview("error/404", model); } /** * 定义404的json数据 * @param request * @return */ @requestmapping(value = "404") @responsebody public responseentity<map<string, object>> error404(httpservletrequest request) { map<string, object> body = geterrorattributes(request, isincludestacktrace(request, mediatype.text_html)); httpstatus status = getstatus(request); return new responseentity<map<string, object>>(body, status); } /** * 定义500的modelandview * @param request * @param response * @return */ @requestmapping(produces = "text/html",value = "500") public modelandview errorhtml500(httpservletrequest request, httpservletresponse response) { response.setstatus(getstatus(request).value()); map<string, object> model = geterrorattributes(request, isincludestacktrace(request, mediatype.text_html)); return new modelandview("error/500", model); } /** * 定义500的错误json信息 * @param request * @return */ @requestmapping(value = "500") @responsebody public responseentity<map<string, object>> error500(httpservletrequest request) { map<string, object> body = geterrorattributes(request, isincludestacktrace(request, mediatype.text_html)); httpstatus status = getstatus(request); return new responseentity<map<string, object>>(body, status); } /** * determine if the stacktrace attribute should be included. * @param request the source request * @param produces the media type produced (or {@code mediatype.all}) * @return if the stacktrace attribute should be included */ protected boolean isincludestacktrace(httpservletrequest request, mediatype produces) { errorproperties.includestacktrace include = this.serverproperties.geterror().getincludestacktrace(); if (include == errorproperties.includestacktrace.always) { return true; } if (include == errorproperties.includestacktrace.on_trace_param) { return gettraceparameter(request); } return false; } /** * 获取错误的信息 * @param request * @param includestacktrace * @return */ private map<string, object> geterrorattributes(httpservletrequest request, boolean includestacktrace) { requestattributes requestattributes = new servletrequestattributes(request); return this.errorattributes.geterrorattributes(requestattributes, includestacktrace); } /** * 是否包含trace * @param request * @return */ private boolean gettraceparameter(httpservletrequest request) { string parameter = request.getparameter("trace"); if (parameter == null) { return false; } return !"false".equals(parameter.tolowercase()); } /** * 获取错误编码 * @param request * @return */ private httpstatus getstatus(httpservletrequest request) { integer statuscode = (integer) request .getattribute("javax.servlet.error.status_code"); if (statuscode == null) { return httpstatus.internal_server_error; } try { return httpstatus.valueof(statuscode); } catch (exception ex) { return httpstatus.internal_server_error; } } /** * 实现错误路径,暂时无用 * @see exceptionmvcautoconfiguration#containercustomizer() * @return */ @override public string geterrorpath() { return ""; } }
总结
第一步,通过定义containercustomizer,重写定义了异常处理对应的视图。目前定义了404和500,可以继续扩展。
第二步,重写basicerrorcontroller,当然可以直接定义一个普通的controller类,直接实现第一步定义的视图的方法。重写的目的是重用errorattributes。这样在页面,直接可以获取到status,message,exception,trace等内容。
如果仅仅是把异常处理的视图作为静态页面,不需要看到异常信息内容的话,直接第一步后,再定义error/404,error/500等静态视图即可。
errorcontroller根据accept头的内容,输出不同格式的错误响应。比如针对浏览器的请求生成html页面,针对其它请求生成json格式的返回
以上两步的操作,比网上流传的更能实现自定义化。希望对大家的学习有所帮助,也希望大家多多支持。
下一篇: 利用相对定位及偏移量做精美输入界面