详解Spring全局异常处理的三种方式
程序员文章站
2024-03-01 09:45:46
在j2ee项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异...
在j2ee项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。 那么,能不能将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护?答案是肯定的。下面将介绍使用spring mvc统一处理异常的解决和实现过程
- 使用spring mvc提供的simplemappingexceptionresolver
- 实现spring的异常处理接口handlerexceptionresolver 自定义自己的异常处理器
- 使用@exceptionhandler注解实现异常处理
(一) simplemappingexceptionresolver
使用这种方式具有集成简单、有良好的扩展性、对已有代码没有入侵性等优点,但该方法仅能获取到异常信息,若在出现异常时,对需要获取除异常以外的数据的情况不适用。
@configuration @enablewebmvc @componentscan(basepackages = {"com.balbala.mvc.web"}) public class webmvcconfig extends webmvcconfigureradapter{ @bean public simplemappingexceptionresolver simplemappingexceptionresolver() { simplemappingexceptionresolver b = new simplemappingexceptionresolver(); properties mappings = new properties(); mappings.put("org.springframework.web.servlet.pagenotfound", "page-404"); mappings.put("org.springframework.dao.dataaccessexception", "data-access"); mappings.put("org.springframework.transaction.transactionexception", "transaction-failure"); b.setexceptionmappings(mappings); return b; } }
(二) handlerexceptionresolver
相比第一种来说,handlerexceptionresolver能准确显示定义的异常处理页面,达到了统一异常处理的目标
1.定义一个类实现handlerexceptionresolver接口,这次贴一个自己以前的代码
package com.athena.common.handler; import com.athena.common.constants.responsecode; import com.athena.common.exception.athenaexception; import com.athena.common.http.rspmsg; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.web.servlet.handlerexceptionresolver; import org.springframework.web.servlet.modelandview; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import java.io.printwriter; /** * created by sam on 15/4/14. */ public class globalhandlerexceptionresolver implements handlerexceptionresolver { private static final logger log = loggerfactory.getlogger(globalhandlerexceptionresolver.class); /** * 在这里处理所有得异常信息 */ @override public modelandview resolveexception(httpservletrequest req, httpservletresponse resp, object o, exception ex) { ex.printstacktrace(); if (ex instanceof athenaexception) { //athenaexception为一个自定义异常 ex.printstacktrace(); printwrite(ex.tostring(), resp); return new modelandview(); } //rspmsg为一个自定义处理异常信息的类 //responsecode为一个自定义错误码的接口 rspmsg unknownexception = null; if (ex instanceof nullpointerexception) { unknownexception = new rspmsg(responsecode.code_unknown, "业务判空异常", null); } else { unknownexception = new rspmsg(responsecode.code_unknown, ex.getmessage(), null); } printwrite(unknownexception.tostring(), resp); return new modelandview(); } /** * 将错误信息添加到response中 * * @param msg * @param response * @throws ioexception */ public static void printwrite(string msg, httpservletresponse response) { try { printwriter pw = response.getwriter(); pw.write(msg); pw.flush(); pw.close(); } catch (exception e) { e.printstacktrace(); } } }
2.加入spring的配置中,这里只贴出了相关部分
import com.athena.common.handler.globalhandlerexceptionresolver; import org.springframework.context.annotation.bean; import com.athena.common.handler.globalhandlerexceptionresolver; import org.springframework.web.servlet.config.annotation.webmvcconfigureradapter; /** * created by sam on 15/4/14. */ public class webspringmvcconfig extends webmvcconfigureradapter { @bean public globalhandlerexceptionresolver globalhandlerexceptionresolver() { return new globalhandlerexceptionresolver(); } }
(三)@exceptionhandler
这是笔者现在项目的使用方式,这里也仅贴出了相关部分
1.首先定义一个父类,实现一些基础的方法
package com.balabala.poet.base.spring; import com.google.common.base.throwables; import com.raiyee.poet.base.exception.messageexception; import com.raiyee.poet.base.utils.ajax; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.core.annotation.annotationutils; import org.springframework.http.httpstatus; import org.springframework.web.bind.annotation.responsestatus; import org.springframework.web.servlet.modelandview; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import java.io.ioexception; import java.io.printwriter; import java.util.date; public class baseglobalexceptionhandler { protected static final logger logger = null; protected static final string default_error_message = "系统忙,请稍后再试"; protected modelandview handleerror(httpservletrequest req, httpservletresponse rsp, exception e, string viewname, httpstatus status) throws exception { if (annotationutils.findannotation(e.getclass(), responsestatus.class) != null) throw e; string errormsg = e instanceof messageexception ? e.getmessage() : default_error_message; string errorstack = throwables.getstacktraceasstring(e); getlogger().error("request: {} raised {}", req.getrequesturi(), errorstack); if (ajax.isajax(req)) { return handleajaxerror(rsp, errormsg, status); } return handleviewerror(req.getrequesturl().tostring(), errorstack, errormsg, viewname); } protected modelandview handleviewerror(string url, string errorstack, string errormessage, string viewname) { modelandview mav = new modelandview(); mav.addobject("exception", errorstack); mav.addobject("url", url); mav.addobject("message", errormessage); mav.addobject("timestamp", new date()); mav.setviewname(viewname); return mav; } protected modelandview handleajaxerror(httpservletresponse rsp, string errormessage, httpstatus status) throws ioexception { rsp.setcharacterencoding("utf-8"); rsp.setstatus(status.value()); printwriter writer = rsp.getwriter(); writer.write(errormessage); writer.flush(); return null; } public logger getlogger() { return loggerfactory.getlogger(baseglobalexceptionhandler.class); } }
2.针对你需要捕捉的异常实现相对应的处理方式
package com.balabala.poet.base.spring; import org.slf4j.logger; import org.slf4j.loggerfactory; import org.springframework.http.httpstatus; import org.springframework.web.bind.annotation.controlleradvice; import org.springframework.web.bind.annotation.exceptionhandler; import org.springframework.web.bind.annotation.responsestatus; import org.springframework.web.servlet.modelandview; import org.springframework.web.servlet.nohandlerfoundexception; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; @controlleradvice public class globalexceptionhandler extends baseglobalexceptionhandler { //比如404的异常就会被这个方法捕获 @exceptionhandler(nohandlerfoundexception.class) @responsestatus(httpstatus.not_found) public modelandview handle404error(httpservletrequest req, httpservletresponse rsp, exception e) throws exception { return handleerror(req, rsp, e, "error-front", httpstatus.not_found); } //500的异常会被这个方法捕获 @exceptionhandler(exception.class) @responsestatus(httpstatus.internal_server_error) public modelandview handleerror(httpservletrequest req, httpservletresponse rsp, exception e) throws exception { return handleerror(req, rsp, e, "error-front", httpstatus.internal_server_error); } //todo 你也可以再写一个方法来捕获你的自定义异常 //try now!!! @override public logger getlogger() { return loggerfactory.getlogger(globalexceptionhandler.class); } }
以上就三种处理方式,希望对大家的学习有所帮助,也希望大家多多支持。