一、前言

后台出现异常如何友好而又高效地回显到前端呢?直接将一堆的错误信息抛给用户界面,显然不合适。

先不考虑代码实现,我们希望是这样的:

(1)如果是页面跳转的请求,出现异常了,我们希望跳转到一个异常显示页面,如下:

当然,这里的界面不够美观,但是理论是这样的。

(2)如果是ajax请求,那么我们,希望后台将合理的错误显示返回到ajax的回调函数里面,如下:

$.ajax({
    type: "post",
    url: "<%=request.getContextPath()%>" + "/businessException.json",
    data: {},
    dataType: "json",
    contentType : "application/json",
    success: function(data) {
        if(data.success == false){
            alert(data.errorMsg);
        }else{
            alert("请求成功无异常");
        }
    },
    error: function(data) {
        alert("调用失败....");
    }
});

将回调函数的data.errorMsg打印出来:

下面,我们根据上面的思路我们来看看代码的实现。因此本文实例包含了异常自定义分装,为了无障碍阅读下文,请猿友移步先看完博主的另外一篇文章:Java异常封装(自己定义错误码和描述,附源码)

二、实例详解

本实例使用的环境 eclipse+maven,其中maven只是为了方便引入jar包。

使用的技术:springmvc

在Spring MVC中,所有用于处理在请求映射和请求处理过程中抛出的异常的类,都要实现HandlerExceptionResolver接口。HandlerExceptionResolver接口有一个方法resolveException,当controller层出现异常之后就会进入到这个方法resolveException。

下面我们直接实现HandlerExceptionResolver接口,代码如下:

package com.luo.exceptionresolver;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import com.alibaba.druid.support.json.JSONUtils;
import com.luo.exception.BusinessException;
import org.springframework.web.servlet.HandlerExceptionResolver;

public class MySimpleMappingExceptionResolver implements
        HandlerExceptionResolver {

    public ModelAndView resolveException(HttpServletRequest request,
            HttpServletResponse response, Object object, Exception exception) {
        // 判断是否ajax请求
        if (!(request.getHeader("accept").indexOf("application/json") > -1 || (request
                .getHeader("X-Requested-With") != null && request.getHeader(
                "X-Requested-With").indexOf("XMLHttpRequest") > -1))) {
            // 如果不是ajax,JSP格式返回
            // 为安全起见,只有业务异常我们对前端可见,否则否则统一归为系统异常
            Map<String, Object> map = new HashMap<String, Object>();
            map.put("success", false);
            if (exception instanceof BusinessException) {
                map.put("errorMsg", exception.getMessage());
            } else {
                map.put("errorMsg", "系统异常!");
            }
            //这里需要手动将异常打印出来,由于没有配置log,实际生产环境应该打印到log里面
            exception.printStackTrace();
            //对于非ajax请求,我们都统一跳转到error.jsp页面
            return new ModelAndView("/error", map);
        } else {
            // 如果是ajax请求,JSON格式返回
            try {
                response.setContentType("application/json;charset=UTF-8");
                PrintWriter writer = response.getWriter();
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("success", false);
                // 为安全起见,只有业务异常我们对前端可见,否则统一归为系统异常
                if (exception instanceof BusinessException) {
                    map.put("errorMsg", exception.getMessage());
                } else {
                    map.put("errorMsg", "系统异常!");
                }
                writer.write(JSONUtils.toJSONString(map));
                writer.flush();
                writer.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}

上面的代码,归结为以下几点:

(1)判断如果不是ajax请求,那么统一跳转到error.jsp页面,否则返回json数据。

(2)如果是业务异常,我们直接打印异常信息,否则,我们统一归为系统异常,如果不明白这里的业务异常为何物,请阅读博主博客:Java异常封装(自己定义错误码和描述,附源码)

另外,需要在springmvc配置文件添加如下配置:

<!-- 框架异常处理Handler -->
<bean id="exceptionResolver" class="com.luo.exceptionresolver.MySimpleMappingExceptionResolver"></bean>

下面我们直接看controller代码:

package com.luo.controller;

import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
import com.luo.errorcode.LuoErrorCode;
import com.luo.exception.BusinessException;

@Controller
public class UserController {

    @RequestMapping("/index.jhtml")
    public ModelAndView getIndex(HttpServletRequest request) throws Exception {
        ModelAndView mav = new ModelAndView("index");
        return mav;
    }

    @RequestMapping("/exceptionForPageJumps.jhtml")
    public ModelAndView exceptionForPageJumps(HttpServletRequest request) throws Exception {
        throw new BusinessException(LuoErrorCode.NULL_OBJ);
    }

    @RequestMapping(value="/businessException.json", method=RequestMethod.POST)
    @ResponseBody
    public String businessException(HttpServletRequest request) {
        throw new BusinessException(LuoErrorCode.NULL_OBJ);
    }

    @RequestMapping(value="/otherException.json", method=RequestMethod.POST)
    @ResponseBody
    public String otherException(HttpServletRequest request) throws Exception {
        throw new Exception();
    }

}

关于controller代码没什么好解释的,下面我们直接看结果吧:

(1)如果跳转页面过程中出现异常,访问http://localhost:8080/web_exception_project/exceptionForPageJumps.jhtml的结果:

(2)如果ajax请求过程中出现异常,访问http://localhost:8080/web_exception_project/index.jhtml,然后,点击业务异常按钮结果:

点击其他异常按钮结果:

(3)HandlerExceptionResolver接口并不能处理404错误,这种错误我们再web.xml里面添加如下配置:

<!-- 错误跳转页面 -->
<error-page>
    <!-- 路径不正确 -->
    <error-code>404</error-code>
    <location>/WEB-INF/view/404.jsp</location>
</error-page>

然后404.jsp代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<taglib uri="http://java.sun.com /jsp/jstl/core" prefix="c" />
<html>
<head>
<title>错误页面</title>
</head>
<body>
页面被黑洞吸走了......
</body>
</html>

然后访问一个不存在的连接:http://localhost:8080/web_exception_project/123456.jhtml,结果如下:

三、本工程源码下载

http://download.csdn.net/detail/u013142781/9424969

javaweb异常提示信息统一处理(使用springmvc,附源码)的更多相关文章

  1. Javaweb异常提示信息统一处理

    Java异常封装(自己定义错误码和描述,附源码) 2016年01月29日 22:30:54 小宝鸽 阅读数:23262 标签: java异常 更多 个人分类: Java基础 所属专栏: Java工作实 ...

  2. Javaweb中提到的反射浅析(附源码)

    反射:一个jdk5.0的新特性,高级运用.在后期的框架中,这个是一大重点,现在估计我们都不会太多的接触他的.但是为了后面的铺垫,我想还是先了解一下: 先构造一个类,然后我们用反射来获取,调用里面的方法 ...

  3. Mybatis+SpringMVC实现分页查询(附源码)

    Maven+Mybatis+Spring+SpringMVC实现分页查询(附源码) 一.项目搭建 关于项目搭建,小宝鸽以前写过一篇Spirng+SpringMVC+Maven+Mybatis+MySQ ...

  4. (原创)通用查询实现方案(可用于DDD)[附源码] -- 简介

    [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html).   [系列文章] 通用查询实现方案(可用于DDD)[附源码] -- ...

  5. 通用查询实现方案(可用于DDD)[附源码] -- 简介

    原文:通用查询实现方案(可用于DDD)[附源码] -- 简介 [声明] 写作不易,转载请注明出处(http://www.cnblogs.com/wiseant/p/3985353.html).   [ ...

  6. 阿里P7终于讲完了JDK+Spring+mybatis+Dubbo+SpringMvc+Netty源码

    前言 这里普及一下,每个公司都有职别定级系统,阿里也是,技术岗以 P 定级,一般校招 P5, 社招 P6 起.其实阅读源码也是有很多诀窍的,这里分享几点心得: 首先要会用.你要知道这个库是干什么的,掌 ...

  7. C#进阶系列——一步一步封装自己的HtmlHelper组件:BootstrapHelper(三:附源码)

    前言:之前的两篇封装了一些基础的表单组件,这篇继续来封装几个基于bootstrap的其他组件.和上篇不同的是,这篇的有几个组件需要某些js文件的支持. 本文原创地址:http://www.cnblog ...

  8. Entity Framework在Asp.net MVC中的实现One Context Per Request(附源码)

    上篇中"Entity Framework中的Identity map和Unit of Work模式", 由于EF中的Identity map和Unit of Work模式,EF体现 ...

  9. 构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(6)-Unity 2.x依赖注入by运行时注入[附源码]

    原文:构建ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统(6)-Unity 2.x依赖注入by运行时注入[附源码] Unity 2.x依赖注入(控制反转)IOC,对 ...

随机推荐

  1. 输出一个对象,会默认执行toString()方法

    今天在看编程思想时看到enum知识点时发现了这个小问题(可能我基础太差了) 如图 然后就一步一步的跟进源码发现了其中的奥秘,首先进入println()方法如下图 看图执行了valueOf()方法进行s ...

  2. Swagger+Asp.net WebApi实例

    第一步新建WebApi项目 文件-新建-项目,弹出以下页面 第二步,新建参数项目 第三步 1.自定义输入参数 2.定义公用输出参数 3.定义输出参数 4.定义返回模型 第四步,在webapi项目中新增 ...

  3. js中三种全局变量声明方法

    声明方式一: 使用var(关键字)+变量名(标识符)的方式在function外部声明,即为全局变量,否则在function声明的是局部变量.该方式即为显式声明详细如下: <script> ...

  4. [LeetCode] Minimum Window Subsequence 最小窗口序列

    Given strings S and T, find the minimum (contiguous) substring W of S, so that T is a subsequence of ...

  5. 网易云安全两篇论文入选计算机视觉顶级会议ICCV

    本文由  网易云发布. 10月22日至29日,全球计算机视觉顶尖专家们共聚威尼斯,参加ICCV2017国际计算机视觉大会,就领域内最新成果展开集中研讨,大会论文集也代表了计算机视觉领域最新的发展方向和 ...

  6. IOS开发-UIDynamic(物理仿真)简单使用

    UIDynamic是从IOS7开始引入的一种新技术,隶属于UIKit框架,我们可以认为是一种物理引擎能模拟和仿真现实生活中的物理现象,比如重力,弹性碰撞等. 可以让开发人员远离物理公式的情况下,实现一 ...

  7. JavaScript的作用;JS常见的三种对话框;==和===的区别;函数内部参数数组arguments在函数内部打印实参;JS的误区:没有块级作用域

    JS:客户端(浏览器)脚本语言 弱类型 基于原型 事件驱动 不需要编译(直接运行)   JS的作用:表单验证,减轻服务端的压力 添加页面动画效果  动态更改页面内容  Ajax网络请求 (一)常见的对 ...

  8. Mac下安装oh-my-zsh

    Mac下自带的终端并不好用,当你打开终端的时候是一个白花花的窗口,其实Mac自带几种shell,默认使用的是bash,可以通过 cat /etc/shells 查看几种shell bin/bash / ...

  9. C++Primer学习——动态内存

    静态内存:用来保存static 栈内存:保存非static 智能指针: shared_ptr:允许多个指针指向一个对象 unique_ptr:独占所指对象 weak_ptr:一种弱引用,指向share ...

  10. 17.10.28&29

    28上午 骚猪选讲 28下午 BOZJ 1081 [SCOI2005]超级格雷码 感觉就是一个找规律,然后模拟输出.半天没找到一个比较简便的模拟方法,这份代码是学习网上一位大佬的,很巧妙. 代码: # ...