SpringMVC异常处理

目标

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

思路

image
注意:

  • springmvc 提供了基于 xml和注解两种异常映射机制。
  • <mvc:view-controller> 是在xml文件中配置的 , @RequestMapping注解。
    image

配置方式

基于 xml的

springmvc 全局配置文件

    <!--配置基于xml 异常处理映射-->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
          id="simpleMappingExceptionResolver">
        <!--配置异常类型和具体页面的对应关系-->
        <property name="exceptionMappings">
            <props>
                <!--<prop key="异常">页面</prop>
                key属性指定异常全类名
                标签体中写对应的视图【这个值要拼写前后缀得到具体的路径】-->
                <prop key="java.lang.Exception">system-error</prop>
            </props>
        </property>
    </bean>

页面

<%--从域中取出 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;
    }
}

ajax 工具类


/**
 * @author zhaokuii11@163.com
 * @create 2021-12-01 20:16
 * @Description 统一整个项目中 Ajax请求返回的结果【未来也可以用户分布式框架各个模块间调用时返回统一类型】
 */
public class ResultEntity<T> {
    public static final String SUCCESS = "success";
    public static final String FAILED = "failed";
    /**
     * 用来封装当前请去处理的结果是成功还是失败
     */
    private String result;
    /**
     * 请去处理失败时返回的错误信息
     */
    private String message;
    /**
     * 要返回的数据
     */
    private T data;

    /**
     * 请求处理成功且不需要返回数据使用的工具方法
     * 【增删改的】
     *
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> successWithoutData() {
        return new ResultEntity<Type>(SUCCESS, null, null);
    }

    /**
     * 请求处理成功且需要返回数据的方法
     * 【查询的】
     *
     * @param data   要返回的数据
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> successWithData(Type data) {
        return new ResultEntity<Type>(SUCCESS, null, data);
    }

    /**
     * 请求处理失败使用的工具方法
     * 【失败的】
     *
     * @param message 失败的错误消息
     * @param <Type>
     * @return
     */
    public static <Type> ResultEntity<Type> failed(String message) {
        return new ResultEntity<Type>(FAILED, message, null);
    }

    public ResultEntity() {
    }

    public ResultEntity(String result, String message, T data) {
        this.result = result;
        this.message = message;
        this.data = data;
    }

    @Override
    public String toString() {
        return "ResultEntity{" +
                "result='" + result + '\'' +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

编写

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<Object> 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<Object> 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);
    }
}
posted @ 2021-12-01 22:20  MikiKawai  阅读(79)  评论(0编辑  收藏  举报