SpringMVC通过HandlerExceptionResolver处理程序异常,包括Handler映射,数据绑定以及目标方法执行时所发生的异常。
SpringMVC中默认是没有加装载HandlerExceptionResolver,我们需要在SpringMVC.xml中配置
<mvc:annotation-driven />
1、可以在Controller里面定义一个局部的异常处理方法(只处理该Controller下的异常)
/** * 在这个方法中可以加入Exception类型的参数,该参数即对于发生的异常对象 * 入参中不能传入map,若希望把异常信息传到页面上需要使用ModelAndView作为返回值 */ @ExceptionHandler({NullPointerException.class}) public String handlerNullPointerException(Exception ex){ System.out.println("异常 : " + ex); return "error"; }
该方法只会对该controller中的NullPointException异常捕获,若是想返回一个错误的提示页面,添加一个ModelAndView返回就好了
2、全局异常处理
①:自定义异常处理类需要实现HandlerExceptionResolver接口,然后再application.xml文件中注册这个bean
@Component
public class GlobalExceptionResolver implements HandlerExceptionResolver { /** * 对异常信息进行统一处理,区分异步和同步请求,分别处理 */ public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { boolean isajax = isAjax(request,response); Throwable deepestException = deepestException(ex); return processException(request, response, handler, deepestException, isajax); } /** * 判断当前请求是否为异步请求. */ private boolean isAjax(HttpServletRequest request, HttpServletResponse response){ return oConvertUtils.isNotEmpty(request.getHeader("X-Requested-With")); } } /** * 获取最原始的异常出处,即最初抛出异常的地方 */ private Throwable deepestException(Throwable e){ Throwable tmp = e; int breakPoint = 0; while(tmp.getCause()!=null){ if(tmp.equals(tmp.getCause())){ break; } tmp=tmp.getCause(); breakPoint++; if(breakPoint>1000){ break; } } return tmp; } /** * 处理异常. * @param request * @param response * @param handler * @param deepestException * @param isajax * @return */ private ModelAndView processException(HttpServletRequest request, HttpServletResponse response, Object handler, Throwable ex, boolean isajax) { //步骤一、异常信息记录到日志文件中. log.error("全局处理异常捕获:", ex); //步骤二、异常信息记录截取前50字符写入数据库中. logDb(ex); //步骤三、分普通请求和ajax请求分别处理. if(isajax){ return processAjax(request,response,handler,ex); }else{ return processNotAjax(request,response,handler,ex); } }
private ModelAndView processAjax(HttpServletRequest request, HttpServletResponse response, Object handler, Throwable deepestException){ ModelAndView empty = new ModelAndView(); //response.setContentType("application/json"); response.setHeader("Cache-Control", "no-store"); AjaxJson json = new AjaxJson(); json.setSuccess(true); json.setMsg(deepestException.getMessage()); PrintWriter pw = null; try { pw=response.getWriter(); pw.write(JSONHelper.bean2json(json)); pw.flush(); } catch (IOException e) { e.printStackTrace(); }finally{ pw.close(); } empty.clear(); return empty; } private ModelAndView processNotAjax(HttpServletRequest request, HttpServletResponse response, Object handler, Throwable ex) { String exceptionMessage = getThrowableMessage(ex); Map<String, Object> model = new HashMap<String, Object>(); model.put("exceptionMessage", exceptionMessage); model.put("ex", ex); return new ModelAndView("common/error", model); } }
②:注解@ControllerAdvice和@ExceptionHandler配合完成全局的异常捕获和处理返回
/** * @author SimpleWu * @ControllerAdvice:如果在当前Handler找不到当前方法出现的异常则将来这个注解标记的类中查找处理异常。 * 意为定义一个全局异常 */ @ControllerAdvice public class UserException { @ExceptionHandler({NullPointerException.class}) public ModelAndView handlerNullPointerException(Exception ex){ System.out.println("[异常] : " + ex); ModelAndView mav = new ModelAndView("error"); mav.addObject("exception",ex); return mav; } }
3、另外spring已经提供SimpleMappingExceptionResolver和DefaultHandlerExceptionResolver
Spring除了实现了一个DefaultHandlerExceptionResolver之外,还实现了一个SimpleMappingExceptionResolver,这两者都是继承自抽象类AbstractHandlerExceptionResolver,而AbstractHandlerExceptionResolver是实现了HandlerExceptionResolver接口的resolveException方法的,并由此抽取出两个抽象方法,一个是在进行异常处理之前执行的方法prepareResponse(exception, response),一个是进行异常解析的doResolveException(request, response, handler, exception)方法。SimpleMappingExceptionResolver,顾名思义就是通过简单的映射关系来决定由哪个视图来处理当前的错误信息。SimpleMappingExceptionResolver提供了通过异常类型exceptionMappings来进行异常与视图之间的映射关系,提供了在发生异常时通过statusCodes来映射异常返回的视图名称和对应的HttpServletResponse的返回码。而且可以通过defaultErrorView和defaultErrorCode来指定默认值,defaultErrorView表示当没有在exceptionMappings里面找到对应的异常类型时就返回defaultErrorView定义的视图,defaultErrorCode表示在发生异常时当没有在视图与返回码的映射关系statusCodes里面找到对应的映射时默认返回的返回码。在使用SimpleMappingExceptionResolver时,当发生异常的时候,SimpleMappingExceptionResolver将会把当前的异常对象放到自身属性exceptionAttribute中,当没有指定exceptionAttribute时,exceptionAttribute就是用默认值exception。
以下是一个简单的例子:详情点击https://www.cnblogs.com/sunhaoyu/articles/5307496.html
(1)SpringMVC的servlet配置文件中申明一个SimpleMappingExceptionResolver bean,并通过配置属性exceptionMappings和defaultExceptionView来指定异常和视图的对应关系。
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="NumberFormatException">number</prop><!-- 表示当抛出NumberFormatException的时候就返回名叫number的视图 --> <prop key="NullPointerException">null</prop> </props> </property> <property name="defaultErrorView" value="exception"/><!-- 表示当抛出异常但没有在exceptionMappings里面找到对应的异常时 返回名叫exception的视图--> <property name="statusCodes"><!-- 定义在发生异常时视图跟返回码的对应关系 --> <props> <prop key="number">500</prop><!-- 表示在发生NumberFormatException时返回视图number,然后这里定义发生异常时视图number对应的HttpServletResponse的返回码是500 --> <prop key="null">503</prop> </props> </property> <property name="defaultStatusCode" value="404"/><!-- 表示在发生异常时默认的HttpServletResponse的返回码是多少,默认是200 --> </bean>