异常映射处理

实现目标

统一管理项目中的异常,普通请求出现异常显示异常消息页面、ajax请求出现异常则返回json数据时携带异常信息,不跳转错误页面。
在这里插入图片描述

注意

springMVC提供了基于XML和注解的两种异常映射机制。
如果我们发送的请求如果是使用的<mvc:view-controller>这个标签处理的,那么如果在这个请求中出现了异常,那么我们需要使用基于XML的异常映射来处理。
如果访问的是requestMapping这个注解的话,那么出现异常的时候需要使用基于注解的异常处理来解决。
在这里插入图片描述

综上,我们干脆直接把基于XML和注解配置异常处理都配置上就好了

实现

配置XML异常解析器

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

后面需要什么就配置什么异常

配置注解的异常映射

在配置注解异常处理映射前我们需要区分接收到的请求是普通请求还是ajax请求

我们如何才能判断一个请求是不是ajax请求呢?

如果当前的请求头包含Accept: application/jsonX-Requested-With: XMLHttpRequest值中的任何一个的话。那么该请求就是一个ajax请求

如此我们知道了如何判断当前请求是不是ajax后,我们来编写我们的工具类,在该工具类中添加一个可以判断请求是否为ajax请求的方法

方法如下

 /**
     * 根据请求头判断当前请求是否是一个ajax请求
     * @param request
     * @return true表示是ajax请求,false表示不是ajax请求
     */
public static boolean judgeRequestType(HttpServletRequest request) {
        String acceptHeader = request.getHeader("Accept");
        String xRequestHeader = request.getHeader("X-Requested-With");
        return (
                (acceptHeader != null && acceptHeader.contains("application/json"))
                        ||
                        (xRequestHeader != null && xRequestHeader.equals("XMLHttpRequest"))
        );
    }

然后编写基于注解的异常映射

springMVC给我们提供的将异常和我们的方法联系在一起的注解就是@ExceptionHandler(value = NullPointerException.class)该注解中的参数表示当出现这个异常,那么就执行当前注解修饰的方法中的内容。参数为异常的字节码类型

/**
 * @author 14767
 * @ControllerAdvice 该注解表示当前类是一个基于注解的异常处理类
 */
@ControllerAdvice
public class CrowdExceptionResolver {
    /**
     * 提取出来的公共方法
     * @param viewName
     * @param exception
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    private ModelAndView commonResolve(String viewName,Exception exception,HttpServletRequest request,HttpServletResponse response) throws IOException {
        boolean b = CrowdUtil.judgeRequestType(request);
        if (b){
            //是ajax请求
            
            ResultEntity<Object> resultEntity = ResultEntity.failed(exception.getMessage());
            Gson gson = new Gson();
            String json = gson.toJson(resultEntity);
            // 将json数据以响应体返回给浏览器
            response.getWriter().write(json);
            // 因为我们已经通过response返回了响应,所以不提供ModelAndView
            return null;
        }
        // 不是ajax请求
        ModelAndView modelAndView = new ModelAndView();
        // 属性名使用一个单独的类中定义单独的常量,方便后面调用防止写错
        modelAndView.addObject(CrowdConstant.ATTR_NAME_EXCEPTION,exception);
        // 设置跳转视图名
        modelAndView.setViewName(viewName);
        return modelAndView;
    }

    @ExceptionHandler(value = NullPointerException.class)
    public ModelAndView resolveNullPointerException(NullPointerException exception, HttpServletRequest request, HttpServletResponse response) throws IOException {

        return commonResolve("system-error",exception,request,response);
    }
}

常量类

/**
 * @author 14767
 * 该类存放一些常量信息
 */
public class CrowdConstant {
    public static final String ATTR_NAME_EXCEPTION = "exception";
}

涉及到的两个注解

  1. @ExceptionHandler
  2. @ControllerAdvice:该异常结合@ExceptionHandler用于全局异常的处理
posted @ 2021-03-28 20:56  谢海川  阅读(142)  评论(0)    收藏  举报