1.内置异常处理解析器

在J2EE项目的开发中,不管是对底层的数据库操作过程,还是业务层的处理过程,还是控制层的处理过程,都不可避免会遇到各种可预知的、不可预知的异常需要处理。每个过程都单独处理异常,系统的代码耦合度高,工作量大且不好统一,维护的工作量也很大。
那么,能不能将所有类型的异常处理从各处理过程解耦出来,这样既保证了相关处理过程的功能较单一,也实现了异常信息的统一处理和维护?答案是肯定的。下面将介绍使用Spring MVC统一处理异常的解决和实现过程。
在SpringMVC中拥有一套非常强大的异常处理机制,SpringMVC通过HandlerExceptionResolver处理程序的异常,包括请求映射,数据绑定以及目标方法的执行时发生的异常。

image.png

image.png

  1. #默认的处理类
  2. org.springframework.web.servlet.HandlerExceptionResolver=
  3. #处理@ExceptionHandler
  4. org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver,\
  5. #解析@ResponseStatus注释类型的异常
  6. org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver,\
  7. #按照不同类型分别对异常进行解析
  8. org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver

1.1示例

controller类

package com.xixi.controller;


import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import java.io.PrintWriter;
import java.io.StringWriter;


/***
 * 处理异常:
 * 通过@ExceptionHandler可以在方法中记录日志
 * 转发到一个友好的页面进行提示
 *
 * 如果@ExceptionHandler写在controller类中 只能处理当前类的异常
 */
@Controller
public class ExceptionController {

    @RequestMapping("/exception")
    public String exception01(@RequestParam String name){
        System.out.println("test");
        return "show";
    }


    @RequestMapping("/exception02")
    public String exception02(@RequestParam String name){
        System.out.println("test");
        return "show";
    }

    @ExceptionHandler
    public ModelAndView handlerException(Exception ex){
        System.out.println("@Controller 方法异常异常处理。。。");

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("ex",ex);
        StringWriter sw =   new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        System.out.println(sw.toString());
        return modelAndView;

    }
}

自定义全局异常

package com.xixi.exception;

import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;

import java.io.PrintWriter;
import java.io.StringWriter;

/***
 *全局异常处理
 *1.@ControllerAdvice
 *2.全局异常 2处理器异常 3具体异常
 *
 * 处理器异常优先级最高,
 * 如果处理器异常和全局异常都定义了也是走处理器异常
 * 如果controller方法中没有处理机制才会走全局异常,而且哪个全局异常粒度
 * 更细就会走哪个
 *
 *
 */
@ControllerAdvice
public class GeneralExceptionHandler {


    @ExceptionHandler
    public ModelAndView handlerException(Exception ex){
        System.out.println("Exception 全局异常处理。。。");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("ex",ex);
        StringWriter sw =   new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        System.out.println(sw.toString());
        return modelAndView;

    }


    @ExceptionHandler
    public ModelAndView handlerException(MissingServletRequestParameterException ex){
        System.out.println("MissingServletRequestParameterException 全局异常处理。。。");
        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error");
        modelAndView.addObject("ex",ex);
        StringWriter sw =   new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        ex.printStackTrace(pw);
        System.out.println(sw.toString());
        return modelAndView;

    }}

页面:


<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
服务器出错了~~~~~
<div style="display: none">
    <%= ((Exception)request.getAttribute("ex")).getMessage()%>
</div>
</body>
</html>

2.全局异常处理



@ControllerAdvice
public class GeneralExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ModelAndView handleException(HttpServletRequest request,
                                        HttpServletResponse reponse, Exception ex,
                                        HandlerMethod handle){
        System.out.println("全局异常处理");
        // 如果当前请求是ajax就返回json

        // 1.根据用户请求的处理方法,是否是一个返回json的处理方法
        //RestController restAnnotation = handle.getClass().getAnnotation(RestController.class); // 获得类上面的某个注解
        //ResponseBody responseBody = handle.getMethod().getAnnotation(ResponseBody.class);//获得方法上面的某个注解
        // if(restAnnotation!=null || responseBody!=null){ }

        // 2.可以根据请求头中的类型Content-Type包含application/json


        if(request.getHeader("Accept").indexOf("application/json")>-1){
          // 可以直接输出json  reponse.getWriter().write();  或者集成jackson

            // 集成jackson的方式:
            //ModelAndView 同时支持视图返回和json返回
            // 这种方式就是返回json
            ModelAndView modelAndView = new ModelAndView(new MappingJackson2JsonView());
            // 通常会根据不同的异常返回不同的编码
            modelAndView.addObject("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
            modelAndView.addObject("message",ex.getMessage());
            return  modelAndView;
        }
        else{
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.setViewName("error");
            modelAndView.addObject("ex", ex);
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            ex.printStackTrace(pw);
            System.out.println(sw.toString());   // 日志记录
            return modelAndView;
        }
    }
}