SpringMVC异常处理


目标

  • 使用异常映射机制将整个项目的异常和错误提示进行统一管理。

思路


注意:

  • springmvc 提供了基于 xml和注解两种异常映射机制。
  • 是在xml文件中配置的 , @RequestMapping注解。

配置方式

基于 xml的

springmvc 全局配置文件

    
    
        
        
            
                
                system-error
            
        
    

页面

<%--从域中取出 exceptiono对象,在进一步访问 message属性就能够显示错误信息。--%>
${pageContext.exception.message}

基于注解的

准备

  • 判断当前请求时 普通请求还是 ajax请求 工具类
import javax.servlet.http.HttpServletRequest;

/**
 * @author zhaokuii11@163.com
 * @create 2021-12-01 20:59
 * @Description 判断请求类型、ajax还是 普通的
 */
public class CrowdUtil {
    /**
     * 判断当前请求是 ajax还是 普通请求
     * 判断依据:
     * Accept : application/json; charset=utf-8
     * X-requested-with: XMLHttpRequest
     * 只要有一个就可以
     *
     * @param request 请求对象
     * @return Boolean true ajax请求、false 普通请求
     */
    public static boolean judgeRequestType(HttpServletRequest request) {
        //1. 获取请求消息头
        String accept = request.getHeader("Accept");
        String xRequestedwith = request.getHeader("X-requested-with");
        //2. 判断
        if (accept != null && accept.contains("application/json") ||
                xRequestedwith != null && xRequestedwith.contains("XMLHttpRequest")) {
            return true;
        }
        return false;
    }
}

编写

import com.aiguigu.crowd.util.CrowdUtil;
import com.aiguigu.crowd.util.ResultEntity;
import com.google.gson.Gson;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @author zhaokuii11@163.com
 * @create 2021-12-01 21:14
 * @Description
 */
//@ControllerAdvice 表示当前类是一个基于注解的异常处理类
@ControllerAdvice
public class CrowdExceptionResolver {

    //    @ExceptionHandler 将一个具体的异常类型和一个方法关联起来【里面是一个数组】
    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointException(
            //实际捕获的德类型
            NullPointerException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //1. 判断当前请去
        boolean requestType = CrowdUtil.judgeRequestType(request);
        //2. 如果 Ajax请求
        if (requestType) {
            //3. 创建 ResultEntity 对象
            ResultEntity resultEntity = ResultEntity.failed(exception.getMessage());
            //4. 消息转为 json对象,创建 gson对象
            Gson gson = new Gson();
            //5. 将 json字符串作为响应体返回给浏览器
            String json = gson.toJson(resultEntity);
            //6. 将 json字符串作为响应体返回给浏览器
            response.getWriter().print(json);
            //7. 由于上面通过原生的 response对象返回了响应,所以不提供 modelAndView对象
            return null;
        }
        //8. 如果不是 Ajax请去则创建 ModelAndView对象
        ModelAndView view = new ModelAndView();
        //9. 将 exception对象存入模型
        view.addObject("exception", exception);
        //10. 设置对应的视图
        view.setViewName("system-error");
        //11. 返回
        return view;
    }

    /**
     * 抽取公共代码
     *
     * @param viewName  发生异常要去的页面
     * @param exception 发生的异常
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private ModelAndView commonResolve(
            //要去的视图
            String viewName,
            //实际捕获的德类型
            Exception exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {

        //1. 判断当前请去
        boolean requestType = CrowdUtil.judgeRequestType(request);
        //2. 如果 Ajax请求
        if (requestType) {
            //3. 创建 ResultEntity 对象
            ResultEntity resultEntity = ResultEntity.failed(exception.getMessage());
            //4. 消息转为 json对象,创建 gson对象
            Gson gson = new Gson();
            //5. 将 json字符串作为响应体返回给浏览器
            String json = gson.toJson(resultEntity);
            //6. 将 json字符串作为响应体返回给浏览器
            response.getWriter().print(json);
            //7. 由于上面通过原生的 response对象返回了响应,所以不提供 modelAndView对象
            return null;
        }
        //8. 如果不是 Ajax请去则创建 ModelAndView对象
        ModelAndView view = new ModelAndView();
        //9. 将 exception对象存入模型
        view.addObject("exception", exception);
        //10. 设置对应的视图
        view.setViewName(viewName);
        //11. 返回
        return view;
    }

    /**
     * 优化
     *
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @ExceptionHandler(value = ArithmeticException.class)
    public ModelAndView resolveArithmeticException(
            //实际捕获的德类型
            NullPointerException exception,
            //当前请求对象
            HttpServletRequest request,
            //当前响应对象
            HttpServletResponse response) throws IOException {
        return commonResolve("system-error", exception, request, response);
    }
}