企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
### 一、前言 后台出现异常如何友好而又高效地回显到前端呢?直接将一堆的错误信息抛给用户界面,显然不合适。 先不考虑代码实现,我们希望是这样的: (1)如果是页面跳转的请求,出现异常了,我们希望跳转到一个异常显示页面,如下: ![](https://box.kancloud.cn/2016-03-15_56e77db839ccd.jpg) 当然,这里的界面不够美观,但是理论是这样的。 (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打印出来: ![](https://box.kancloud.cn/2016-03-15_56e77db8562d4.jpg) 下面,我们根据上面的思路我们来看看代码的实现。因此本文实例包含了异常自定义分装,为了无障碍阅读下文,请猿友移步先看完博主的另外一篇文章:[Java异常封装(自己定义错误码和描述,附源码)](http://blog.csdn.net/u013142781/article/details/50609488)。 ### 二、实例详解 本实例使用的环境 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异常封装(自己定义错误码和描述,附源码)](http://blog.csdn.net/u013142781/article/details/50609488)。 另外,需要在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](http://localhost:8080/web_exception_project/exceptionForPageJumps.jhtml)的结果: ![](https://box.kancloud.cn/2016-03-15_56e77db839ccd.jpg) (2)如果ajax请求过程中出现异常,访问[http://localhost:8080/web_exception_project/index.jhtml](http://localhost:8080/web_exception_project/index.jhtml),然后,点击业务异常按钮结果: ![](https://box.kancloud.cn/2016-03-15_56e77db8562d4.jpg) 点击其他异常按钮结果: ![](https://box.kancloud.cn/2016-03-15_56e77db8846b0.jpg) (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://localhost:8080/web_exception_project/123456.jhtml),结果如下: ![](https://box.kancloud.cn/2016-03-15_56e77db8a296d.jpg) ### 三、本工程源码下载 [http://download.csdn.net/detail/u013142781/9424969](http://download.csdn.net/detail/u013142781/9424969)